Explorar el Código

feat(go): use uuid group id;

Vishal Dalwadi hace 3 meses
padre
commit
7f06dde882
Se han modificado 7 ficheros con 199 adiciones y 43 borrados
  1. 34 0
      logic/auth.go
  2. 2 0
      logic/user_mgmt.go
  3. 5 0
      migrate/migrate.go
  4. 6 9
      pro/auth/sync.go
  5. 1 0
      pro/initialize.go
  6. 40 9
      pro/logic/migrate.go
  7. 111 25
      pro/logic/user_mgmt.go

+ 34 - 0
logic/auth.go

@@ -315,11 +315,45 @@ func UpdateUser(userchange, user *models.User) (*models.User, error) {
 		user.DisplayName = userchange.DisplayName
 	}
 
+	if user.ExternalIdentityProviderID != "" &&
+		userchange.AccountDisabled != user.AccountDisabled {
+		return userchange, errors.New("account status cannot be updated for external user")
+	}
+
 	// Reset Gw Access for service users
 	go UpdateUserGwAccess(*user, *userchange)
 	if userchange.PlatformRoleID != "" {
 		user.PlatformRoleID = userchange.PlatformRoleID
 	}
+
+	for groupID := range userchange.UserGroups {
+		_, ok := user.UserGroups[groupID]
+		if !ok {
+			group, err := GetUserGroup(groupID)
+			if err != nil {
+				return userchange, err
+			}
+
+			if group.ExternalIdentityProviderID != "" {
+				return userchange, errors.New("cannot modify membership of external groups")
+			}
+		}
+	}
+
+	for groupID := range user.UserGroups {
+		_, ok := userchange.UserGroups[groupID]
+		if !ok {
+			group, err := GetUserGroup(groupID)
+			if err != nil {
+				return userchange, err
+			}
+
+			if group.ExternalIdentityProviderID != "" {
+				return userchange, errors.New("cannot modify membership of external groups")
+			}
+		}
+	}
+
 	user.UserGroups = userchange.UserGroups
 	user.NetworkRoles = userchange.NetworkRoles
 	AddGlobalNetRolesToAdmins(user)

+ 2 - 0
logic/user_mgmt.go

@@ -50,6 +50,8 @@ var MigrateUserRoleAndGroups = func(u models.User) {
 
 }
 
+var MigrateGroups = func() {}
+
 var UpdateUserGwAccess = func(currentUser, changeUser models.User) {}
 
 var UpdateRole = func(r models.UserRolePermissionTemplate) error { return nil }

+ 5 - 0
migrate/migrate.go

