From 866bba7f07412f23e75e1b4169cef93618eafd0d Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 20 Jun 2023 16:55:58 +0200 Subject: [PATCH] update role --- modules/database/database.go | 34 ++++++--- modules/structs/roles.go | 12 ++-- modules/utils/globals.go | 25 ++++--- socketclients/socketclients.go | 126 +++++++++++++++++++++++++++++++-- socketserver/hub.go | 14 ++-- 5 files changed, 176 insertions(+), 35 deletions(-) diff --git a/modules/database/database.go b/modules/database/database.go index 3525fd2..c705a41 100644 --- a/modules/database/database.go +++ b/modules/database/database.go @@ -8,6 +8,7 @@ import ( "time" "github.com/google/uuid" + "github.com/rs/zerolog/log" "golang.org/x/crypto/bcrypt" "gorm.io/driver/mysql" "gorm.io/gorm" @@ -36,12 +37,12 @@ func InitDatabase() { db.AutoMigrate(&structs.Role{}) db.AutoMigrate(&structs.RolePermission{}) - createDefaultRole() - //adminRoleId := createDefaultRole() - //createUser(adminRoleId) + //createUser() } -func createUser(roleId string) { +func createUser() { + adminRoleId := createDefaultRole() + pw := []byte("haha") hashedPassword, err := bcrypt.GenerateFromPassword(pw, bcrypt.DefaultCost) @@ -52,7 +53,7 @@ func createUser(roleId string) { DB.Create(&structs.User{ Id: uuid.New().String(), - RoleId: roleId, + RoleId: adminRoleId, Username: "Alex", Email: "alex@roese.dev", Password: string(hashedPassword), @@ -63,15 +64,17 @@ func createUser(roleId string) { func createDefaultRole() (roleId string) { // create admin role if not already existing role := structs.Role{ - Id: uuid.New().String(), - DisplayName: "Admin", - Description: "Management board", - CreatedAt: time.Now(), + Id: uuid.New().String(), + Master: true, + DisplayName: "Admin", + Description: "Management board", + CreatedAt: time.Now(), + SortingOrder: 0, } var foundRole structs.Role - DB.First(&foundRole, "display_name = ?", role.DisplayName) + DB.First(&foundRole, "master = ?", true) if foundRole.Id == "" { result := DB.Create(&role) @@ -164,3 +167,14 @@ func isPermissionOutdated(systemPermissions []string, permission string) bool { return true } + +func GetRoleSortingOrder() int { + var lastSortingOrder int + + if err := DB.Model(&structs.Role{}).Select("MAX(sorting_order)").Scan(&lastSortingOrder).Error; err != nil { + log.Error().Msgf("Error getting role sorting order %v", err.Error()) + return 0 + } + + return lastSortingOrder + 1 +} diff --git a/modules/structs/roles.go b/modules/structs/roles.go index cdf3a39..cee58aa 100644 --- a/modules/structs/roles.go +++ b/modules/structs/roles.go @@ -5,11 +5,13 @@ import ( ) type Role struct { - Id string - DisplayName string - Description string - UpdatedAt time.Time - CreatedAt time.Time + Id string + Master bool `gorm:"type:bool"` // this reflects the role that has all rights + DisplayName string + Description string + SortingOrder int + UpdatedAt time.Time + CreatedAt time.Time } // Permissions assigned to the role diff --git a/modules/utils/globals.go b/modules/utils/globals.go index 7f7915b..174e0d9 100644 --- a/modules/utils/globals.go +++ b/modules/utils/globals.go @@ -1,16 +1,19 @@ package utils const ( - minUsername = "2" - maxUsername = "20" - MinUsername = 2 - MaxUsername = 20 - minPassword = "6" - MinPassword = 6 - maxPassword = "64" - MaxPassword = 64 - minScannerName = "3" - maxScannerName = "16" + minUsername = "2" + maxUsername = "20" + MinUsername = 2 + MaxUsername = 20 + minPassword = "6" + MinPassword = 6 + maxPassword = "64" + MaxPassword = 64 + minScannerName = "3" + maxScannerName = "16" + MinRoleDisplayName = 3 + MaxRoleDisplayName = 30 + MaxRoleDescription = 80 LenHeaderXAuthorization = 36 lenHeaderXAuthorization = "36" @@ -45,6 +48,7 @@ const ( SentCmdTaskUnlocked = 17 SentCmdUserProfileUpdated = 18 SentCmdAdminAreaNewRoleCreated = 19 + SentCmdAdminAreaRoleUpdated = 20 ) // commands received from web clients @@ -56,6 +60,7 @@ const ( ReceivedCmdTaskLocking = 5 ReceivedCmdUpdateUserProfile = 6 ReceivedCmdAdminAreaCreateNewRole = 7 + ReceivedCmdAdminAreaUpdateRole = 8 ) const ( diff --git a/socketclients/socketclients.go b/socketclients/socketclients.go index 33a9539..5afd4f8 100644 --- a/socketclients/socketclients.go +++ b/socketclients/socketclients.go @@ -201,7 +201,7 @@ func UpdateUserProfile(conn *websocket.Conn, changes map[string]interface{}) { if changes["username"] != nil { username := changes["username"].(string) - if isUsernameLengthValid(username) { // only affected if username was manipulated as min and max is provided in web ui + if isValueLenValid(username, utils.MinUsername, utils.MaxUsername) { // only affected if username was manipulated as min and max is provided in web ui if isUsernameAvailable(username) { user.Username = username updates["Username"] = username @@ -296,15 +296,15 @@ func UpdateUserProfile(conn *websocket.Conn, changes map[string]interface{}) { } } -func isUsernameLengthValid(username string) bool { - l := len(username) - return l > utils.MinUsername && l < utils.MaxUsername +func isValueLenValid(value string, min int, max int) bool { + l := len(value) + return l > min && l < max } func GetAllRoles() []structs.Role { var roles []structs.Role - database.DB.Find(&roles) + database.DB.Order("sorting_order").Find(&roles) return roles } @@ -355,3 +355,119 @@ func GetAdminAreaRolesPermissions() []structs.RolePermissions { return rolePermissions } + +func isRoleDisplayNameAvailable(roleDisplayName string) bool { + var role structs.Role + + database.DB.Select("display_name").Where("display_name = ?", roleDisplayName).Find(&role) + + return role.DisplayName == "" +} + +func AdminAreaUpdateRole(sessionId string, body map[string]interface{}) { + log.Debug().Msgf("update role %v", body) + + if body["RoleId"] == nil { + log.Error().Msgf("No role id specified in update role %v", body) + return + } + + roleId := body["RoleId"].(string) + changes := body["Changes"].(map[string]interface{}) + + if changes["AddedPermissions"] != nil { + log.Debug().Msgf("addedPermissions %v", len(changes["AddedPermissions"].([]interface{}))) + } + + // user has nothing changed + if changes["DisplayName"] == nil && + changes["Description"] == nil && + changes["AddedPermissions"] == nil && + changes["RemovedPermissions"] == nil { + log.Error().Msgf("User has not specified anything to update the role %v", body) + return + } + + updatedRole := structs.Role{ + Id: roleId, + } + + var changesResult = make(map[string]uint8) + var updates = make(map[string]interface{}) + + if changes["DisplayName"] != nil && isValueLenValid(changes["DisplayName"].(string), utils.MinRoleDisplayName, utils.MaxRoleDisplayName) { + if isRoleDisplayNameAvailable(changes["DisplayName"].(string)) { + updatedRole.DisplayName = changes["DisplayName"].(string) + updates["DisplayName"] = changes["DisplayName"].(string) + } else { + changesResult["DisplayName"] = 1 + } + } + + if changes["Description"] != nil { + updatedRole.Description = changes["Description"].(string) + updates["Description"] = changes["Description"].(string) + } + + if changes["AddedPermissions"] != nil { + addedPermissions := changes["AddedPermissions"].([]interface{}) + + updates["AddedPermissions"] = addedPermissions + + var dbAddedPermissions []structs.RolePermission + + for _, addedPermission := range addedPermissions { + dbAddedPermissions = append(dbAddedPermissions, structs.RolePermission{ + RoleId: roleId, + PermissionId: addedPermission.(string), + }) + } + + database.DB.Create(dbAddedPermissions) + + log.Debug().Msgf("dbAddedPermissions: %v", dbAddedPermissions) + } + + if changes["RemovedPermissions"] != nil { + removedPermissions := changes["RemovedPermissions"].([]interface{}) + + updates["RemovedPermissions"] = removedPermissions + + for _, removedPermission := range removedPermissions { + + database.DB.Where("role_id = ?", roleId).Where("permission_id = ?", removedPermission.(string)).Delete(&structs.RolePermission{}) + + log.Debug().Msgf("dbRemovedPermissions: %v", removedPermission) + } + } + + database.DB.Model(&structs.Role{}).Where("id = ?", roleId).Updates(&updatedRole) + + log.Debug().Msgf("updated role: %v", updatedRole) + + // TODO: check permissions + + SendMessageOnlyToSessionId(sessionId, structs.SendSocketMessage{ + Cmd: utils.SentCmdAdminAreaRoleUpdated, + Body: struct { + RoleId string + Changes map[string]interface{} + Result map[string]uint8 + }{ + RoleId: roleId, + Changes: updates, + Result: changesResult, + }, + }) + + BroadcastMessageExceptUserSessionId(sessionId, structs.SendSocketMessage{ + Cmd: utils.SentCmdAdminAreaRoleUpdated, + Body: struct { + RoleId string + Changes map[string]interface{} + }{ + RoleId: roleId, + Changes: updates, + }, + }) +} diff --git a/socketserver/hub.go b/socketserver/hub.go index bf623f6..31b50e0 100644 --- a/socketserver/hub.go +++ b/socketserver/hub.go @@ -201,19 +201,23 @@ func RunHub() { // TODO: check permissions role := structs.Role{ - Id: uuid.New().String(), - DisplayName: "New Role " + time.Now().String(), - Description: "Role description", - CreatedAt: time.Now(), + Id: uuid.New().String(), + DisplayName: "New Role " + uuid.New().String(), + Description: "Role description", + CreatedAt: time.Now(), + SortingOrder: database.GetRoleSortingOrder(), } - //database.DB.Create(&role) + database.DB.Create(&role) socketclients.BroadcastMessage(structs.SendSocketMessage{ Cmd: utils.SentCmdAdminAreaNewRoleCreated, Body: role, }) break + case utils.ReceivedCmdAdminAreaUpdateRole: + socketclients.AdminAreaUpdateRole(data.Conn.Locals("sessionId").(string), receivedMessage.Body) + break default: log.Error().Msgf("Received unknown message: %v", receivedMessage) break