package web import ( "net/http" "sourcecraft.dev/bigbes/sr-ht-ecore/chrome" "sourcecraft.dev/bigbes/sr-ht-spec/authn" ) // viewData is the root value every template is executed against. // // chrome.Page is embedded rather than copied field by field, so the shared // partials — "srht-nav", "srht-env-banner" — find the fields they read on the // dot they are handed, and a field ecore adds later arrives here without an // edit. The page's own payload lives under Data and is reached as // {{.Data.Something}}, which is what keeps a page from shadowing a chrome // field: a page wanting a "Username" of its own puts it in its payload, where // it cannot silently replace the one the login block reads. type viewData struct { chrome.Page // Data is the page's own payload. Data any } // view builds the frame for one request: the shared chrome plus a title. // // The username handed to the chrome is the *authoritative* identity, not // whatever the cookie said: on this instance a logged-in human who is not the // owner resolves to anonymous, so the nav offers them a login rather than // greeting them by a name that grants nothing. An agent's bearer token is not // an identity for the nav either — it never renders a page for itself. func (s *Server) view(r *http.Request, title string) viewData { username := "" if p := authn.PrincipalFromContext(r.Context()); p.IsOwner() { username = p.Owner } return viewData{Page: s.chromeSvc.Page(r, title, username)} } // loginRedirect sends a viewer with no read authority to meta.sr.ht's login, // with return_to pointing back at what they asked for. There is no login flow // of our own — identity is the shared unified-login cookie and nothing else. // // The URL comes from the chrome rather than from a second hand-rolled // concatenation of the meta origin and an escaped return_to: the link in the // nav and the redirect a gate issues must be the same URL, and the cheapest way // to guarantee that is to have exactly one place that builds it. LoginURLFor is // that place — a redirect wants the one field, not a whole page built to be // thrown away. func (s *Server) loginRedirect(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, s.chromeSvc.LoginURLFor(r), http.StatusFound) }