Просмотр исходного кода

NET-1227: User Cli cmds Update (#3064)

* generalise smtp config

* copy over smtp vars

* env new line

* fix master key api access

* comment user tests

* fix network and user invite for master key access

* remove email sender type

* user mgmt commands

* check user role on CE

* user role nmtcl cmds

* user groups commands

* fix role and groups command

* fix user create cmd

* add usage info

* rm user role check

* fix user update cmd

* fix static check
Abhishek K 1 год назад
Родитель
Сommit
5a4d0663da

+ 29 - 4
cli/cmd/user/create.go

@@ -1,6 +1,8 @@
 package user
 
 import (
+	"strings"
+
 	"github.com/gravitl/netmaker/cli/functions"
 	"github.com/gravitl/netmaker/models"
 	"github.com/spf13/cobra"
@@ -12,18 +14,41 @@ var userCreateCmd = &cobra.Command{
 	Short: "Create a new user",
 	Long:  `Create a new user`,
 	Run: func(cmd *cobra.Command, args []string) {
-		user := &models.User{UserName: username, Password: password, IsAdmin: admin}
+		user := &models.User{UserName: username, Password: password, PlatformRoleID: models.UserRoleID(platformID)}
+		if len(networkRoles) > 0 {
+			netRolesMap := make(map[models.NetworkID]map[models.UserRoleID]struct{})
+			for netID, netRoles := range networkRoles {
+				roleMap := make(map[models.UserRoleID]struct{})
+				for _, roleID := range strings.Split(netRoles, " ") {
+					roleMap[models.UserRoleID(roleID)] = struct{}{}
+				}
+				netRolesMap[models.NetworkID(netID)] = roleMap
+			}
+			user.NetworkRoles = netRolesMap
+		}
+		if len(groups) > 0 {
+			grMap := make(map[models.UserGroupID]struct{})
+			for _, groupID := range groups {
+				grMap[models.UserGroupID(groupID)] = struct{}{}
+			}
+			user.UserGroups = grMap
+		}
+
 		functions.PrettyPrint(functions.CreateUser(user))
 	},
 }
 
 func init() {
+
 	userCreateCmd.Flags().StringVar(&username, "name", "", "Name of the user")
 	userCreateCmd.Flags().StringVar(&password, "password", "", "Password of the user")
+	userCreateCmd.Flags().StringVarP(&platformID, "platform-role", "r", models.ServiceUser.String(),
+		"Platform Role of the user; run `nmctl roles list` to see available user roles")
 	userCreateCmd.MarkFlagRequired("name")
 	userCreateCmd.MarkFlagRequired("password")
-	userCreateCmd.Flags().BoolVar(&admin, "admin", false, "Make the user an admin ?")
-	userCreateCmd.Flags().StringVar(&networks, "networks", "", "List of networks the user will access to (comma separated)")
-	userCreateCmd.Flags().StringVar(&groups, "groups", "", "List of user groups the user will be part of (comma separated)")
+	userCreateCmd.PersistentFlags().StringToStringVarP(&networkRoles, "network-roles", "n", nil,
+		"Mapping of networkID and list of roles user will be part of (comma separated)")
+	userCreateCmd.Flags().BoolVar(&admin, "admin", false, "Make the user an admin ? (deprecated v0.25.0 onwards)")
+	userCreateCmd.Flags().StringArrayVarP(&groups, "groups", "g", nil, "List of user groups the user will be part of (comma separated)")
 	rootCmd.AddCommand(userCreateCmd)
 }

+ 6 - 5
cli/cmd/user/flags.go

@@ -1,9 +1,10 @@
 package user
 
 var (
-	username string
-	password string
-	admin    bool
-	networks string
-	groups   string
+	username     string
+	password     string
+	platformID   string
+	admin        bool
+	networkRoles map[string]string
+	groups       []string
 )

+ 118 - 0
cli/cmd/user/groups.go

@@ -0,0 +1,118 @@
+package user
+
+import (
+	"fmt"
+	"os"
+	"strings"
+
+	"github.com/gravitl/netmaker/cli/cmd/commons"
+	"github.com/gravitl/netmaker/cli/functions"
+	"github.com/guumaster/tablewriter"
+	"github.com/spf13/cobra"
+)
+
+var userGroupCmd = &cobra.Command{
+	Use:   "group",
+	Args:  cobra.NoArgs,
+	Short: "Manage User Groups",
+	Long:  `Manage User Groups`,
+}
+
+var userGroupListCmd = &cobra.Command{
+	Use:   "list",
+	Args:  cobra.NoArgs,
+	Short: "List all user groups",
+	Long:  `List all user groups`,
+	Run: func(cmd *cobra.Command, args []string) {
+		data := functions.ListUserGrps()
+		switch commons.OutputFormat {
+		case commons.JsonOutput:
+			functions.PrettyPrint(data)
+		default:
+			table := tablewriter.NewWriter(os.Stdout)
+			h := []string{"ID", "MetaData", "Network Roles"}
+			table.SetHeader(h)
+			for _, d := range data {
+
+				roleInfoStr := ""
+				for netID, netRoleMap := range d.NetworkRoles {
+					roleList := []string{}
+					for roleID := range netRoleMap {
+						roleList = append(roleList, roleID.String())
+					}
+					roleInfoStr += fmt.Sprintf("[%s]: %s", netID, strings.Join(roleList, ","))
+				}
+				e := []string{d.ID.String(), d.MetaData, roleInfoStr}
+				table.Append(e)
+			}
+			table.Render()
+		}
+	},
+}
+
+var userGroupCreateCmd = &cobra.Command{
+	Use:   "create",
+	Args:  cobra.NoArgs,
+	Short: "create user group",
+	Long:  `create user group`,
+	Run: func(cmd *cobra.Command, args []string) {
+		fmt.Println("CLI doesn't support creation of groups currently. Visit the dashboard to create one or refer to our api documentation https://docs.v2.netmaker.io/reference")
+	},
+}
+
+var userGroupDeleteCmd = &cobra.Command{
+	Use:   "delete [groupID]",
+	Args:  cobra.ExactArgs(1),
+	Short: "delete user group",
+	Long:  `delete user group`,
+	Run: func(cmd *cobra.Command, args []string) {
+		resp := functions.DeleteUserGrp(args[0])
+		if resp != nil {
+			fmt.Println(resp.Message)
+		}
+	},
+}
+
+var userGroupGetCmd = &cobra.Command{
+	Use:   "get [groupID]",
+	Args:  cobra.ExactArgs(1),
+	Short: "get user group",
+	Long:  `get user group`,
+	Run: func(cmd *cobra.Command, args []string) {
+		data := functions.GetUserGrp(args[0])
+		switch commons.OutputFormat {
+		case commons.JsonOutput:
+			functions.PrettyPrint(data)
+		default:
+			table := tablewriter.NewWriter(os.Stdout)
+			h := []string{"ID", "MetaData", "Network Roles"}
+			table.SetHeader(h)
+			roleInfoStr := ""
+			for netID, netRoleMap := range data.NetworkRoles {
+				roleList := []string{}
+				for roleID := range netRoleMap {
+					roleList = append(roleList, roleID.String())
+				}
+				roleInfoStr += fmt.Sprintf("[%s]: %s", netID, strings.Join(roleList, ","))
+			}
+			e := []string{data.ID.String(), data.MetaData, roleInfoStr}
+			table.Append(e)
+			table.Render()
+		}
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(userGroupCmd)
+	// list roles cmd
+	userGroupCmd.AddCommand(userGroupListCmd)
+
+	// create roles cmd
+	userGroupCmd.AddCommand(userGroupCreateCmd)
+
+	// delete role cmd
+	userGroupCmd.AddCommand(userGroupDeleteCmd)
+
+	// Get Role
+	userGroupCmd.AddCommand(userGroupGetCmd)
+}

+ 7 - 3
cli/cmd/user/list.go

@@ -2,7 +2,7 @@ package user
 
 import (
 	"os"
-	"strconv"
+	"strings"
 
 	"github.com/gravitl/netmaker/cli/cmd/commons"
 	"github.com/gravitl/netmaker/cli/functions"
@@ -22,9 +22,13 @@ var userListCmd = &cobra.Command{
 			functions.PrettyPrint(data)
 		default:
 			table := tablewriter.NewWriter(os.Stdout)
-			table.SetHeader([]string{"Name", "SuperAdmin", "Admin"})
+			table.SetHeader([]string{"Name", "Platform Role", "Groups"})
 			for _, d := range *data {
-				table.Append([]string{d.UserName, strconv.FormatBool(d.IsSuperAdmin), strconv.FormatBool(d.IsAdmin)})
+				g := []string{}
+				for gID := range d.UserGroups {
+					g = append(g, gID.String())
+				}
+				table.Append([]string{d.UserName, d.PlatformRoleID.String(), strings.Join(g, ",")})
 			}
 			table.Render()
 		}

+ 121 - 0
cli/cmd/user/roles.go

@@ -0,0 +1,121 @@
+package user
+
+import (
+	"fmt"
+	"os"
+	"strconv"
+
+	"github.com/gravitl/netmaker/cli/cmd/commons"
+	"github.com/gravitl/netmaker/cli/functions"
+	"github.com/guumaster/tablewriter"
+	"github.com/spf13/cobra"
+)
+
+var userRoleCmd = &cobra.Command{
+	Use:   "role",
+	Args:  cobra.NoArgs,
+	Short: "Manage User Roles",
+	Long:  `Manage User Roles`,
+}
+
+// List Roles
+var (
+	platformRoles bool
+)
+var userRoleListCmd = &cobra.Command{
+	Use:   "list",
+	Args:  cobra.NoArgs,
+	Short: "List all user roles",
+	Long:  `List all user roles`,
+	Run: func(cmd *cobra.Command, args []string) {
+		data := functions.ListUserRoles()
+		switch commons.OutputFormat {
+		case commons.JsonOutput:
+			functions.PrettyPrint(data)
+		default:
+			table := tablewriter.NewWriter(os.Stdout)
+			h := []string{"ID", "Default", "Dashboard Access", "Full Access"}
+
+			if !platformRoles {
+				h = append(h, "Network")
+			}
+			table.SetHeader(h)
+			for _, d := range data {
+				e := []string{d.ID.String(), strconv.FormatBool(d.Default), strconv.FormatBool(d.DenyDashboardAccess), strconv.FormatBool(d.FullAccess)}
+				if !platformRoles {
+					e = append(e, d.NetworkID.String())
+				}
+				table.Append(e)
+			}
+			table.Render()
+		}
+	},
+}
+
+var userRoleCreateCmd = &cobra.Command{
+	Use:   "create",
+	Args:  cobra.NoArgs,
+	Short: "create user role",
+	Long:  `create user role`,
+	Run: func(cmd *cobra.Command, args []string) {
+		fmt.Println("CLI doesn't support creation of roles currently. Visit the dashboard to create one or refer to our api documentation https://docs.v2.netmaker.io/reference")
+	},
+}
+
+var userRoleDeleteCmd = &cobra.Command{
+	Use:   "delete [roleID]",
+	Args:  cobra.ExactArgs(1),
+	Short: "delete user role",
+	Long:  `delete user role`,
+	Run: func(cmd *cobra.Command, args []string) {
+		resp := functions.DeleteUserRole(args[0])
+		if resp != nil {
+			fmt.Println(resp.Message)
+		}
+	},
+}
+
+var userRoleGetCmd = &cobra.Command{
+	Use:   "get [roleID]",
+	Args:  cobra.ExactArgs(1),
+	Short: "get user role",
+	Long:  `get user role`,
+	Run: func(cmd *cobra.Command, args []string) {
+		d := functions.GetUserRole(args[0])
+		switch commons.OutputFormat {
+		case commons.JsonOutput:
+			functions.PrettyPrint(d)
+		default:
+			table := tablewriter.NewWriter(os.Stdout)
+			h := []string{"ID", "Default Role", "Dashboard Access", "Full Access"}
+
+			if d.NetworkID != "" {
+				h = append(h, "Network")
+			}
+			table.SetHeader(h)
+			e := []string{d.ID.String(), strconv.FormatBool(d.Default), strconv.FormatBool(!d.DenyDashboardAccess), strconv.FormatBool(d.FullAccess)}
+			if !platformRoles {
+				e = append(e, d.NetworkID.String())
+			}
+			table.Append(e)
+			table.Render()
+		}
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(userRoleCmd)
+	// list roles cmd
+	userRoleListCmd.Flags().BoolVar(&platformRoles, "platform-roles", true,
+		"set to false to list network roles. By default it will only list platform roles")
+	userRoleCmd.AddCommand(userRoleListCmd)
+
+	// create roles cmd
+	userRoleCmd.AddCommand(userRoleCreateCmd)
+
+	// delete role cmd
+	userRoleCmd.AddCommand(userRoleDeleteCmd)
+
+	// Get Role
+	userRoleCmd.AddCommand(userRoleGetCmd)
+}

+ 32 - 4
cli/cmd/user/update.go

@@ -1,6 +1,8 @@
 package user
 
 import (
+	"strings"
+
 	"github.com/gravitl/netmaker/cli/functions"
 	"github.com/gravitl/netmaker/models"
 	"github.com/spf13/cobra"
@@ -12,14 +14,40 @@ var userUpdateCmd = &cobra.Command{
 	Short: "Update a user",
 	Long:  `Update a user`,
 	Run: func(cmd *cobra.Command, args []string) {
-		user := &models.User{UserName: args[0], IsAdmin: admin}
+		user := &models.User{UserName: args[0]}
+		if platformID != "" {
+			user.PlatformRoleID = models.UserRoleID(platformID)
+		}
+		if len(networkRoles) > 0 {
+			netRolesMap := make(map[models.NetworkID]map[models.UserRoleID]struct{})
+			for netID, netRoles := range networkRoles {
+				roleMap := make(map[models.UserRoleID]struct{})
+				for _, roleID := range strings.Split(netRoles, ",") {
+					roleMap[models.UserRoleID(roleID)] = struct{}{}
+				}
+				netRolesMap[models.NetworkID(netID)] = roleMap
+			}
+			user.NetworkRoles = netRolesMap
+		}
+		if len(groups) > 0 {
+			grMap := make(map[models.UserGroupID]struct{})
+			for _, groupID := range groups {
+				grMap[models.UserGroupID(groupID)] = struct{}{}
+			}
+			user.UserGroups = grMap
+		}
 		functions.PrettyPrint(functions.UpdateUser(user))
 	},
 }
 
 func init() {
-	userUpdateCmd.Flags().BoolVar(&admin, "admin", false, "Make the user an admin ?")
-	userUpdateCmd.Flags().StringVar(&networks, "networks", "", "List of networks the user will access to (comma separated)")
-	userUpdateCmd.Flags().StringVar(&groups, "groups", "", "List of user groups the user will be part of (comma separated)")
+
+	userUpdateCmd.Flags().StringVar(&password, "password", "", "Password of the user")
+	userUpdateCmd.Flags().StringVarP(&platformID, "platform-role", "r", "",
+		"Platform Role of the user; run `nmctl roles list` to see available user roles")
+	userUpdateCmd.PersistentFlags().StringToStringVarP(&networkRoles, "network-roles", "n", nil,
+		"Mapping of networkID and list of roles user will be part of (comma separated)")
+	userUpdateCmd.Flags().BoolVar(&admin, "admin", false, "Make the user an admin ? (deprecated v0.25.0 onwards)")
+	userUpdateCmd.Flags().StringArrayVarP(&groups, "groups", "g", nil, "List of user groups the user will be part of (comma separated)")
 	rootCmd.AddCommand(userUpdateCmd)
 }

+ 1 - 1
cli/config/config.go

@@ -86,7 +86,7 @@ func GetCurrentContext() (name string, ctx Context) {
 			return
 		}
 	}
-	log.Fatalf("No current context set, do so via `netmaker context use <name>`")
+	log.Fatalf("No current context set, do so via `nmctl context use <name>`")
 	return
 }
 

+ 38 - 1
cli/functions/user.go

@@ -1,6 +1,8 @@
 package functions
 
 import (
+	"encoding/json"
+	"fmt"
 	"net/http"
 
 	"github.com/gravitl/netmaker/models"
@@ -18,7 +20,7 @@ func CreateUser(payload *models.User) *models.User {
 
 // UpdateUser - update a user
 func UpdateUser(payload *models.User) *models.User {
-	return request[models.User](http.MethodPut, "/api/users/networks/"+payload.UserName, payload)
+	return request[models.User](http.MethodPut, "/api/users/"+payload.UserName, payload)
 }
 
 // DeleteUser - delete a user
@@ -35,3 +37,38 @@ func GetUser(username string) *models.User {
 func ListUsers() *[]models.ReturnUser {
 	return request[[]models.ReturnUser](http.MethodGet, "/api/users", nil)
 }
+
+func ListUserRoles() (roles []models.UserRolePermissionTemplate) {
+	resp := request[models.SuccessResponse](http.MethodGet, "/api/v1/users/roles", nil)
+	d, _ := json.Marshal(resp.Response)
+	json.Unmarshal(d, &roles)
+	return
+}
+
+func DeleteUserRole(roleID string) *models.SuccessResponse {
+	return request[models.SuccessResponse](http.MethodDelete, fmt.Sprintf("/api/v1/users/role?role_id=%s", roleID), nil)
+}
+func GetUserRole(roleID string) (role models.UserRolePermissionTemplate) {
+	resp := request[models.SuccessResponse](http.MethodGet, fmt.Sprintf("/api/v1/users/role?role_id=%s", roleID), nil)
+	d, _ := json.Marshal(resp.Response)
+	json.Unmarshal(d, &role)
+	return
+}
+
+func ListUserGrps() (groups []models.UserGroup) {
+	resp := request[models.SuccessResponse](http.MethodGet, "/api/v1/users/groups", nil)
+	d, _ := json.Marshal(resp.Response)
+	json.Unmarshal(d, &groups)
+	return
+}
+
+func DeleteUserGrp(grpID string) *models.SuccessResponse {
+	return request[models.SuccessResponse](http.MethodDelete, fmt.Sprintf("/api/v1/users/group?group_id=%s", grpID), nil)
+}
+
+func GetUserGrp(grpID string) (group models.UserGroup) {
+	resp := request[models.SuccessResponse](http.MethodGet, fmt.Sprintf("/api/v1/users/group?group_id=%s", grpID), nil)
+	d, _ := json.Marshal(resp.Response)
+	json.Unmarshal(d, &group)
+	return
+}

+ 4 - 2
logic/auth.go

@@ -297,7 +297,9 @@ func UpdateUser(userchange, user *models.User) (*models.User, error) {
 	}
 	// Reset Gw Access for service users
 	go UpdateUserGwAccess(*user, *userchange)
-	user.PlatformRoleID = userchange.PlatformRoleID
+	if userchange.PlatformRoleID != "" {
+		user.PlatformRoleID = userchange.PlatformRoleID
+	}
 	user.UserGroups = userchange.UserGroups
 	user.NetworkRoles = userchange.NetworkRoles
 	err := ValidateUser(user)
@@ -325,7 +327,7 @@ func ValidateUser(user *models.User) error {
 	// check if role is valid
 	_, err := GetRole(user.PlatformRoleID)
 	if err != nil {
-		return err
+		return errors.New("failed to fetch platform role " + user.PlatformRoleID.String())
 	}
 	v := validator.New()
 	_ = v.RegisterValidation("in_charset", func(fl validator.FieldLevel) bool {