@@ 1,150 0,0 @@
-package web
-
-import (
- "net/http"
- "net/url"
- "sort"
- "strings"
-
- "sourcecraft.dev/bigbes/sr-ht-core/auth"
- "sourcecraft.dev/bigbes/sr-ht-core/config"
- "github.com/vaughan0/go-ini"
-
- "sourcecraft.dev/bigbes/sr-ht-dolt/authn"
-)
-
-// serviceName is our own service key in the shared config and nav.
-const serviceName = "dolt.sr.ht"
-
-// networkOrder is upstream core.sr.ht's fixed nav ordering (flask.py
-// _network_order). Services present in the config but not listed here sort
-// after these, alphabetically. paste.sr.ht and pages.sr.ht are excluded from
-// the network entirely (they have no user-facing nav), mirroring _network.
-var networkOrder = []string{
- "hub.sr.ht",
- "git.sr.ht",
- "hg.sr.ht",
- "lists.sr.ht",
- "todo.sr.ht",
- "builds.sr.ht",
- "man.sr.ht",
- "meta.sr.ht",
-}
-
-var networkExcluded = map[string]bool{
- "paste.sr.ht": true,
- "pages.sr.ht": true,
-}
-
-// navEntry is one service link in the shared nav.
-type navEntry struct {
- // Name is the leading segment of the service (e.g. "git" for git.sr.ht),
- // rendered as the link text exactly as upstream nav.html does.
- Name string
- // Site is the full service key (e.g. "git.sr.ht").
- Site string
- // Origin is the external URL for the service.
- Origin string
- // Active is true for our own service, which highlights it in the nav.
- Active bool
-}
-
-// basePage is the chrome model shared by every rendered page. Handler view
-// structs embed it so templates reference its fields directly (e.g. .SiteName).
-type basePage struct {
- Title string
- Site string
- SiteLabel string
- SiteName string
- Environment string
- ShowEnvBanner bool
- Network []navEntry
- MetaOrigin string
- SelfOrigin string
- LoginURL string
- LogoutURL string
- StyleHref string
- // CurrentUser is the authenticated caller, or nil for an anonymous request.
- CurrentUser *auth.AuthContext
-}
-
-// buildNetwork returns the ordered nav entries for conf: every section ending
-// ".sr.ht" that is not excluded, ordered by networkOrder then alphabetically
-// for unknown services. Origins are resolved externally via config.GetOrigin.
-func buildNetwork(conf ini.File) []navEntry {
- var sites []string
- for section := range conf {
- if !strings.HasSuffix(section, ".sr.ht") || networkExcluded[section] {
- continue
- }
- sites = append(sites, section)
- }
-
- orderIndex := func(s string) int {
- for i, n := range networkOrder {
- if n == s {
- return i
- }
- }
- return len(networkOrder) // unknown services sort after the fixed set
- }
- sort.Slice(sites, func(i, j int) bool {
- oi, oj := orderIndex(sites[i]), orderIndex(sites[j])
- if oi != oj {
- return oi < oj
- }
- return sites[i] < sites[j] // stable, alphabetical among unknowns
- })
-
- entries := make([]navEntry, 0, len(sites))
- for _, s := range sites {
- entries = append(entries, navEntry{
- Name: strings.SplitN(s, ".", 2)[0],
- Site: s,
- Origin: config.GetOrigin(conf, s, true),
- Active: s == serviceName,
- })
- }
- return entries
-}
-
-// newBasePage builds the chrome model for a request. Title is the per-page
-// <title>; the caller sets any page-specific fields on its own view struct.
-func (a *app) newBasePage(r *http.Request, title string) basePage {
- conf := a.cfg.Conf
- env := config.GetString(conf, "sr.ht", "environment", "development")
- self := config.GetOrigin(conf, serviceName, true)
- meta := config.GetOrigin(conf, "meta.sr.ht", true)
-
- return basePage{
- Title: title,
- Site: serviceName,
- SiteLabel: strings.SplitN(serviceName, ".", 2)[0],
- SiteName: config.GetString(conf, "sr.ht", "site-name", "sr.ht"),
- Environment: env,
- ShowEnvBanner: env != "production",
- Network: buildNetwork(conf),
- MetaOrigin: meta,
- SelfOrigin: self,
- LoginURL: loginURL(self, meta, r),
- LogoutURL: logoutURL(self, meta),
- StyleHref: a.styleHref,
- CurrentUser: authn.CallerFromContext(r.Context()),
- }
-}
-
-// loginURL mirrors core.sr.ht flask.py: {meta}/login?return_to={self+full_path}.
-// full_path is the request path with its query string, so login round-trips the
-// user back to exactly where they were.
-func loginURL(self, meta string, r *http.Request) string {
- returnTo := self + r.URL.EscapedPath()
- if r.URL.RawQuery != "" {
- returnTo += "?" + r.URL.RawQuery
- }
- return meta + "/login?return_to=" + url.QueryEscape(returnTo)
-}
-
-// logoutURL mirrors core.sr.ht flask.py: {meta}/logout?return_to={self origin}.
-func logoutURL(self, meta string) string {
- return meta + "/logout?return_to=" + url.QueryEscape(self)
-}