Antonio Mika
·
2026-10-25
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 *Config) {
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 router.SetUser(r, user.Name)
47
48 ff, err := cfg.DB.FindFeature(user.ID, "plus")
49 if err != nil || (ff != nil && !ff.IsValid()) {
50 cfg.Logger.Error("pico+ required for auto-forms", "username", props.Username)
51 http.Error(w, "pico+ required for auto-forms", http.StatusPaymentRequired)
52 return
53 }
54
55 err = cfg.DB.InsertFormEntry(user.ID, formName, formValues)
56 if err != nil {
57 cfg.Logger.Error("failed to save form data", "err", err)
58 http.Error(w, "failed to save form data", http.StatusInternalServerError)
59 return
60 }
61
62 serveAutoFormSubmitted(w, r, cfg)
63}
64
65type FormData struct {
66 Error string
67}
68
69func serveAutoFormSubmitted(w http.ResponseWriter, r *http.Request, cfg *Config) {
70 errorMsg := r.URL.Query().Get("error")
71 data := loginFormData{
72 Error: errorMsg,
73 }
74
75 w.WriteHeader(http.StatusUnprocessableEntity)
76
77 ts, err := router.RenderTemplate(staticDir, []string{cfg.StaticPath("html/auto_form.page.tmpl")})
78 if err != nil {
79 cfg.Logger.Error("could not render auto form template", "err", err.Error())
80 http.Error(w, "Server error", http.StatusInternalServerError)
81 return
82 }
83
84 err = ts.Execute(w, data)
85 if err != nil {
86 cfg.Logger.Error("could not execute login template", "err", err.Error())
87 http.Error(w, "Server error", http.StatusInternalServerError)
88 }
89}