56 lines
1.8 KiB
Go
56 lines
1.8 KiB
Go
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` at the
|
|
// deployment root and have it picked up automatically as styling for
|
|
// the profile page.
|
|
|
|
const profileCustomCSSName = ".profile.css"
|
|
|
|
// hasCustomProfileCSS reports whether <fsRoot>/.profile.css exists.
|
|
// The profile template uses this to decide whether to inject the
|
|
// <link> tag.
|
|
func hasCustomProfileCSS(fsRoot string) bool {
|
|
_, err := os.Stat(filepath.Join(fsRoot, profileCustomCSSName))
|
|
return err == nil
|
|
}
|
|
|
|
// profileAssetsPathPrefix is the URL prefix for admin static assets.
|
|
// The only consumer is the profile page, which emits a <link> to
|
|
// /custom.css when an operator has placed one at root.
|
|
const profileAssetsPathPrefix = ProfilePathPrefix + "/assets"
|
|
|
|
// serveProfileAssets handles GET /.profile/assets/<file>. V1 only
|
|
// ships `custom.css` (passthrough of <root>/.profile.css when present);
|
|
// 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() {
|
|
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)
|
|
}
|
|
}
|