From 2d206826d63abddd9c787a2474206fea41820b17 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Mon, 11 Mar 2024 22:20:41 -0700 Subject: [PATCH] add(admin): add user --- api/api.go | 1 + api/app-admin-routes.go | 53 ++++++++++++++++++++++++++++++++ api/auth.go | 52 +++++++++++++++++++++++++++++++ templates/pages/admin-users.tmpl | 9 ++++-- 4 files changed, 113 insertions(+), 2 deletions(-) diff --git a/api/api.go b/api/api.go index 278e792..cec0175 100644 --- a/api/api.go +++ b/api/api.go @@ -157,6 +157,7 @@ func (api *API) registerWebAppRoutes(router *gin.Engine) { router.GET("/admin/import", api.authWebAppMiddleware, api.authAdminWebAppMiddleware, api.appGetAdminImport) router.POST("/admin/import", api.authWebAppMiddleware, api.authAdminWebAppMiddleware, api.appPerformAdminImport) router.GET("/admin/users", api.authWebAppMiddleware, api.authAdminWebAppMiddleware, api.appGetAdminUsers) + router.POST("/admin/users", api.authWebAppMiddleware, api.authAdminWebAppMiddleware, api.appUpdateAdminUsers) router.GET("/admin", api.authWebAppMiddleware, api.authAdminWebAppMiddleware, api.appGetAdmin) router.POST("/admin", api.authWebAppMiddleware, api.authAdminWebAppMiddleware, api.appPerformAdminAction) router.POST("/login", api.appAuthLogin) diff --git a/api/app-admin-routes.go b/api/app-admin-routes.go index 59211e2..22cf205 100644 --- a/api/app-admin-routes.go +++ b/api/app-admin-routes.go @@ -54,6 +54,20 @@ type requestAdminImport struct { Type importType `form:"type"` } +type operationType string + +const ( + opUpdate operationType = "UPDATE" + opCreate operationType = "CREATE" +) + +type requestAdminUpdateUser struct { + User string `form:"user"` + Password string `form:"password"` + isAdmin bool `form:"is_admin"` + Operation operationType `form:"operation"` +} + type requestAdminLogs struct { Filter string `form:"filter"` } @@ -225,6 +239,45 @@ func (api *API) appGetAdminUsers(c *gin.Context) { c.HTML(http.StatusOK, "page/admin-users", templateVars) } +func (api *API) appUpdateAdminUsers(c *gin.Context) { + templateVars, _ := api.getBaseTemplateVars("admin-users", c) + + var rAdminUserUpdate requestAdminUpdateUser + if err := c.ShouldBind(&rAdminUserUpdate); err != nil { + log.Error("Invalid URI Bind") + appErrorPage(c, http.StatusNotFound, "Invalid user update") + return + } + + var err error + switch rAdminUserUpdate.Operation { + case opCreate: + err = api.createUser(rAdminUserUpdate.User, rAdminUserUpdate.Password) + case opUpdate: + err = fmt.Errorf("unimplemented") + default: + appErrorPage(c, http.StatusNotFound, "Unknown user operation") + return + + } + + if err != nil { + appErrorPage(c, http.StatusInternalServerError, fmt.Sprintf("Unable to create user: %v", err)) + return + } + + users, err := api.db.Queries.GetUsers(api.db.Ctx) + if err != nil { + log.Error("GetUsers DB Error: ", err) + appErrorPage(c, http.StatusInternalServerError, fmt.Sprintf("GetUsers DB Error: %v", err)) + return + } + + templateVars["Data"] = users + + c.HTML(http.StatusOK, "page/admin-users", templateVars) +} + func (api *API) appGetAdminImport(c *gin.Context) { templateVars, _ := api.getBaseTemplateVars("admin-import", c) diff --git a/api/auth.go b/api/auth.go index 68b01f7..63f8f4f 100644 --- a/api/auth.go +++ b/api/auth.go @@ -460,3 +460,55 @@ func (api *API) rotateAllAuthHashes() error { return nil } + +func (api *API) createUser(username string, rawPassword string) error { + password := fmt.Sprintf("%x", md5.Sum([]byte(rawPassword))) + + if username == "" { + return fmt.Errorf("username can't be empty") + } + + if rawPassword == "" { + return fmt.Errorf("password can't be empty") + } + + hashedPassword, err := argon2.CreateHash(password, argon2.DefaultParams) + if err != nil { + return fmt.Errorf("unable to create hashed password") + } + + // Generate auth hash + rawAuthHash, err := utils.GenerateToken(64) + if err != nil { + return fmt.Errorf("unable to create token for user") + } + + // Get current users + currentUsers, err := api.db.Queries.GetUsers(api.db.Ctx) + if err != nil { + return fmt.Errorf("unable to get current users") + } + + // Determine if we should be admin + isAdmin := false + if len(currentUsers) == 0 { + isAdmin = true + } + + // Create user in DB + authHash := fmt.Sprintf("%x", rawAuthHash) + if rows, err := api.db.Queries.CreateUser(api.db.Ctx, database.CreateUserParams{ + ID: username, + Pass: &hashedPassword, + AuthHash: &authHash, + Admin: isAdmin, + }); err != nil { + log.Error("CreateUser DB Error:", err) + return fmt.Errorf("unable to create user") + } else if rows == 0 { + log.Warn("User Already Exists:", username) + return fmt.Errorf("user already exists") + } + + return nil +} diff --git a/templates/pages/admin-users.tmpl b/templates/pages/admin-users.tmpl index 145d028..6e62e3d 100644 --- a/templates/pages/admin-users.tmpl +++ b/templates/pages/admin-users.tmpl @@ -9,8 +9,13 @@ action="./users" class="flex flex-col gap-2 text-black dark:text-white text-sm"> +