Files
musenalm/pages/user_create.go
2025-05-23 16:26:03 +02:00

137 lines
4.0 KiB
Go

package pages
import (
"fmt"
"github.com/Theodor-Springmann-Stiftung/musenalm/app"
"github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels"
"github.com/Theodor-Springmann-Stiftung/musenalm/middleware"
"github.com/Theodor-Springmann-Stiftung/musenalm/pagemodels"
"github.com/Theodor-Springmann-Stiftung/musenalm/templating"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/router"
)
const (
URL_USER_CREATE = "/user/new/"
PATH_VALUE_ROLE = "role"
TEMPLATE_USER_CREATE = "/user/new/"
)
func init() {
ucp := &UserCreatePage{
StaticPage: pagemodels.StaticPage{
Name: pagemodels.P_USER_CREATE_NAME,
Layout: "blank",
Template: TEMPLATE_USER_CREATE,
URL: URL_USER_CREATE,
},
}
app.Register(ucp)
}
type UserCreatePage struct {
pagemodels.StaticPage
}
func (p *UserCreatePage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error {
rg := router.Group(URL_USER_CREATE)
rg.BindFunc(middleware.HasToken())
rg.GET("{"+PATH_VALUE_ROLE+"}", p.GET(engine, app))
rg.POST("{"+PATH_VALUE_ROLE+"}", p.POST(engine, app))
return nil
}
func (p *UserCreatePage) GET(engine *templating.Engine, app core.App) HandleFunc {
return func(e *core.RequestEvent) error {
role := e.Request.PathValue("role")
if role != "User" && role != "Editor" && role != "Admin" {
return engine.Response404(e, fmt.Errorf("invalid role: %s", role), nil)
}
// TODO: check access token
data := make(map[string]any)
nonce, token, err := CSRF_CACHE.GenerateTokenBundle()
if err != nil {
return engine.Response500(e, err, data)
}
data["role"] = role
data["csrf_nonce"] = nonce
data["csrf_token"] = token
return engine.Response200(e, p.Template, data, p.Layout)
}
}
func InvalidSignupResponse(engine *templating.Engine, e *core.RequestEvent, error string) error {
data := make(map[string]any)
data["error"] = error
nonce, token, err := CSRF_CACHE.GenerateTokenBundle()
if err != nil {
return engine.Response500(e, err, data)
}
data["csrf_nonce"] = nonce
data["csrf_token"] = token
str, err := engine.RenderToString(e, data, TEMPLATE_USER_CREATE, "blank")
if err != nil {
return engine.Response500(e, err, data)
}
return e.HTML(400, str)
}
func (p *UserCreatePage) POST(engine *templating.Engine, app core.App) HandleFunc {
return func(e *core.RequestEvent) error {
role := e.Request.PathValue("role")
if role != "User" && role != "Editor" && role != "Admin" {
return engine.Response404(e, fmt.Errorf("invalid role: %s", role), nil)
}
// TODO: check access token
data := make(map[string]any)
data["role"] = role
formdata := struct {
Username string `form:"username"`
Password string `form:"password"`
PasswordRepeat string `form:"password_repeat"`
Name string `form:"name"`
CsrfNonce string `form:"csrf_nonce"`
CsrfToken string `form:"csrf_token"`
}{}
if err := e.BindBody(&formdata); err != nil {
return engine.Response500(e, err, data)
}
data["formdata"] = formdata
if _, err := CSRF_CACHE.ValidateTokenBundle(formdata.CsrfNonce, formdata.CsrfToken); err != nil {
return InvalidSignupResponse(engine, e, "CSRF-Token ungültig.")
}
if formdata.Username == "" || formdata.Password == "" || formdata.Name == "" {
return InvalidSignupResponse(engine, e, "Bitte alle Felder ausfüllen.")
}
if formdata.Password != formdata.PasswordRepeat {
return InvalidSignupResponse(engine, e, "Passwörter stimmen nicht überein.")
}
_, err := app.FindAuthRecordByEmail(dbmodels.USERS_TABLE, formdata.Username)
if err == nil {
return InvalidSignupResponse(engine, e, "Benutzer existiert bereits.")
}
user, err := dbmodels.CreateUser(app, formdata.Username, formdata.Password, formdata.Name, role)
if err != nil {
return InvalidSignupResponse(engine, e, fmt.Sprintf("Fehler beim Erstellen des Benutzers: %s", err.Error()))
}
data["user"] = user
return engine.Response200(e, p.Template, data, p.Layout)
}
}