From 772ed316cb4e3ec6aebe78fa87a9ecafbd42338c Mon Sep 17 00:00:00 2001 From: konrad Date: Tue, 23 Jan 2018 12:37:13 +0100 Subject: [PATCH] Added list user method --- models/user.go | 82 +++++++++++++------------------------ models/user_test.go | 15 +++++++ models/users_list.go | 25 +++++++++++ routes/api/v1/users_list.go | 27 ++++++++++++ routes/login.go | 1 + routes/routes.go | 13 ++++-- 6 files changed, 106 insertions(+), 57 deletions(-) create mode 100644 models/users_list.go create mode 100644 routes/api/v1/users_list.go diff --git a/models/user.go b/models/user.go index 1c9b32f..c7eaf9f 100644 --- a/models/user.go +++ b/models/user.go @@ -15,23 +15,23 @@ type UserLogin struct { // User holds information about an user type User struct { - ID int64 `xorm:"int(11) autoincr not null unique pk"` - Name string `xorm:"varchar(250)"` - Username string `xorm:"varchar(250) not null unique"` - Password string `xorm:"varchar(250) not null"` - Email string `xorm:"varchar(250)"` - IsAdmin bool `xorm:"tinyint(1) not null"` - Created int64 `xorm:"created"` - Updated int64 `xorm:"updated"` + ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"` + Name string `xorm:"varchar(250)" json:"name"` + Username string `xorm:"varchar(250) not null unique" json:"username"` + Password string `xorm:"varchar(250) not null" json:"password"` + Email string `xorm:"varchar(250)" json:"email"` + IsAdmin bool `xorm:"tinyint(1) not null" json:"isAdmin"` + Created int64 `xorm:"created" json:"created"` + Updated int64 `xorm:"updated" json:"updated"` } // UserLog logs user actions type UserLog struct { - ID int64 `xorm:"int(11) autoincr not null unique pk"` - UserID int64 `xorm:"int(11)"` - Log string `xorm:"varchar(250)"` - ItemID int64 `xorm:"int(11)"` - Time int64 `xorm:"created"` + ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"` + UserID int64 `xorm:"int(11)" json:"userID"` + Log string `xorm:"varchar(250)" json:"log"` + ItemID int64 `xorm:"int(11)" json:"itemID"` + Time int64 `xorm:"created" json:"time"` } // TableName returns the table name for users @@ -51,46 +51,6 @@ func GetUser(user User) (userOut User, exists bool, err error) { return userOut, exists, err } -// CreateUser creates a new user and inserts it into the database -func CreateUser(user User) (newUser User, err error) { - - newUser = user - - // Check if we have all needed informations - if newUser.Password == "" || newUser.Username == "" { - return User{}, fmt.Errorf("you need to specify at least a username and a password") - } - - // Check if the user already existst - _, exists, err := GetUser(User{Name: newUser.Name}) - if err != nil { - return User{}, err - } - if exists { - return User{}, fmt.Errorf("this username is already taken. Please use another") - } - - // Hash the password - newUser.Password, err = hashPassword(user.Password) - if err != nil { - return User{}, err - } - - // Insert it - _, err = x.Insert(newUser) - if err != nil { - return User{}, err - } - - return newUser, nil -} - -// HashPassword hashes a password -func hashPassword(password string) (string, error) { - bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14) - return string(bytes), err -} - // CheckUserCredentials checks user credentials func CheckUserCredentials(u *UserLogin) (User, error) { @@ -149,3 +109,19 @@ func LogAction(action string, itemID int64, c echo.Context) (err error) { return logAction(action, user, itemID) } + +// IsAdmin checks based on it's JWT token if the user is admin +func IsAdmin(c echo.Context) bool { + + // Get the users JWT token + jwtinf := c.Get("user").(*jwt.Token) + claims := jwtinf.Claims.(jwt.MapClaims) + + // And check if he is admin + if claims["admin"].(bool) { + return true + } + + // Send him to nirvarna if not + return false +} diff --git a/models/user_test.go b/models/user_test.go index 12f928a..747aec9 100644 --- a/models/user_test.go +++ b/models/user_test.go @@ -15,8 +15,19 @@ func TestCreateUser(t *testing.T) { Username: "testuu", Password: "1234", Email: "noone@example.com", + IsAdmin: true, } + // Delete every preexisting user to have a fresh start +/* allusers, err := ListUsers("") + for _, user := range allusers { + // Delete it + assert.Equal(t, dummyuser.Name, user.Name) + assert.Equal(t, dummyuser.Username, user.Username) + assert.Equal(t, dummyuser.Email, user.Email) + assert.Equal(t, dummyuser.IsAdmin, user.IsAdmin) + }*/ + // Create a new user createdUser, err := CreateUser(dummyuser) assert.NoError(t, err) @@ -45,4 +56,8 @@ func TestCreateUser(t *testing.T) { user, err := CheckUserCredentials(&UserLogin{"testuu", "1234"}) assert.NoError(t, err) assert.Equal(t, dummyuser.Name, user.Name) + + // List one user + + // Delete it } diff --git a/models/users_list.go b/models/users_list.go new file mode 100644 index 0000000..6bf4d5f --- /dev/null +++ b/models/users_list.go @@ -0,0 +1,25 @@ +package models + +// ListUsers returns a list with all users, filtered by an optional searchstring +func ListUsers(searchterm string) (users []User, err error) { + + if searchterm == "" { + err = x.Find(&users) + } else { + err = x. + Where("username LIKE ?", "%"+searchterm+"%"). + Or("name LIKE ?", "%"+searchterm+"%"). + Find(&users) + } + + // Obfuscate the password. Selecting everything except the password didn't work. + for i := range users { + users[i].Password = "" + } + + if err != nil { + return []User{}, err + } + + return users, nil +} diff --git a/routes/api/v1/users_list.go b/routes/api/v1/users_list.go new file mode 100644 index 0000000..8584486 --- /dev/null +++ b/routes/api/v1/users_list.go @@ -0,0 +1,27 @@ +package v1 + +import ( + "net/http" + + "github.com/labstack/echo" + "git.mowie.cc/konrad/Library/models" +) + +func UsersList(c echo.Context) error { + + // Check if the user is admin + if !models.IsAdmin(c) { + return echo.ErrUnauthorized + } + + // Prepare the searchterm + search := c.QueryParam("s") + + list, err := models.ListUsers(search) + + if err != nil { + return c.JSON(http.StatusInternalServerError, models.Message{"Error getting users."}) + } + + return c.JSON(http.StatusOK, list) +} \ No newline at end of file diff --git a/routes/login.go b/routes/login.go index 033bfaf..7c1f320 100644 --- a/routes/login.go +++ b/routes/login.go @@ -33,6 +33,7 @@ func Login(c echo.Context) error { claims["username"] = user.Username claims["email"] = user.Email claims["id"] = user.ID + claims["admin"] = user.IsAdmin claims["exp"] = time.Now().Add(time.Hour * 72).Unix() avatar := md5.Sum([]byte(user.Email)) diff --git a/routes/routes.go b/routes/routes.go index 0392e7e..05759a5 100644 --- a/routes/routes.go +++ b/routes/routes.go @@ -106,6 +106,10 @@ func RegisterRoutes(e *echo.Echo) { a.DELETE("/items/:id", apiv1.ItemDelete) a.POST("/items/:id", apiv1.ItemAddOrUpdate) + // ====== Admin Routes ====== + + a.GET("/users", apiv1.UsersList) + // Manage Users /* @@ -141,9 +145,10 @@ func RegisterRoutes(e *echo.Echo) { GET /settings - |Nutzereinstellungen (Passwort, name etc) POST /settings - |Nutzereinstellungen (Passwort, name etc) - GET /user - Nutzer anzeigen - PUT /user - |neue Nutzer anlegen - DELETE /user/:id - |nutzer löschen - POST /user/:id - |nutzer bearbeiten + GET /user - |Nutzer anzeigen --> Auch nur admin + PUT /user - |neue Nutzer anlegen --> Nur admin + DELETE /user/:id - |nutzer löschen --> Nur admins (sich selber löschen sollte nicht möglich sein) + POST /user/:id - |nutzer bearbeiten --> Sollte entweder Admin oder der Nutzer selbst sein + */ }