From 6c6a6dd3296935f02d6c4486b740ca7b5bf45403 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Sun, 25 Feb 2024 19:40:36 -0500 Subject: [PATCH] feat(api): first user is admin --- api/auth.go | 77 ++++++++++++++++++++++++++++--------------- database/query.sql | 4 +-- database/query.sql.go | 12 +++++-- 3 files changed, 61 insertions(+), 32 deletions(-) diff --git a/api/auth.go b/api/auth.go index c479a65..4314300 100644 --- a/api/auth.go +++ b/api/auth.go @@ -205,7 +205,7 @@ func (api *API) appAuthRegister(c *gin.Context) { return } - // Generate Auth Hash + // Generate auth hash rawAuthHash, err := utils.GenerateToken(64) if err != nil { log.Error("Failed to generate user token: ", err) @@ -214,31 +214,41 @@ func (api *API) appAuthRegister(c *gin.Context) { return } - // Create User in DB - authHash := fmt.Sprintf("%x", rawAuthHash) - rows, err := api.db.Queries.CreateUser(api.db.Ctx, database.CreateUserParams{ - ID: username, - Pass: &hashedPassword, - AuthHash: &authHash, - }) - - // SQL Error + // Get current users + currentUsers, err := api.db.Queries.GetUsers(api.db.Ctx) if err != nil { - log.Error("CreateUser DB Error:", err) - templateVars["Error"] = "Registration Disabled or User Already Exists" + log.Error("Failed to check all users: ", err) + templateVars["Error"] = "Failed to Create User" c.HTML(http.StatusBadRequest, "page/login", templateVars) return } - // User Already Exists - if rows == 0 { + // 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) + templateVars["Error"] = "Registration Disabled or User Already Exists" + c.HTML(http.StatusBadRequest, "page/login", templateVars) + return + } else if rows == 0 { log.Warn("User Already Exists:", username) templateVars["Error"] = "Registration Disabled or User Already Exists" c.HTML(http.StatusBadRequest, "page/login", templateVars) return } - // Get User + // Get user user, err := api.db.Queries.GetUser(api.db.Ctx, username) if err != nil { log.Error("GetUser DB Error:", err) @@ -247,7 +257,7 @@ func (api *API) appAuthRegister(c *gin.Context) { return } - // Set Session + // Set session auth := authData{ UserName: user.ID, IsAdmin: user.Admin, @@ -289,6 +299,7 @@ func (api *API) koAuthRegister(c *gin.Context) { return } + // Generate password hash hashedPassword, err := argon2.CreateHash(rUser.Password, argon2.DefaultParams) if err != nil { log.Error("Argon2 Hash Failure:", err) @@ -296,7 +307,7 @@ func (api *API) koAuthRegister(c *gin.Context) { return } - // Generate Auth Hash + // Generate auth hash rawAuthHash, err := utils.GenerateToken(64) if err != nil { log.Error("Failed to generate user token: ", err) @@ -304,20 +315,32 @@ func (api *API) koAuthRegister(c *gin.Context) { return } - authHash := fmt.Sprintf("%x", rawAuthHash) - rows, err := api.db.Queries.CreateUser(api.db.Ctx, database.CreateUserParams{ - ID: rUser.Username, - Pass: &hashedPassword, - AuthHash: &authHash, - }) + // Get current users + currentUsers, err := api.db.Queries.GetUsers(api.db.Ctx) if err != nil { - log.Error("CreateUser DB Error:", err) - apiErrorPage(c, http.StatusBadRequest, "Invalid User Data") + log.Error("Failed to check all users: ", err) + apiErrorPage(c, http.StatusBadRequest, "Failed to Create User") return } - // User Exists - if rows == 0 { + // Determine if we should be admin + isAdmin := false + if len(currentUsers) == 0 { + isAdmin = true + } + + // Create user + authHash := fmt.Sprintf("%x", rawAuthHash) + if rows, err := api.db.Queries.CreateUser(api.db.Ctx, database.CreateUserParams{ + ID: rUser.Username, + Pass: &hashedPassword, + AuthHash: &authHash, + Admin: isAdmin, + }); err != nil { + log.Error("CreateUser DB Error:", err) + apiErrorPage(c, http.StatusBadRequest, "Invalid User Data") + return + } else if rows == 0 { log.Error("User Already Exists:", rUser.Username) apiErrorPage(c, http.StatusBadRequest, "User Already Exists") return diff --git a/database/query.sql b/database/query.sql index 019d8e4..f8c53d8 100644 --- a/database/query.sql +++ b/database/query.sql @@ -26,8 +26,8 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING *; -- name: CreateUser :execrows -INSERT INTO users (id, pass, auth_hash) -VALUES (?, ?, ?) +INSERT INTO users (id, pass, auth_hash, admin) +VALUES (?, ?, ?, ?) ON CONFLICT DO NOTHING; -- name: DeleteDocument :execrows diff --git a/database/query.sql.go b/database/query.sql.go index 0092c6c..4710f9f 100644 --- a/database/query.sql.go +++ b/database/query.sql.go @@ -113,8 +113,8 @@ func (q *Queries) AddMetadata(ctx context.Context, arg AddMetadataParams) (Metad } const createUser = `-- name: CreateUser :execrows -INSERT INTO users (id, pass, auth_hash) -VALUES (?, ?, ?) +INSERT INTO users (id, pass, auth_hash, admin) +VALUES (?, ?, ?, ?) ON CONFLICT DO NOTHING ` @@ -122,10 +122,16 @@ type CreateUserParams struct { ID string `json:"id"` Pass *string `json:"-"` AuthHash *string `json:"auth_hash"` + Admin bool `json:"-"` } func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (int64, error) { - result, err := q.db.ExecContext(ctx, createUser, arg.ID, arg.Pass, arg.AuthHash) + result, err := q.db.ExecContext(ctx, createUser, + arg.ID, + arg.Pass, + arg.AuthHash, + arg.Admin, + ) if err != nil { return 0, err }