package handler import ( "net/http" "os" "path/filepath" "strings" "codeberg.org/VARASYS/ZDDC/zddc/internal/config" ) // Custom CSS pipeline. Lets an operator drop `.profile.css` (or the // legacy `.admin.css`) at the deployment root and have it picked up // automatically as styling for the profile page. Previously lived // alongside the retired form editor; kept because the profile page // still relies on it. const ( profileCustomCSSName = ".profile.css" adminCustomCSSName = ".admin.css" // legacy fallback ) // hasCustomProfileCSS reports whether /.profile.css (or the // legacy .admin.css) exists. The profile template uses this to decide // whether to inject the tag. func hasCustomProfileCSS(fsRoot string) bool { if _, err := os.Stat(filepath.Join(fsRoot, profileCustomCSSName)); err == nil { return true } if _, err := os.Stat(filepath.Join(fsRoot, adminCustomCSSName)); err == nil { return true } return false } // profileAssetsPathPrefix is the URL prefix for admin static assets. // Lived at /.profile/zddc/assets/ during the form-editor era; renamed // once the form editor retired. The only consumer is the profile page, // which emits a to /custom.css when an operator has placed one // at root. const profileAssetsPathPrefix = ProfilePathPrefix + "/assets" // serveProfileAssets handles GET /.profile/assets/. V1 only // ships `custom.css` (passthrough of /.profile.css when // present, falling back to /.admin.css); other paths return // 404 so we don't accidentally expose arbitrary files. The caller // (profilehandler.go) has already gated on admin scope. func serveProfileAssets(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 } rest := strings.TrimPrefix(r.URL.Path, profileAssetsPathPrefix+"/") switch rest { case "custom.css": path := filepath.Join(cfg.Root, profileCustomCSSName) if fi, err := os.Stat(path); err != nil || fi.IsDir() { path = filepath.Join(cfg.Root, adminCustomCSSName) if fi, err := os.Stat(path); err != nil || fi.IsDir() { http.NotFound(w, r) return } } w.Header().Set("Content-Type", "text/css; charset=utf-8") w.Header().Set("Cache-Control", "no-cache") http.ServeFile(w, r, path) default: http.NotFound(w, r) } }