package handler import ( "html/template" "net/http" "codeberg.org/VARASYS/ZDDC/zddc/internal/config" ) // profileView is the data passed to the profile template. type profileView struct { AccessView ProfilePathPrefix string AssetsPathPrefix string HasCustomCSS bool HasEditableSubtrees bool EditableParentChoices []treeEntry // AdminSubtrees filtered to CanEdit; used as create-project parents } // serveProfilePage renders the universal profile page at GET /.profile/. // Reachable to anyone (anonymous included); admin / super-admin sections // are conditionally rendered server-side based on the caller's effective // access — non-admin HTML contains zero admin markup. func serveProfilePage(cfg config.Config, w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { w.Header().Set("Allow", "GET") http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return } view := profileView{ AccessView: enumerateAccess(cfg, EmailFromContext(r)), ProfilePathPrefix: ProfilePathPrefix, AssetsPathPrefix: zddcAssetsPathPrefix, HasCustomCSS: hasCustomProfileCSS(cfg.Root), } for _, t := range view.AdminSubtrees { if t.CanEdit { view.EditableParentChoices = append(view.EditableParentChoices, t) } } view.HasEditableSubtrees = len(view.EditableParentChoices) > 0 w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Cache-Control", "no-store") if err := profileTemplate.Execute(w, view); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } // profileTemplate is the html/template for the profile page. Single page, // three layered blocks (universal / admin / super-admin), inline styles // using the same custom-property naming as the editor so a future merge // with shared/base.css stays trivial. One inline IIFE handles theme, // localStorage, and the create-project AJAX submit. var profileTemplate = template.Must(template.New("profile").Parse(` zddc-server — profile {{ if .HasCustomCSS }}{{ end }}

Your profile

Identity

{{ if .Email }}

Signed in as {{ .Email }}.

{{ else }}

Not signed in. The server reads identity from the {{ .EmailHeader }} header. If you expected to be authenticated, your reverse proxy or SSO gateway is not forwarding it.

{{ end }}

Configured email header: {{ .EmailHeader }}

Effective access

Super-admin: {{ if .IsSuperAdmin }}yes{{ else }}no{{ end }}

Visible projects

{{ if .Projects }} {{ else }}

No projects accessible.

{{ end }} {{ if .HasAnyAdminScope }}

Subtrees you administer

{{ if .AdminSubtrees }} {{ else }}

None.

{{ end }} {{ end }}

Theme

Applies to every ZDDC tool you open in this browser. Stored in localStorage["zddc-theme"].

Local storage

Browser-side state used by the ZDDC tools at this origin. The profile page can read and write it for you.

KeyValueBytes
{{ if .HasAnyAdminScope }}

Editable .zddc files

Open the form-based editor for any subtree you administer.

{{ if .HasEditableSubtrees }} {{ else }}

No .zddc files within your edit authority. Subtree admins cannot edit the file that grants their own authority — only an admin from a higher level can.

{{ end }}

Create new project folder

Creates a directory under the chosen parent. If you fill in any of title / allow / deny / admins, a starter .zddc is also written; otherwise the directory is empty and inherits ACL from its ancestors.

ACL — Allow (optional)

ACL — Deny (optional)

Admins (optional)

{{ end }} {{ if .IsSuperAdmin }}

Server config

Effective config from environment variables. Read-only.

loading…

Logs level:

loading…

whoami

Headers as they arrived at the binary. Useful for debugging SSO header passthrough.

loading…
{{ end }} `))