Files
musenalm/controllers/user_management_access.go
Simon Martens 9f7306526f qr -> ajax
2025-05-30 03:01:38 +02:00

136 lines
4.3 KiB
Go

package controllers
import (
"fmt"
"time"
"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"
"github.com/pocketbase/pocketbase/tools/types"
)
const (
URL_USER_MANAGEMENT_ACCESS = "/user/management/access/"
TEMPLATE_USER_MANAGEMENT_ACCESS = "/user/management/access/"
)
func init() {
ump := &UserManagementAccessPage{
StaticPage: pagemodels.StaticPage{
Name: pagemodels.P_USER_MGMT_ACCESS_NAME,
Layout: "blankfooter",
Template: TEMPLATE_USER_MANAGEMENT_ACCESS,
URL: URL_USER_MANAGEMENT_ACCESS,
},
}
app.Register(ump)
}
type UserManagementAccessPage struct {
pagemodels.StaticPage
}
func (p *UserManagementAccessPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error {
rg := router.Group(URL_USER_MANAGEMENT_ACCESS)
rg.BindFunc(middleware.IsAdmin())
rg.GET("{"+PATH_VALUE_ROLE+"}", p.GET(engine, app))
rg.POST("{"+PATH_VALUE_ROLE+"}", p.POST(engine, app))
return nil
}
func (p *UserManagementAccessPage) 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)
}
path_access := URL_USER_CREATE + role
record, err := app.FindFirstRecordByData(dbmodels.ACCESS_TOKENS_TABLE, dbmodels.ACCESS_TOKENS_URL_FIELD, path_access)
var access_token *dbmodels.AccessToken
if err != nil {
token, err := dbmodels.CreateAccessToken(app, "", path_access, 7*24*time.Hour)
if err != nil {
return engine.Response500(e, err, nil)
}
access_token = token
} else {
access_token = dbmodels.NewAccessToken(record)
access_token.SetExpires(types.NowDateTime().Add(7 * 24 * time.Hour))
if err := app.Save(access_token); err != nil {
return engine.Response500(e, err, nil)
}
}
// TODO: check if access token exists, if not generate
data := make(map[string]any)
data["role"] = role
data["access_url"] = "https://musenalm.de" + path_access + "?token=" + access_token.Token()
data["relative_url"] = path_access + "?token=" + access_token.Token()
data["validUntil"] = access_token.Expires().Time().Local().Format("02.01.2006 15:04")
req := templating.NewRequest(e)
data["csrf_token"] = req.Session().Token
SetRedirect(data, e)
return engine.Response200(e, p.Template, data, p.Layout)
}
}
func (p *UserManagementAccessPage) 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)
}
formdata := struct {
CSRF string `json:"csrf_token" form:"csrf_token"`
}{}
if err := e.BindBody(&formdata); err != nil {
return engine.Response500(e, fmt.Errorf("invalid form data: %w", err), nil)
}
req := templating.NewRequest(e)
if err := req.CheckCSRF(formdata.CSRF); err != nil {
return engine.Response500(e, fmt.Errorf("invalid CSRF token: %w", err), nil)
}
path_access := URL_USER_CREATE + role
record, err := app.FindFirstRecordByData(dbmodels.ACCESS_TOKENS_TABLE, dbmodels.ACCESS_TOKENS_URL_FIELD, path_access)
if err == nil {
go app.Delete(record)
}
token, err := dbmodels.CreateAccessToken(app, "", path_access, 7*24*time.Hour)
if err != nil {
return engine.Response500(e, err, nil)
}
data := make(map[string]any)
data["role"] = role
data["access_url"] = "https://musenalm.de" + path_access + "?token=" + token.Token()
data["relative_url"] = path_access + "?token=" + token.Token()
data["validUntil"] = token.Expires().Time().Format("02.01.2006 15:04")
data["csrf_token"] = req.Session().Token
SetRedirect(data, e)
return engine.Response200(e, p.Template, data, p.Layout)
}
}
func SetRedirect(data map[string]any, e *core.RequestEvent) {
redirect_url := e.Request.URL.Query().Get("redirectTo")
if redirect_url != "" {
data["redirect_url"] = redirect_url
}
}