repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

pico / pkg / apps / pgs
Eric Bower  ·  2026-03-10

auto_form.go

 1package pgs
 2
 3import (
 4	"net/http"
 5
 6	"github.com/picosh/pico/pkg/shared/router"
 7)
 8
 9func handleAutoForm(w http.ResponseWriter, r *http.Request, cfg *PgsConfig) {
10	formName := r.PathValue("fname")
11	if r.Method != http.MethodPost {
12		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
13		return
14	}
15
16	err := r.ParseForm()
17	if err != nil {
18		cfg.Logger.Error("failed to parse auto form", "err", err)
19		http.Error(w, "failed to parse auto form", http.StatusBadRequest)
20		return
21	}
22
23	formValues := make(map[string]interface{})
24	for key, values := range r.PostForm {
25		if len(values) == 1 {
26			formValues[key] = values[0]
27		} else if len(values) > 1 {
28			formValues[key] = values
29		}
30	}
31
32	subdomain := router.GetSubdomainFromRequest(r, cfg.Domain, cfg.TxtPrefix)
33	props, err := router.GetProjectFromSubdomain(subdomain)
34	if err != nil {
35		cfg.Logger.Error("could not get project from subdomain", "subdomain", subdomain, "err", err)
36		http.Error(w, "not found", http.StatusNotFound)
37		return
38	}
39
40	user, err := cfg.DB.FindUserByName(props.Username)
41	if err != nil {
42		cfg.Logger.Error("user not found", "username", props.Username)
43		http.Error(w, "not found", http.StatusNotFound)
44		return
45	}
46
47	ff, err := cfg.DB.FindFeature(user.ID, "plus")
48	if err != nil || (ff != nil && !ff.IsValid()) {
49		cfg.Logger.Error("pico+ required for auto-forms", "username", props.Username)
50		http.Error(w, "pico+ required for auto-forms", http.StatusPaymentRequired)
51		return
52	}
53
54	err = cfg.DB.InsertFormEntry(user.ID, formName, formValues)
55	if err != nil {
56		cfg.Logger.Error("failed to save form data", "err", err)
57		http.Error(w, "failed to save form data", http.StatusInternalServerError)
58		return
59	}
60
61	serveAutoFormSubmitted(w, r, cfg)
62}
63
64type FormData struct {
65	Error string
66}
67
68func serveAutoFormSubmitted(w http.ResponseWriter, r *http.Request, cfg *PgsConfig) {
69	errorMsg := r.URL.Query().Get("error")
70	data := loginFormData{
71		Error: errorMsg,
72	}
73
74	w.WriteHeader(http.StatusUnprocessableEntity)
75
76	ts, err := renderTemplate(cfg, []string{cfg.StaticPath("html/auto_form.page.tmpl")})
77	if err != nil {
78		cfg.Logger.Error("could not render auto form template", "err", err.Error())
79		http.Error(w, "Server error", http.StatusInternalServerError)
80		return
81	}
82
83	err = ts.Execute(w, data)
84	if err != nil {
85		cfg.Logger.Error("could not execute login template", "err", err.Error())
86		http.Error(w, "Server error", http.StatusInternalServerError)
87	}
88}