@@ -25,6 +25,7 @@ func Run() {
 	assignSuperAdmin()
 	createDefaultTagsAndPolicies()
 	removeOldUserGrps()
+	syncGroups()
 	syncUsers()
 	updateHosts()
 	updateNodes()
@@ -388,6 +389,10 @@ func MigrateEmqx() {
 
 }
 
+func syncGroups() {
+	logic.MigrateGroups()
+}
+
 func syncUsers() {
 	// create default network user roles for existing networks
 	if servercfg.IsPro {

+ 6 - 9
pro/auth/sync.go

@@ -185,9 +185,7 @@ func syncGroups(idpGroups []idp.Group) error {
 	}
 
 	dbGroupsMap := make(map[string]models.UserGroup)
-	dbGroupsNameMap := make(map[models.UserGroupID]struct{})
 	for _, group := range dbGroups {
-		dbGroupsNameMap[group.ID] = struct{}{}
 		if group.ExternalIdentityProviderID != "" {
 			dbGroupsMap[group.ExternalIdentityProviderID] = group
 		}
@@ -220,14 +218,7 @@ func syncGroups(idpGroups []idp.Group) error {
 
 		dbGroup, ok := dbGroupsMap[group.ID]
 		if !ok {
-			// create the group only if it doesn't exist.
-			if _, ok := dbGroupsNameMap[models.UserGroupID(group.Name)]; ok {
-				logger.Log(0, "group with name "+group.Name+" already exists, skipping creation")
-				continue
-			}
-
 			err := proLogic.CreateUserGroup(models.UserGroup{
-				ID:                         models.UserGroupID(group.Name),
 				ExternalIdentityProviderID: group.ID,
 				Default:                    false,
 				Name:                       group.Name,
@@ -235,6 +226,12 @@ func syncGroups(idpGroups []idp.Group) error {
 			if err != nil {
 				return err
 			}
+		} else {
+			dbGroup.Name = group.Name
+			err = proLogic.UpdateUserGroup(dbGroup)
+			if err != nil {
+				return err
+			}
 		}
 
 		groupMembersMap := make(map[string]struct{})

+ 1 - 0
pro/initialize.go

@@ -133,6 +133,7 @@ func InitPro() {
 	logic.UpdateUserGwAccess = proLogic.UpdateUserGwAccess
 	logic.CreateDefaultUserPolicies = proLogic.CreateDefaultUserPolicies
 	logic.MigrateUserRoleAndGroups = proLogic.MigrateUserRoleAndGroups
+	logic.MigrateGroups = proLogic.MigrateGroups
 	logic.IntialiseGroups = proLogic.UserGroupsInit
 	logic.AddGlobalNetRolesToAdmins = proLogic.AddGlobalNetRolesToAdmins
 	logic.GetUserGroupsInNetwork = proLogic.GetUserGroupsInNetwork

+ 40 - 9
pro/logic/migrate.go

@@ -1,12 +1,45 @@
 package logic
 
 import (
-	"fmt"
+	"github.com/google/uuid"
 
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 )
 
+func MigrateGroups() {
+	groups, err := ListUserGroups()
+	if err != nil {
+		return
+	}
+
+	groupMapping := make(map[models.UserGroupID]models.UserGroupID)
+
+	for _, group := range groups {
+		newGroupID := models.UserGroupID(uuid.NewString())
+		groupMapping[group.ID] = newGroupID
+
+		group.ID = newGroupID
+		UpdateUserGroup(group)
+	}
+
+	users, err := logic.GetUsersDB()
+	if err != nil {
+		return
+	}
+
+	for _, user := range users {
+		userGroups := make(map[models.UserGroupID]struct{})
+		for groupID := range user.UserGroups {
+			newGroupID := groupMapping[groupID]
+			userGroups[newGroupID] = struct{}{}
+		}
+
+		user.UserGroups = userGroups
+		logic.UpsertUser(user)
+	}
+}
+
 func MigrateUserRoleAndGroups(user models.User) {
 	var err error
 	if user.PlatformRoleID == models.AdminRole || user.PlatformRoleID == models.SuperAdminRole {
@@ -22,10 +55,9 @@ func MigrateUserRoleAndGroups(user models.User) {
 			}
 			var g models.UserGroup
 			if user.PlatformRoleID == models.ServiceUser {
-				g, err = GetUserGroup(models.UserGroupID(fmt.Sprintf("%s-%s-grp", gwNode.Network, models.NetworkUser)))
+				g, err = GetDefaultNetworkUserGroup(models.NetworkID(gwNode.Network))
 			} else {
-				g, err = GetUserGroup(models.UserGroupID(fmt.Sprintf("%s-%s-grp",
-					gwNode.Network, models.NetworkAdmin)))
+				g, err = GetDefaultNetworkAdminGroup(models.NetworkID(gwNode.Network))
 			}
 			if err != nil {
 				continue
@@ -47,14 +79,13 @@ func MigrateUserRoleAndGroups(user models.User) {
 			}
 
 			if user.PlatformRoleID == models.ServiceUser {
-				g, err = GetUserGroup(models.UserGroupID(fmt.Sprintf("%s-%s-grp", netID, models.NetworkUser)))
+				g, err = GetDefaultNetworkUserGroup(netID)
 			} else {
-				role := models.NetworkUser
 				if adminAccess {
-					role = models.NetworkAdmin
+					g, err = GetDefaultNetworkAdminGroup(netID)
+				} else {
+					g, err = GetDefaultNetworkUserGroup(netID)
 				}
-				g, err = GetUserGroup(models.UserGroupID(fmt.Sprintf("%s-%s-grp",
-					netID, role)))
 			}
 			if err != nil {
 				continue

+ 111 - 25
pro/logic/user_mgmt.go

@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"github.com/google/uuid"
 	"time"
 
 	"github.com/gravitl/netmaker/database"
@@ -15,6 +16,11 @@ import (
 	"golang.org/x/exp/slog"
 )
 
+const (
+	globalNetworksAdminGroupName = "All Networks Admin Group"
+	globalNetworksUserGroupName  = "All Networks User Group"
+)
+
 var ServiceUserPermissionTemplate = models.UserRolePermissionTemplate{
 	ID:                  models.ServiceUser,
 	Default:             true,
@@ -112,9 +118,9 @@ func UserRolesInit() {
 func UserGroupsInit() {
 	// create default network groups
 	var NetworkGlobalAdminGroup = models.UserGroup{
-		ID:       models.UserGroupID(fmt.Sprintf("global-%s-grp", models.NetworkAdmin)),
+		ID:       models.UserGroupID(uuid.NewString()),
 		Default:  true,
-		Name:     "All Networks Admin Group",
+		Name:     globalNetworksAdminGroupName,
 		MetaData: "can manage configuration of all networks",
 		NetworkRoles: map[models.NetworkID]map[models.UserRoleID]struct{}{
 			models.AllNetworks: {
@@ -123,11 +129,11 @@ func UserGroupsInit() {
 		},
 	}
 	var NetworkGlobalUserGroup = models.UserGroup{
-		ID:      models.UserGroupID(fmt.Sprintf("global-%s-grp", models.NetworkUser)),
-		Name:    "All Networks User Group",
+		ID:      models.UserGroupID(uuid.NewString()),
+		Name:    globalNetworksUserGroupName,
 		Default: true,
 		NetworkRoles: map[models.NetworkID]map[models.UserRoleID]struct{}{
-			models.NetworkID(models.AllNetworks): {
+			models.AllNetworks: {
 				models.UserRoleID(fmt.Sprintf("global-%s", models.NetworkUser)): {},
 			},
 		},
@@ -216,7 +222,7 @@ func CreateDefaultNetworkRolesAndGroups(netID models.NetworkID) {
 
 	// create default network groups
 	var NetworkAdminGroup = models.UserGroup{
-		ID:      models.UserGroupID(fmt.Sprintf("%s-%s-grp", netID, models.NetworkAdmin)),
+		ID:      models.UserGroupID(uuid.NewString()),
 		Name:    fmt.Sprintf("%s Admin Group", netID),
 		Default: true,
 		NetworkRoles: map[models.NetworkID]map[models.UserRoleID]struct{}{
@@ -227,7 +233,7 @@ func CreateDefaultNetworkRolesAndGroups(netID models.NetworkID) {
 		MetaData: fmt.Sprintf("can manage your network `%s` configuration including adding and removing devices.", netID),
 	}
 	var NetworkUserGroup = models.UserGroup{
-		ID:      models.UserGroupID(fmt.Sprintf("%s-%s-grp", netID, models.NetworkUser)),
+		ID:      models.UserGroupID(uuid.NewString()),
 		Name:    fmt.Sprintf("%s User Group", netID),
 		Default: true,
 		NetworkRoles: map[models.NetworkID]map[models.UserRoleID]struct{}{
@@ -249,28 +255,29 @@ func DeleteNetworkRoles(netID string) {
 	if err != nil {
 		return
 	}
-	defaultUserGrp := fmt.Sprintf("%s-%s-grp", netID, models.NetworkUser)
-	defaultAdminGrp := fmt.Sprintf("%s-%s-grp", netID, models.NetworkAdmin)
+
+	defaultAdminGrp, _ := GetDefaultNetworkAdminGroup(models.NetworkID(netID))
+	defaultUserGrp, _ := GetDefaultNetworkUserGroup(models.NetworkID(netID))
 	for _, user := range users {
 		var upsert bool
 		if _, ok := user.NetworkRoles[models.NetworkID(netID)]; ok {
 			delete(user.NetworkRoles, models.NetworkID(netID))
 			upsert = true
 		}
-		if _, ok := user.UserGroups[models.UserGroupID(defaultUserGrp)]; ok {
-			delete(user.UserGroups, models.UserGroupID(defaultUserGrp))
+		if _, ok := user.UserGroups[defaultUserGrp.ID]; ok {
+			delete(user.UserGroups, defaultUserGrp.ID)
 			upsert = true
 		}
-		if _, ok := user.UserGroups[models.UserGroupID(defaultAdminGrp)]; ok {
-			delete(user.UserGroups, models.UserGroupID(defaultAdminGrp))
+		if _, ok := user.UserGroups[defaultAdminGrp.ID]; ok {
+			delete(user.UserGroups, defaultAdminGrp.ID)
 			upsert = true
 		}
 		if upsert {
 			logic.UpsertUser(user)
 		}
 	}
-	database.DeleteRecord(database.USER_GROUPS_TABLE_NAME, defaultUserGrp)
-	database.DeleteRecord(database.USER_GROUPS_TABLE_NAME, defaultAdminGrp)
+	database.DeleteRecord(database.USER_GROUPS_TABLE_NAME, defaultUserGrp.ID.String())
+	database.DeleteRecord(database.USER_GROUPS_TABLE_NAME, defaultAdminGrp.ID.String())
 	userGs, _ := ListUserGroups()
 	for _, userGI := range userGs {
 		if _, ok := userGI.NetworkRoles[models.NetworkID(netID)]; ok {
@@ -525,14 +532,22 @@ func ValidateUpdateGroupReq(g models.UserGroup) error {
 
 // CreateUserGroup - creates new user group
 func CreateUserGroup(g models.UserGroup) error {
+	g.ID = models.UserGroupID(uuid.NewString())
 	// check if the group already exists
-	if g.ID == "" {
-		return errors.New("group id cannot be empty")
+	if g.Name == "" {
+		return errors.New("group name cannot be empty")
 	}
-	_, err := database.FetchRecord(database.USER_GROUPS_TABLE_NAME, g.ID.String())
-	if err == nil {
-		return errors.New("group already exists")
+	groups, err := ListUserGroups()
+	if err != nil {
+		return err
 	}
+
+	for _, group := range groups {
+		if group.Name == g.Name {
+			return errors.New("group already exists")
+		}
+	}
+
 	d, err := json.Marshal(g)
 	if err != nil {
 		return err
@@ -554,6 +569,68 @@ func GetUserGroup(gid models.UserGroupID) (models.UserGroup, error) {
 	return ug, nil
 }
 
+func GetDefaultGlobalNetworksAdminGroup() (models.UserGroup, error) {
+	groups, err := ListUserGroups()
+	if err != nil {
+		return models.UserGroup{}, err
+	}
+
+	for _, group := range groups {
+		if group.Default && group.Name == globalNetworksAdminGroupName {
+			return group, nil
+		}
+	}
+
+	return models.UserGroup{}, errors.New("default global networks admin group not found")
+}
+
+func GetDefaultGlobalNetworksUserGroup() (models.UserGroup, error) {
+	groups, err := ListUserGroups()
+	if err != nil {
+		return models.UserGroup{}, err
+	}
+
+	for _, group := range groups {
+		if group.Default && group.Name == globalNetworksUserGroupName {
+			return group, nil
+		}
+	}
+
+	return models.UserGroup{}, errors.New("default global networks user group not found")
+}
+
+func GetDefaultNetworkAdminGroup(networkID models.NetworkID) (models.UserGroup, error) {
+	groups, err := ListUserGroups()
+	if err != nil {
+		return models.UserGroup{}, err
+	}
+
+	groupName := fmt.Sprintf("%s Admin Group", networkID)
+	for _, group := range groups {
+		if group.Default && group.Name == groupName {
+			return group, nil
+		}
+	}
+
+	return models.UserGroup{}, errors.New("default network admin group not found")
+}
+
+func GetDefaultNetworkUserGroup(networkID models.NetworkID) (models.UserGroup, error) {
+	groups, err := ListUserGroups()
+	if err != nil {
+		return models.UserGroup{}, err
+	}
+
+	groupName := fmt.Sprintf("%s User Group", networkID)
+	for _, group := range groups {
+		if group.Default && group.Name == groupName {
+			return group, nil
+		}
+	}
+
+	return models.UserGroup{}, errors.New("default network user group not found")
+}
+
 // ListUserGroups - lists user groups
 func ListUserGroups() ([]models.UserGroup, error) {
 	data, err := database.FetchRecords(database.USER_GROUPS_TABLE_NAME)
@@ -1128,6 +1205,9 @@ func CreateDefaultUserPolicies(netID models.NetworkID) {
 	}
 
 	if !logic.IsAclExists(fmt.Sprintf("%s.%s-grp", netID, models.NetworkAdmin)) {
+		globalAdminGroup, _ := GetDefaultGlobalNetworksAdminGroup()
+		networkAdminGroup, _ := GetDefaultNetworkAdminGroup(netID)
+
 		defaultUserAcl := models.Acl{
 			ID:          fmt.Sprintf("%s.%s-grp", netID, models.NetworkAdmin),
 			Name:        "Network Admin",
@@ -1140,11 +1220,11 @@ func CreateDefaultUserPolicies(netID models.NetworkID) {
 			Src: []models.AclPolicyTag{
 				{
 					ID:    models.UserGroupAclID,
-					Value: fmt.Sprintf("%s-%s-grp", netID, models.NetworkAdmin),
+					Value: globalAdminGroup.ID.String(),
 				},
 				{
 					ID:    models.UserGroupAclID,
-					Value: fmt.Sprintf("global-%s-grp", models.NetworkAdmin),
+					Value: networkAdminGroup.ID.String(),
 				},
 			},
 			Dst: []models.AclPolicyTag{
@@ -1161,6 +1241,9 @@ func CreateDefaultUserPolicies(netID models.NetworkID) {
 	}
 
 	if !logic.IsAclExists(fmt.Sprintf("%s.%s-grp", netID, models.NetworkUser)) {
+		globalUserGroup, _ := GetDefaultGlobalNetworksUserGroup()
+		networkUserGroup, _ := GetDefaultNetworkUserGroup(netID)
+
 		defaultUserAcl := models.Acl{
 			ID:          fmt.Sprintf("%s.%s-grp", netID, models.NetworkUser),
 			Name:        "Network User",
@@ -1173,11 +1256,11 @@ func CreateDefaultUserPolicies(netID models.NetworkID) {
 			Src: []models.AclPolicyTag{
 				{
 					ID:    models.UserGroupAclID,
-					Value: fmt.Sprintf("%s-%s-grp", netID, models.NetworkUser),
+					Value: globalUserGroup.ID.String(),
 				},
 				{
 					ID:    models.UserGroupAclID,
-					Value: fmt.Sprintf("global-%s-grp", models.NetworkUser),
+					Value: networkUserGroup.ID.String(),
 				},
 			},
 
@@ -1216,5 +1299,8 @@ func AddGlobalNetRolesToAdmins(u *models.User) {
 		return
 	}
 	u.UserGroups = make(map[models.UserGroupID]struct{})
-	u.UserGroups[models.UserGroupID(fmt.Sprintf("global-%s-grp", models.NetworkAdmin))] = struct{}{}
+
+	globalAdminGroup, _ := GetDefaultGlobalNetworksAdminGroup()
+
+	u.UserGroups[globalAdminGroup.ID] = struct{}{}
 }