~bigbes/sr-ht-spec

ref: ef7bddf8b3d64cb4c204a064ad73dbacc78443cb sr-ht-spec/web/view.go -rw-r--r-- 2.2 KiB
ef7bddf8 — Eugene Blikh ci: publish the apk into artifacts.sr.ht as well 3 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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)
}