// Copyright 2023 wanderer // SPDX-License-Identifier: AGPL-3.0-only package handlers import ( "context" "net/http" "git.dotya.ml/mirre-mt/pcmt/ent" moduser "git.dotya.ml/mirre-mt/pcmt/modules/user" "github.com/labstack/echo-contrib/session" "github.com/labstack/echo/v4" ) func ManageUsers(client *ent.Client) echo.HandlerFunc { //nolint:gocognit return func(c echo.Context) error { addHeaders(c) sess, _ := session.Get(setting.SessionCookieName(), c) if sess == nil { c.Logger().Info("No session found, unauthorised.") return renderErrorPage( c, http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized), "No session found, please log in", ) } uname := sess.Values["username"] if uname == nil { c.Logger().Debugf("%d - %s", http.StatusUnauthorized, "session expired or invalid") return renderErrorPage( c, http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized)+": Log in again", "Session expired, log in again.", ) } log.Info("gorilla session", "username", sess.Values["username"].(string)) username := sess.Values["username"].(string) var u moduser.User ctx := context.WithValue(context.Background(), moduser.CtxKey{}, slogger) if usr, err := moduser.QueryUser(ctx, client, username); err == nil && usr != nil { u.ID = usr.ID u.Username = usr.Username u.IsAdmin = usr.IsAdmin u.CreatedAt = usr.CreatedAt u.IsActive = usr.IsActive u.IsLoggedIn = true } else { c.Logger().Error(http.StatusText(http.StatusInternalServerError) + " - " + err.Error()) return renderErrorPage( c, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), err.Error(), ) } if !u.IsAdmin { c.Logger().Debug("this is a restricted endpoint") status := http.StatusUnauthorized msg := http.StatusText(status) return renderErrorPage( c, status, msg+": You should not be here", "Restricted endpoint", ) } data := make(map[string]any) flash := sess.Values["flash"] path := c.Request().URL.Path if path == "/manage/users/new" { p := page{ AppName: setting.AppName(), AppVer: appver, Title: "Manage Users - New User", CSRF: c.Get("csrf").(string), DevelMode: setting.IsDevel(), Current: "manage-users-new", User: u, } if flash != nil { data["flash"] = flash.(string) delete(sess.Values, "flash") _ = sess.Save(c.Request(), c.Response()) } err := c.Render( http.StatusOK, "manage/user-new.tmpl", p, ) if err != nil { return renderErrorPage( c, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), err.Error(), ) } return nil } var allUsers []*moduser.User if users, err := moduser.ListAll(ctx, client); err == nil && users != nil { for _, u := range users { usr := &moduser.User{ Username: u.Username, Email: u.Email, ID: u.ID, IsActive: u.IsActive, IsAdmin: u.IsAdmin, CreatedAt: u.CreatedAt, UpdatedAt: u.UpdatedAt, } allUsers = append(allUsers, usr) } } else { c.Logger().Error(http.StatusText(http.StatusInternalServerError) + " - " + err.Error()) return renderErrorPage( c, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), err.Error(), ) } data["allusers"] = allUsers p := page{ AppName: setting.AppName(), AppVer: appver, Title: "Manage Users", CSRF: c.Get("csrf").(string), DevelMode: setting.IsDevel(), Current: "manage-users", User: u, Data: data, } if flash != nil { data["flash"] = flash.(string) delete(sess.Values, "flash") _ = sess.Save(c.Request(), c.Response()) } err := c.Render( http.StatusOK, "manage/user.tmpl", p, ) if err != nil { return renderErrorPage( c, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), err.Error(), ) } return nil } } func CreateUser(client *ent.Client) echo.HandlerFunc { //nolint:gocognit return func(c echo.Context) error { addHeaders(c) sess, _ := session.Get(setting.SessionCookieName(), c) if sess == nil { c.Logger().Info("No session found, unauthorised.") return renderErrorPage( c, http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized), "No session found, please log in", ) } uname := sess.Values["username"] if uname == nil { c.Logger().Debugf("%d - %s", http.StatusUnauthorized, "session expired or invalid") return renderErrorPage( c, http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized)+": Log in again", "Session expired, log in again.", ) } log.Info("gorilla session", "username", sess.Values["username"].(string)) username := sess.Values["username"].(string) var u moduser.User ctx := context.WithValue(context.Background(), moduser.CtxKey{}, slogger) if usr, err := moduser.QueryUser(ctx, client, username); err == nil && usr != nil { u.ID = usr.ID u.Username = usr.Username u.IsAdmin = usr.IsAdmin u.CreatedAt = usr.CreatedAt u.IsActive = usr.IsActive u.IsLoggedIn = true } else { c.Logger().Error(http.StatusText(http.StatusInternalServerError) + " - " + err.Error()) return renderErrorPage( c, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError), err.Error(), ) } if !u.IsAdmin { c.Logger().Debug("this is a restricted endpoint") status := http.StatusUnauthorized msg := http.StatusText(status) return renderErrorPage( c, status, msg+": You should not be here", "Restricted endpoint", ) } uc := new(userCreate) if err := c.Bind(uc); err != nil { return renderErrorPage( c, http.StatusBadRequest, http.StatusText(http.StatusBadRequest), err.Error(), ) } if uc.Username == "" || uc.Password == "" || uc.RepeatPassword == "" || uc.Password != uc.RepeatPassword { c.Logger().Error("username or password not set, returning to /manage/users/new") msg := "Error: both username and password need to be set" if uc.Password != uc.RepeatPassword { msg += "; password needs to be passed the same twice" } data := make(map[string]any) data["flash"] = msg data["form"] = uc return c.Render( http.StatusBadRequest, "manage/user-new.tmpl", page{ AppName: setting.AppName(), AppVer: appver, Title: "Manage Users - New User", DevelMode: setting.IsDevel(), Current: "manage-user-new", Data: data, }, ) } var msg string usr, err := moduser.CreateUser(ctx, client, uc.Email, uc.Username, uc.Password, uc.IsAdmin) if err == nil && usr != nil { msg = "created user '" + usr.Username + "'!" sess.Values["flash"] = msg _ = sess.Save(c.Request(), c.Response()) return c.Redirect(http.StatusSeeOther, "/manage/users") } if ent.IsNotSingular(err) { c.Logger().Error("user exists") msg = "Error: user already exists: " + err.Error() } else { msg = "Error: " + err.Error() } data := make(map[string]any) data["flash"] = msg data["form"] = uc return c.Render( http.StatusInternalServerError, "manage/user-new.tmpl", page{ AppName: setting.AppName(), AppVer: appver, Title: "Manage Users", DevelMode: setting.IsDevel(), Current: "manage-user", Data: data, }, ) } }