Files

115 lines
3.6 KiB
Go

package editor
import (
"fmt"
"net/http"
"regexp"
"strings"
"git.coffeylabs.org/coffey-labs/hotdog-cms/internal/site"
)
// The analytics wizard and the privacy settings: analytics: and privacy: in
// site.yaml, written as two blocks, the rest of the file left as it was.
// Statistics wait for consent unless the person chooses otherwise, and that
// choice is spelled out in the file.
func (s *Server) apiPrivacy(w http.ResponseWriter, r *http.Request, sess *Session, f *ForgeConfig, id string) {
st, acc, err := s.siteByID(r.Context(), sess, f, id)
if s.signedOut(w, r, err) {
return
}
if err != nil || st == nil {
apiError(w, http.StatusNotFound, "No such site, or you can't open it.")
return
}
branch := r.URL.Query().Get("branch")
if branch == "" {
branch = st.Branch
}
loaded, _, commit, err := s.ws.checkout(sess, f.Kind, st, s.cloneURL(st), branch)
if loaded == nil {
apiError(w, http.StatusBadGateway, "Couldn't load the site: "+trimErr(err))
return
}
p := loaded.Config.Privacy
writeJSON(w, http.StatusOK, map[string]any{
"analytics": loaded.Config.Analytics,
"privacy": map[string]string{"controller": p.Controller, "contact": p.Contact, "updated": p.Updated},
"commit": commit, "branch": branch, "canWrite": acc.Write,
})
}
type privacyRequest struct {
Branch string `json:"branch"`
BaseCommit string `json:"baseCommit"`
Analytics *site.AnalyticsConfig `json:"analytics"`
Privacy map[string]string `json:"privacy"`
}
var emailish = regexp.MustCompile(`^[^@\s]+@[^@\s]+\.[^@\s]+$`)
func (s *Server) privacySave(w http.ResponseWriter, r *http.Request, sess *Session, f *ForgeConfig, st *SiteConfig) {
var req privacyRequest
if !decode(w, r, &req) {
return
}
if req.Branch == "" {
req.Branch = st.Branch
}
if err := req.Analytics.Validate(); err != nil {
apiError(w, http.StatusUnprocessableEntity, "Analytics: "+err.Error())
return
}
if c := strings.TrimSpace(req.Privacy["contact"]); c != "" && !emailish.MatchString(c) {
apiError(w, http.StatusUnprocessableEntity, fmt.Sprintf("%q doesn't look like an email address.", c))
return
}
_, siteDir, _, err := s.ws.checkout(sess, f.Kind, st, s.cloneURL(st), req.Branch)
if siteDir == "" {
s.writeError(w, r, err)
return
}
raw, err := readIn(siteDir, "site.yaml")
if err != nil {
apiError(w, http.StatusBadGateway, "Couldn't read site.yaml.")
return
}
var an map[string]any
if a := req.Analytics; a != nil {
an = map[string]any{"provider": a.Provider}
for k, v := range map[string]string{"domain": a.Domain, "src": a.Src, "url": a.URL, "site_id": a.SiteID, "id": a.ID} {
if v = strings.TrimSpace(v); v != "" {
an[k] = v
}
}
if !a.IsGated() {
an["gated"] = false // counting without asking: a choice, written down
}
}
pv := map[string]any{}
for _, k := range []string{"controller", "contact", "updated"} {
if v := strings.TrimSpace(req.Privacy[k]); v != "" {
pv[k] = v
}
}
out, err := setTopLevel(string(raw), "analytics", an)
if err == nil {
out, err = setTopLevel(out, "privacy", pv)
}
if err != nil {
apiError(w, http.StatusUnprocessableEntity, err.Error())
return
}
target, create := req.Branch, false
if req.Branch == st.Branch {
target, create = s.draftName(r, sess, f, st, "privacy.md"), true
}
commit, err := s.ws.save(sess, f.Kind, st, s.cloneURL(st), req.Branch, target, create, req.BaseCommit, map[string][]byte{repoFile(st, "site.yaml"): []byte(out)}, "Update analytics and privacy settings")
if err != nil {
s.writeError(w, r, err)
return
}
writeJSON(w, http.StatusOK, map[string]any{"branch": target, "commit": commit, "created": create})
}