More improvements to the edit page

This commit is contained in:
Melon 2023-09-08 00:30:03 +01:00
parent 65f77dbe79
commit 498e42ebe8
Signed by: melon
GPG Key ID: 6C9D970C50D26A25
5 changed files with 36 additions and 18 deletions

View File

@ -91,7 +91,8 @@ func normalLoad(startUp startUpConfig, wd string) {
exit_reload.ExitReload("Tulip", func() {}, func() { exit_reload.ExitReload("Tulip", func() {}, func() {
// stop http server // stop http server
srv.Close() _ = srv.Close()
_ = db.Close()
}) })
} }
@ -112,6 +113,7 @@ func checkDbHasUser(db *database.DB) error {
if err != nil { if err != nil {
return fmt.Errorf("failed to start transaction: %w", err) return fmt.Errorf("failed to start transaction: %w", err)
} }
defer tx.Rollback()
if err := tx.HasUser(); err != nil { if err := tx.HasUser(); err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
err := tx.InsertUser("Admin", "admin", "admin", "admin@localhost") err := tx.InsertUser("Admin", "admin", "admin", "admin@localhost")

View File

@ -2,6 +2,7 @@ package database
import ( import (
"database/sql" "database/sql"
"fmt"
"github.com/MrMelon54/pronouns" "github.com/MrMelon54/pronouns"
"github.com/google/uuid" "github.com/google/uuid"
"golang.org/x/text/language" "golang.org/x/text/language"
@ -36,7 +37,8 @@ type UserPatch struct {
Locale language.Tag Locale language.Tag
} }
func (u *UserPatch) ParseFromForm(v url.Values) (err error) { func (u *UserPatch) ParseFromForm(v url.Values) (safeErrs []error) {
var err error
u.Name = v.Get("name") u.Name = v.Get("name")
u.Picture = v.Get("picture") u.Picture = v.Get("picture")
u.Website = v.Get("website") u.Website = v.Get("website")
@ -45,16 +47,16 @@ func (u *UserPatch) ParseFromForm(v url.Values) (err error) {
} else { } else {
u.Pronouns, err = pronouns.FindPronoun(v.Get("pronouns")) u.Pronouns, err = pronouns.FindPronoun(v.Get("pronouns"))
if err != nil { if err != nil {
return err safeErrs = append(safeErrs, fmt.Errorf("invalid pronoun selected"))
} }
} }
if v.Has("reset_birthdate") { if v.Has("reset_birthdate") || v.Get("birthdate") == "" {
u.Birthdate = sql.NullTime{} u.Birthdate = sql.NullTime{}
} else { } else {
u.Birthdate = sql.NullTime{Valid: true} u.Birthdate = sql.NullTime{Valid: true}
u.Birthdate.Time, err = time.Parse(time.DateOnly, v.Get("birthdate")) u.Birthdate.Time, err = time.Parse(time.DateOnly, v.Get("birthdate"))
if err != nil { if err != nil {
return err safeErrs = append(safeErrs, fmt.Errorf("invalid time selected"))
} }
} }
if v.Has("reset_zoneinfo") { if v.Has("reset_zoneinfo") {
@ -62,7 +64,7 @@ func (u *UserPatch) ParseFromForm(v url.Values) (err error) {
} else { } else {
u.ZoneInfo, err = time.LoadLocation(v.Get("zoneinfo")) u.ZoneInfo, err = time.LoadLocation(v.Get("zoneinfo"))
if err != nil { if err != nil {
return err safeErrs = append(safeErrs, fmt.Errorf("invalid timezone selected"))
} }
} }
if v.Has("reset_locale") { if v.Has("reset_locale") {
@ -70,8 +72,8 @@ func (u *UserPatch) ParseFromForm(v url.Values) (err error) {
} else { } else {
u.Locale, err = language.Parse(v.Get("locale")) u.Locale, err = language.Parse(v.Get("locale"))
if err != nil { if err != nil {
return err safeErrs = append(safeErrs, fmt.Errorf("invalid language selected"))
} }
} }
return nil return
} }

View File

@ -35,3 +35,7 @@ func (d *DB) BeginCtx(ctx context.Context) (*Tx, error) {
} }
return &Tx{begin}, err return &Tx{begin}, err
} }
func (d *DB) Close() error {
return d.db.Close()
}

View File

@ -22,16 +22,16 @@
</div> </div>
<div> <div>
<label for="field_website">Website</label> <label for="field_website">Website</label>
<input type="text" name="website" id="field_website" value="{{.User.Picture}}"> <input type="text" name="website" id="field_website" value="{{.User.Website}}">
</div> </div>
<div> <div>
<label for="field_pronouns">Pronouns</label> <label for="field_pronouns">Pronouns</label>
<select name="pronouns" id="field_pronouns"> <select name="pronouns" id="field_pronouns">
<option value="they/them" selected>They/Them</option> <option value="they/them" {{if eq "they/them" .FieldPronoun}}selected{{end}}>They/Them</option>
<option value="he/him">He/Him</option> <option value="he/him" {{if eq "he/him" .FieldPronoun}}selected{{end}}>He/Him</option>
<option value="she/her">She/Her</option> <option value="she/her" {{if eq "she/her" .FieldPronoun}}selected{{end}}>She/Her</option>
<option value="it/its">It/Its</option> <option value="it/its" {{if eq "it/its" .FieldPronoun}}selected{{end}}>It/Its</option>
<option value="one/one's">One/One's</option> <option value="one/one's" {{if eq "one/one's" .FieldPronoun}}selected{{end}}>One/One's</option>
</select> </select>
<label>Reset? <input type="checkbox" name="reset_pronouns"></label> <label>Reset? <input type="checkbox" name="reset_pronouns"></label>
</div> </div>
@ -58,7 +58,7 @@
<option value="{{.Value}}">{{.Label}}</option> <option value="{{.Value}}">{{.Label}}</option>
{{end}} {{end}}
</datalist> </datalist>
<label>Reset? <input type="checkbox" name="reset_zoneinfo"></label> <label>Reset? <input type="checkbox" name="reset_locale"></label>
</div> </div>
<button type="submit">Edit</button> <button type="submit">Edit</button>
</form> </form>

View File

@ -234,6 +234,7 @@ func NewHttpServer(listen, domain string, db *database.DB, privKey []byte, clien
if err := pages.RenderPageTemplate(rw, "edit", map[string]any{ if err := pages.RenderPageTemplate(rw, "edit", map[string]any{
"User": user, "User": user,
"Nonce": lNonce, "Nonce": lNonce,
"FieldPronoun": user.Pronouns.String(),
"ListZoneInfo": lists.ListZoneInfo(), "ListZoneInfo": lists.ListZoneInfo(),
"ListLocale": lists.ListLocale(), "ListLocale": lists.ListLocale(),
}); err != nil { }); err != nil {
@ -243,13 +244,22 @@ func NewHttpServer(listen, domain string, db *database.DB, privKey []byte, clien
r.POST("/edit", hs.RequireAuthentication("403 Forbidden", http.StatusForbidden, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, auth UserAuth) { r.POST("/edit", hs.RequireAuthentication("403 Forbidden", http.StatusForbidden, func(rw http.ResponseWriter, req *http.Request, params httprouter.Params, auth UserAuth) {
if req.ParseForm() != nil { if req.ParseForm() != nil {
rw.WriteHeader(http.StatusBadRequest) rw.WriteHeader(http.StatusBadRequest)
_, _ = rw.Write([]byte("400 Bad Request\n"))
return return
} }
var patch database.UserPatch var patch database.UserPatch
err := patch.ParseFromForm(req.Form) errs := patch.ParseFromForm(req.Form)
if err != nil { if len(errs) > 0 {
rw.WriteHeader(http.StatusBadRequest) rw.WriteHeader(http.StatusBadRequest)
_, _ = fmt.Fprintln(rw, "<!DOCTYPE html>\n<html>\n<body>")
_, _ = fmt.Fprintln(rw, "<p>400 Bad Request: Failed to parse form data, press the back button in your browser, check your inputs and try again.</p>")
_, _ = fmt.Fprintln(rw, "<ul>")
for _, i := range errs {
_, _ = fmt.Fprintf(rw, " <li>%s</li>\n", i)
}
_, _ = fmt.Fprintln(rw, "</ul>")
_, _ = fmt.Fprintln(rw, "</body>\n</html>")
return return
} }
if hs.DbTx(rw, func(tx *database.Tx) error { if hs.DbTx(rw, func(tx *database.Tx) error {
@ -260,7 +270,7 @@ func NewHttpServer(listen, domain string, db *database.DB, privKey []byte, clien
}) { }) {
return return
} }
http.Redirect(rw, req, "/", http.StatusFound) http.Redirect(rw, req, "/edit", http.StatusFound)
})) }))
r.GET("/userinfo", func(rw http.ResponseWriter, req *http.Request, params httprouter.Params) { r.GET("/userinfo", func(rw http.ResponseWriter, req *http.Request, params httprouter.Params) {
token, err := oauthSrv.ValidationBearerToken(req) token, err := oauthSrv.ValidationBearerToken(req)