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)
}