Caddy module to require at-proto authentication and restrict routes to DIDs
2

Configure Feed

Select the types of activity you want to include in your feed.

at main 2.1 kB View raw
1package ui 2 3import ( 4 "embed" 5 "fmt" 6 "html/template" 7 "io" 8 "os" 9) 10 11//go:embed templates/login.html templates/forbidden.html 12var embeddedTemplates embed.FS 13 14// Config holds user overrides for UI templates. 15type Config struct { 16 LoginTemplatePath string `json:"login_template_path,omitempty"` 17 ForbiddenTemplatePath string `json:"forbidden_template_path,omitempty"` 18} 19 20// Renderer handles rendering of HTML pages. 21type Renderer struct { 22 login *template.Template 23 forbidden *template.Template 24} 25 26// NewRenderer initializes a new template renderer, loading defaults and user overrides. 27func NewRenderer(config Config) (*Renderer, error) { 28 r := &Renderer{} 29 30 // Helper to load or fallback 31 load := func(userPath, defaultName string) (*template.Template, error) { 32 var tmplStr string 33 var b []byte 34 var err error 35 36 if userPath != "" { 37 b, err = os.ReadFile(userPath) 38 if err != nil { 39 return nil, fmt.Errorf("failed to read custom template %s: %w", userPath, err) 40 } 41 tmplStr = string(b) 42 } else { 43 b, err = embeddedTemplates.ReadFile("templates/" + defaultName) 44 if err != nil { 45 // Should not happen if embedded correctly 46 return nil, fmt.Errorf("failed to read embedded template %s: %w", defaultName, err) 47 } 48 tmplStr = string(b) 49 } 50 return template.New(defaultName).Parse(tmplStr) 51 } 52 53 var err error 54 if r.login, err = load(config.LoginTemplatePath, "login.html"); err != nil { 55 return nil, err 56 } 57 if r.forbidden, err = load(config.ForbiddenTemplatePath, "forbidden.html"); err != nil { 58 return nil, err 59 } 60 61 return r, nil 62} 63 64// LoginData is the context for login.html 65type LoginData struct { 66 AppName string 67 Error string 68 Redirect string 69 LoginURL string 70} 71 72// ForbiddenData is the context for forbidden.html 73type ForbiddenData struct { 74 AppName string 75 DID string 76 Handle string 77 LogoutURL string 78} 79 80func (r *Renderer) RenderLogin(w io.Writer, data LoginData) error { 81 return r.login.Execute(w, data) 82} 83 84func (r *Renderer) RenderForbidden(w io.Writer, data ForbiddenData) error { 85 return r.forbidden.Execute(w, data) 86}