From f27172cfd8a055ed0343f575bdd94b070417f69e Mon Sep 17 00:00:00 2001 From: konrad Date: Tue, 23 Jan 2018 14:31:54 +0100 Subject: [PATCH] Added method to add or update a user --- models/error.go | 19 +++++++++ models/models.go | 10 ++--- models/user.go | 6 +++ models/user_add_update.go | 9 ++-- routes/api/v1/user_add_update.go | 73 ++++++++++++++++++++++++++++++++ routes/routes.go | 1 + 6 files changed, 110 insertions(+), 8 deletions(-) create mode 100644 models/error.go create mode 100644 routes/api/v1/user_add_update.go diff --git a/models/error.go b/models/error.go new file mode 100644 index 0000000..b3e90ee --- /dev/null +++ b/models/error.go @@ -0,0 +1,19 @@ +package models + +import "fmt" + +// ErrUsernameExists represents a "UsernameAlreadyExists" kind of error. +type ErrUsernameExists struct { + UserID int64 + Username string +} + +// IsErrUsernameExists checks if an error is a ErrUsernameExists. +func IsErrUsernameExists(err error) bool { + _, ok := err.(ErrUsernameExists) + return ok +} + +func (err ErrUsernameExists) Error() string { + return fmt.Sprintf("a user with this username does already exist [user id: %d, username: %s]", err.UserID, err.Username) +} \ No newline at end of file diff --git a/models/models.go b/models/models.go index 4f47db6..80e0018 100644 --- a/models/models.go +++ b/models/models.go @@ -53,23 +53,23 @@ func SetEngine() (err error) { x.ShowSQL(Config.Database.ShowQueries) - // Check if the first user already exists, aka a user with the ID = 1. If not, insert it - _, exists, err := GetUserByID(1) + // Check if at least one user already exists. If not, insert it + total, err := x.Count(User{}) if err != nil { return err } // If it doesn't exist, create it - if !exists { + if total < 1 { Config.FirstUser.IsAdmin = true // Make the first user admin _, err = CreateUser(Config.FirstUser) if err != nil { - // Janky hack, I know - if err.Error() != "this username is already taken. Please use another" { + if !IsErrUsernameExists(err) { return err } } + fmt.Println("Created new user " + Config.FirstUser.Username) } diff --git a/models/user.go b/models/user.go index 253e38f..799284f 100644 --- a/models/user.go +++ b/models/user.go @@ -41,6 +41,11 @@ func (User) TableName() string { // GetUserByID gets informations about a user by its ID func GetUserByID(id int64) (user User, exists bool, err error) { + // Apparently xorm does otherwise look for all users but return only one, which leads to returing one even if the ID is 0 + if user.ID == 0 { + return User{}, false, nil + } + return GetUser(User{ID: id}) } @@ -48,6 +53,7 @@ func GetUserByID(id int64) (user User, exists bool, err error) { func GetUser(user User) (userOut User, exists bool, err error) { userOut = user exists, err = x.Get(&userOut) + //fmt.Println(user, userOut, exists, err) return userOut, exists, err } diff --git a/models/user_add_update.go b/models/user_add_update.go index dbedd76..ffb5251 100644 --- a/models/user_add_update.go +++ b/models/user_add_update.go @@ -16,12 +16,12 @@ func CreateUser(user User) (newUser User, err error) { } // Check if the user already existst - _, exists, err := GetUser(User{Name: newUser.Name}) + existingUser, exists, err := GetUser(User{Username: newUser.Username}) if err != nil { return User{}, err } if exists { - return User{}, fmt.Errorf("this username is already taken. Please use another") + return User{}, ErrUsernameExists{existingUser.ID, existingUser.Username} } // Hash the password @@ -36,7 +36,10 @@ func CreateUser(user User) (newUser User, err error) { return User{}, err } - return newUser, nil + // Get the full new User + newUserOut, _, err := GetUser(newUser) + + return newUserOut, nil } // HashPassword hashes a password diff --git a/routes/api/v1/user_add_update.go b/routes/api/v1/user_add_update.go new file mode 100644 index 0000000..5723c4a --- /dev/null +++ b/routes/api/v1/user_add_update.go @@ -0,0 +1,73 @@ +package v1 + +import ( + "encoding/json" + "git.mowie.cc/konrad/Library/models" + "github.com/labstack/echo" + "net/http" + "strconv" + "strings" +) + +// UserAddOrUpdate is the handler to add a user +func UserAddOrUpdate(c echo.Context) error { + // Check for Request Content + userFromString := c.FormValue("user") + var datUser *models.User + + if userFromString == "" { + // b := new(models.User) + if err := c.Bind(&datUser); err != nil { + return c.JSON(http.StatusBadRequest, models.Message{"No user model provided."}) + } + } else { + // Decode the JSON + dec := json.NewDecoder(strings.NewReader(userFromString)) + err := dec.Decode(&datUser) + + if err != nil { + return c.JSON(http.StatusBadRequest, models.Message{"Error decoding user: " + err.Error()}) + } + } + + // Check if we have an ID other than the one in the struct + id := c.Param("id") + if id != "" { + // Make int + userID, err := strconv.ParseInt(id, 10, 64) + + if err != nil { + return c.JSON(http.StatusInternalServerError, models.Message{"Could not get item id."}) + } + datUser.ID = userID + } + + // Check if the user exists + _, exists, err := models.GetUserByID(datUser.ID) + if err != nil { + return c.JSON(http.StatusInternalServerError, models.Message{"Could not check if the user exists."}) + } + + // Insert or update the user + var newUser models.User + if exists { + newUser, err = models.UpdateUser(*datUser) + } else { + newUser, err = models.CreateUser(*datUser) + } + + if err != nil { + if models.IsErrUsernameExists(err) { + return c.JSON(http.StatusBadRequest, models.Message{"A user with this username already exists"}) + } + return c.JSON(http.StatusInternalServerError, models.Message{"Error"}) + } + + // Log the action + err = models.LogAction("Added or updated a user", newUser.ID, c) + if err != nil { + return c.JSON(http.StatusInternalServerError, models.Message{"Could not log."}) + } + + return c.JSON(http.StatusOK, newUser) +} diff --git a/routes/routes.go b/routes/routes.go index 05759a5..f449328 100644 --- a/routes/routes.go +++ b/routes/routes.go @@ -109,6 +109,7 @@ func RegisterRoutes(e *echo.Echo) { // ====== Admin Routes ====== a.GET("/users", apiv1.UsersList) + a.PUT("/users", apiv1.UserAddOrUpdate) // Manage Users