From 2f3682f3ca694285a86be5e2ce48d1cecc6bc481 Mon Sep 17 00:00:00 2001 From: Sergiu Ghitea <28300158+sergiught@users.noreply.github.com> Date: Tue, 17 Jan 2023 16:02:02 +0100 Subject: [PATCH 1/3] Add ability to view a user's assigned roles Update user roles number flat help text --- docs/auth0_users.md | 1 + docs/auth0_users_create.md | 1 + docs/auth0_users_delete.md | 1 + docs/auth0_users_import.md | 1 + docs/auth0_users_open.md | 1 + docs/auth0_users_roles.md | 11 ++++ docs/auth0_users_roles_show.md | 45 +++++++++++++++ docs/auth0_users_search.md | 1 + docs/auth0_users_show.md | 1 + docs/auth0_users_unblock.md | 1 + docs/auth0_users_update.md | 1 + internal/auth0/user.go | 5 +- internal/cli/users.go | 3 +- internal/cli/users_roles.go | 97 ++++++++++++++++++++++++++++++++ internal/display/roles.go | 18 ++++++ test/integration/test-cases.yaml | 4 ++ 16 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 docs/auth0_users_roles.md create mode 100644 docs/auth0_users_roles_show.md create mode 100644 internal/cli/users_roles.go diff --git a/docs/auth0_users.md b/docs/auth0_users.md index b7a125da9..c86055516 100644 --- a/docs/auth0_users.md +++ b/docs/auth0_users.md @@ -12,6 +12,7 @@ Manage resources for users. - [auth0 users delete](auth0_users_delete.md) - Delete a user - [auth0 users import](auth0_users_import.md) - Import users from schema - [auth0 users open](auth0_users_open.md) - Open the user's settings page +- [auth0 users roles](auth0_users_roles.md) - Manage a user's roles - [auth0 users search](auth0_users_search.md) - Search for users - [auth0 users show](auth0_users_show.md) - Show an existing user - [auth0 users unblock](auth0_users_unblock.md) - Remove brute-force protection blocks for a given user diff --git a/docs/auth0_users_create.md b/docs/auth0_users_create.md index bc42acf86..da83f238c 100644 --- a/docs/auth0_users_create.md +++ b/docs/auth0_users_create.md @@ -54,6 +54,7 @@ auth0 users create [flags] - [auth0 users delete](auth0_users_delete.md) - Delete a user - [auth0 users import](auth0_users_import.md) - Import users from schema - [auth0 users open](auth0_users_open.md) - Open the user's settings page +- [auth0 users roles](auth0_users_roles.md) - Manage a user's roles - [auth0 users search](auth0_users_search.md) - Search for users - [auth0 users show](auth0_users_show.md) - Show an existing user - [auth0 users unblock](auth0_users_unblock.md) - Remove brute-force protection blocks for a given user diff --git a/docs/auth0_users_delete.md b/docs/auth0_users_delete.md index 1ab6d2c91..77c8a0235 100644 --- a/docs/auth0_users_delete.md +++ b/docs/auth0_users_delete.md @@ -48,6 +48,7 @@ auth0 users delete [flags] - [auth0 users delete](auth0_users_delete.md) - Delete a user - [auth0 users import](auth0_users_import.md) - Import users from schema - [auth0 users open](auth0_users_open.md) - Open the user's settings page +- [auth0 users roles](auth0_users_roles.md) - Manage a user's roles - [auth0 users search](auth0_users_search.md) - Search for users - [auth0 users show](auth0_users_show.md) - Show an existing user - [auth0 users unblock](auth0_users_unblock.md) - Remove brute-force protection blocks for a given user diff --git a/docs/auth0_users_import.md b/docs/auth0_users_import.md index f9da93f36..ffac67f59 100644 --- a/docs/auth0_users_import.md +++ b/docs/auth0_users_import.md @@ -49,6 +49,7 @@ auth0 users import [flags] - [auth0 users delete](auth0_users_delete.md) - Delete a user - [auth0 users import](auth0_users_import.md) - Import users from schema - [auth0 users open](auth0_users_open.md) - Open the user's settings page +- [auth0 users roles](auth0_users_roles.md) - Manage a user's roles - [auth0 users search](auth0_users_search.md) - Search for users - [auth0 users show](auth0_users_show.md) - Show an existing user - [auth0 users unblock](auth0_users_unblock.md) - Remove brute-force protection blocks for a given user diff --git a/docs/auth0_users_open.md b/docs/auth0_users_open.md index 3560d59d6..8417ea860 100644 --- a/docs/auth0_users_open.md +++ b/docs/auth0_users_open.md @@ -37,6 +37,7 @@ auth0 users open [flags] - [auth0 users delete](auth0_users_delete.md) - Delete a user - [auth0 users import](auth0_users_import.md) - Import users from schema - [auth0 users open](auth0_users_open.md) - Open the user's settings page +- [auth0 users roles](auth0_users_roles.md) - Manage a user's roles - [auth0 users search](auth0_users_search.md) - Search for users - [auth0 users show](auth0_users_show.md) - Show an existing user - [auth0 users unblock](auth0_users_unblock.md) - Remove brute-force protection blocks for a given user diff --git a/docs/auth0_users_roles.md b/docs/auth0_users_roles.md new file mode 100644 index 000000000..3aaa3c0c3 --- /dev/null +++ b/docs/auth0_users_roles.md @@ -0,0 +1,11 @@ +--- +layout: default +--- +# auth0 users roles + +Manage a user's assigned roles. To learn more about roles and their behavior, read [Role-based Access Control](https://auth0.com/docs/manage-users/access-control/rbac). + +## Commands + +- [auth0 users roles show](auth0_users_roles_show.md) - Show a user's roles + diff --git a/docs/auth0_users_roles_show.md b/docs/auth0_users_roles_show.md new file mode 100644 index 000000000..5766b5b6b --- /dev/null +++ b/docs/auth0_users_roles_show.md @@ -0,0 +1,45 @@ +--- +layout: default +--- +# auth0 users roles show + +Display information about an existing user's assigned roles. + +## Usage +``` +auth0 users roles show [flags] +``` + +## Examples + +``` + auth0 users roles show + auth0 users roles show + auth0 users roles show --number 100 + auth0 users roles show -n 100 --json +``` + + +## Flags + +``` + --json Output in json format. + -n, --number int Number of user roles to retrieve. Minimum 1, maximum 1000. (default 50) +``` + + +## InheritedFlags + +``` + --debug Enable debug mode. + --no-color Disable colors. + --no-input Disable interactivity. + --tenant string Specific tenant to use. +``` + + +## Related Commands + +- [auth0 users roles show](auth0_users_roles_show.md) - Show a user's roles + + diff --git a/docs/auth0_users_search.md b/docs/auth0_users_search.md index 5e2db2ba9..e56204b52 100644 --- a/docs/auth0_users_search.md +++ b/docs/auth0_users_search.md @@ -48,6 +48,7 @@ auth0 users search [flags] - [auth0 users delete](auth0_users_delete.md) - Delete a user - [auth0 users import](auth0_users_import.md) - Import users from schema - [auth0 users open](auth0_users_open.md) - Open the user's settings page +- [auth0 users roles](auth0_users_roles.md) - Manage a user's roles - [auth0 users search](auth0_users_search.md) - Search for users - [auth0 users show](auth0_users_show.md) - Show an existing user - [auth0 users unblock](auth0_users_unblock.md) - Remove brute-force protection blocks for a given user diff --git a/docs/auth0_users_show.md b/docs/auth0_users_show.md index 2fd732dff..2e040d1cb 100644 --- a/docs/auth0_users_show.md +++ b/docs/auth0_users_show.md @@ -43,6 +43,7 @@ auth0 users show [flags] - [auth0 users delete](auth0_users_delete.md) - Delete a user - [auth0 users import](auth0_users_import.md) - Import users from schema - [auth0 users open](auth0_users_open.md) - Open the user's settings page +- [auth0 users roles](auth0_users_roles.md) - Manage a user's roles - [auth0 users search](auth0_users_search.md) - Search for users - [auth0 users show](auth0_users_show.md) - Show an existing user - [auth0 users unblock](auth0_users_unblock.md) - Remove brute-force protection blocks for a given user diff --git a/docs/auth0_users_unblock.md b/docs/auth0_users_unblock.md index c9b3e5706..f836a8c94 100644 --- a/docs/auth0_users_unblock.md +++ b/docs/auth0_users_unblock.md @@ -36,6 +36,7 @@ auth0 users unblock [flags] - [auth0 users delete](auth0_users_delete.md) - Delete a user - [auth0 users import](auth0_users_import.md) - Import users from schema - [auth0 users open](auth0_users_open.md) - Open the user's settings page +- [auth0 users roles](auth0_users_roles.md) - Manage a user's roles - [auth0 users search](auth0_users_search.md) - Search for users - [auth0 users show](auth0_users_show.md) - Show an existing user - [auth0 users unblock](auth0_users_unblock.md) - Remove brute-force protection blocks for a given user diff --git a/docs/auth0_users_update.md b/docs/auth0_users_update.md index b5a8b3779..bb8861b10 100644 --- a/docs/auth0_users_update.md +++ b/docs/auth0_users_update.md @@ -52,6 +52,7 @@ auth0 users update [flags] - [auth0 users delete](auth0_users_delete.md) - Delete a user - [auth0 users import](auth0_users_import.md) - Import users from schema - [auth0 users open](auth0_users_open.md) - Open the user's settings page +- [auth0 users roles](auth0_users_roles.md) - Manage a user's roles - [auth0 users search](auth0_users_search.md) - Search for users - [auth0 users show](auth0_users_show.md) - Show an existing user - [auth0 users unblock](auth0_users_unblock.md) - Remove brute-force protection blocks for a given user diff --git a/internal/auth0/user.go b/internal/auth0/user.go index 1f3ce9cb8..3ffd29b9d 100644 --- a/internal/auth0/user.go +++ b/internal/auth0/user.go @@ -3,7 +3,7 @@ package auth0 import "github.com/auth0/go-auth0/management" type UserAPI interface { - // Retrieves a list of blocked IP addresses of a particular user. + // Blocks retrieves a list of blocked IP addresses of a particular user. Blocks(id string, opts ...management.RequestOption) ([]*management.UserBlock, error) // Unblock a user that was blocked due to an excessive amount of incorrectly @@ -27,4 +27,7 @@ type UserAPI interface { // Search for users Search(opts ...management.RequestOption) (us *management.UserList, err error) + + // Roles lists all roles associated with a user. + Roles(id string, opts ...management.RequestOption) (r *management.RoleList, err error) } diff --git a/internal/cli/users.go b/internal/cli/users.go index 4b72a569d..d97a462d1 100644 --- a/internal/cli/users.go +++ b/internal/cli/users.go @@ -121,8 +121,9 @@ func usersCmd(cli *cli) *cobra.Command { cmd.AddCommand(searchUsersCmd(cli)) cmd.AddCommand(createUserCmd(cli)) cmd.AddCommand(showUserCmd(cli)) - cmd.AddCommand(deleteUserCmd(cli)) cmd.AddCommand(updateUserCmd(cli)) + cmd.AddCommand(deleteUserCmd(cli)) + cmd.AddCommand(userRolesCmd(cli)) cmd.AddCommand(openUserCmd(cli)) cmd.AddCommand(userBlocksCmd(cli)) cmd.AddCommand(deleteUserBlocksCmd(cli)) diff --git a/internal/cli/users_roles.go b/internal/cli/users_roles.go new file mode 100644 index 000000000..281c6ea93 --- /dev/null +++ b/internal/cli/users_roles.go @@ -0,0 +1,97 @@ +package cli + +import ( + "fmt" + + "github.com/auth0/go-auth0/management" + "github.com/spf13/cobra" +) + +var ( + userRolesNumber = Flag{ + Name: "Number", + LongForm: "number", + ShortForm: "n", + Help: "Number of user roles to retrieve. Minimum 1, maximum 1000.", + } +) + +func userRolesCmd(cli *cli) *cobra.Command { + cmd := &cobra.Command{ + Use: "roles", + Short: "Manage a user's roles", + Long: "Manage a user's assigned roles. To learn more about roles and their behavior, read " + + "[Role-based Access Control](https://auth0.com/docs/manage-users/access-control/rbac).", + } + + cmd.SetUsageTemplate(resourceUsageTemplate()) + cmd.AddCommand(showUserRolesCmd(cli)) + + return cmd +} + +func showUserRolesCmd(cli *cli) *cobra.Command { + var inputs struct { + ID string + Number int + } + + cmd := &cobra.Command{ + Use: "show", + Args: cobra.MaximumNArgs(1), + Short: "Show a user's roles", + Long: "Display information about an existing user's assigned roles.", + Example: ` auth0 users roles show + auth0 users roles show + auth0 users roles show --number 100 + auth0 users roles show -n 100 --json`, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + if err := userID.Ask(cmd, &inputs.ID); err != nil { + return err + } + } else { + inputs.ID = args[0] + } + + if inputs.Number < 1 || inputs.Number > 1000 { + return fmt.Errorf("number flag invalid, please pass a number between 1 and 1000") + } + + list, err := getWithPagination( + cmd.Context(), + inputs.Number, + func(opts ...management.RequestOption) (result []interface{}, hasNext bool, err error) { + userRoleList, err := cli.api.User.Roles(inputs.ID, opts...) + if err != nil { + return nil, false, err + } + + var output []interface{} + for _, userRole := range userRoleList.Roles { + output = append(output, userRole) + } + + return output, userRoleList.HasNext(), nil + }, + ) + if err != nil { + return fmt.Errorf("failed to find roles for user with ID %s: %w", inputs.ID, err) + } + + var userRoles []*management.Role + for _, item := range list { + userRoles = append(userRoles, item.(*management.Role)) + } + + cli.renderer.UserRoleList(userRoles) + + return nil + }, + } + + cmd.Flags().BoolVar(&cli.json, "json", false, "Output in json format.") + userRolesNumber.RegisterInt(cmd, &inputs.Number, defaultPageSize) + + return cmd +} diff --git a/internal/display/roles.go b/internal/display/roles.go index c2415a9fb..13f5bd0fb 100644 --- a/internal/display/roles.go +++ b/internal/display/roles.go @@ -58,6 +58,24 @@ func (r *Renderer) RoleList(roles []*management.Role) { r.Results(res) } +func (r *Renderer) UserRoleList(roles []*management.Role) { + resource := "roles assigned to user" + r.Heading(fmt.Sprintf("%s (%d)", resource, len(roles))) + + if len(roles) == 0 { + r.EmptyState(resource) + r.Infof("Use 'auth0 users roles assign' to assign roles to a user.") + return + } + + var res []View + for _, role := range roles { + res = append(res, makeRoleView(role)) + } + + r.Results(res) +} + func (r *Renderer) RoleShow(role *management.Role) { r.Heading("role") r.Result(makeRoleView(role)) diff --git a/test/integration/test-cases.yaml b/test/integration/test-cases.yaml index 615a1a34c..6c496dec2 100644 --- a/test/integration/test-cases.yaml +++ b/test/integration/test-cases.yaml @@ -464,6 +464,10 @@ tests: email: betteruser@example.com # Name is not being displayed, hence using email exit-code: 0 + users roles show: + command: auth0 users roles show $(cat ./test/integration/identifiers/user-id) + exit-code: 0 + # Test 'roles create' roles create and check data: command: auth0 roles create --name integration-test-role-new1 --description testRole --json --no-input From aaf01377c9fcc4ad6e1f67d38b7f7d0318420c18 Mon Sep 17 00:00:00 2001 From: Sergiu Ghitea <28300158+sergiught@users.noreply.github.com> Date: Tue, 17 Jan 2023 15:45:34 +0100 Subject: [PATCH 2/3] Abstract make test-integration logic into separate bash file --- Makefile | 5 +---- test/integration/scripts/run-test-suites.sh | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 test/integration/scripts/run-test-suites.sh diff --git a/Makefile b/Makefile index 8642502a4..456f3aa2a 100644 --- a/Makefile +++ b/Makefile @@ -140,10 +140,7 @@ test-unit: ## Run unit tests test-integration: $(GO_BIN)/commander ## Run integration tests. To run a specific test pass the FILTER var. Usage: `make test-integration FILTER="attack protection"` ${call print, "Running integration tests"} @$(MAKE) install # ensure fresh install prior to running test - auth0 login --domain ${AUTH0_CLI_CLIENT_DOMAIN} --client-id ${AUTH0_CLI_CLIENT_ID} --client-secret ${AUTH0_CLI_CLIENT_SECRET} && commander test ./test/integration/test-cases.yaml --filter "$(FILTER)"; \ - exit_code=$$?; \ - bash ./test/integration/scripts/test-cleanup.sh; \ - exit $$exit_code + @bash ./test/integration/scripts/run-test-suites.sh test-mocks: $(GO_BIN)/mockgen ## Generate testing mocks using mockgen ${call print, "Generating test mocks"} diff --git a/test/integration/scripts/run-test-suites.sh b/test/integration/scripts/run-test-suites.sh new file mode 100644 index 000000000..2c1161f06 --- /dev/null +++ b/test/integration/scripts/run-test-suites.sh @@ -0,0 +1,18 @@ +#! /bin/bash -v + +set -e + +auth0 login \ + --domain "${AUTH0_CLI_CLIENT_DOMAIN}" \ + --client-id "${AUTH0_CLI_CLIENT_ID}" \ + --client-secret "${AUTH0_CLI_CLIENT_SECRET}" + +set +e + +commander test --filter "$FILTER" --dir ./test/integration + +exit_code=$? + +bash ./test/integration/scripts/test-cleanup.sh + +exit $exit_code From 56b3dc0b4a87cfa9d246ba82aeb3c2dba71e7a04 Mon Sep 17 00:00:00 2001 From: Sergiu Ghitea <28300158+sergiught@users.noreply.github.com> Date: Tue, 17 Jan 2023 16:45:59 +0100 Subject: [PATCH 3/3] Update message when no roles assigned to user --- internal/display/roles.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/display/roles.go b/internal/display/roles.go index 13f5bd0fb..b1b087f2b 100644 --- a/internal/display/roles.go +++ b/internal/display/roles.go @@ -63,7 +63,7 @@ func (r *Renderer) UserRoleList(roles []*management.Role) { r.Heading(fmt.Sprintf("%s (%d)", resource, len(roles))) if len(roles) == 0 { - r.EmptyState(resource) + r.Output("No roles assigned to user.\n\n") r.Infof("Use 'auth0 users roles assign' to assign roles to a user.") return }