-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CLI-80: user-blocks commands with user_id #201
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
//go:generate mockgen -source=user.go -destination=user_mock.go -package=auth0 | ||
|
||
package auth0 | ||
|
||
import "gopkg.in/auth0.v5/management" | ||
|
||
type UserAPI interface { | ||
// 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 | ||
// provided credentials. | ||
Unblock(id string, opts ...management.RequestOption) error | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,110 @@ | ||||||
package cli | ||||||
|
||||||
import ( | ||||||
"errors" | ||||||
"fmt" | ||||||
|
||||||
"github.com/auth0/auth0-cli/internal/ansi" | ||||||
"github.com/spf13/cobra" | ||||||
"gopkg.in/auth0.v5/management" | ||||||
) | ||||||
|
||||||
var ( | ||||||
userID = Argument{ | ||||||
Name: "user_id", | ||||||
Help: "user_id of the user.", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
) | ||||||
|
||||||
func userBlocksCmd(cli *cli) *cobra.Command { | ||||||
cmd := &cobra.Command{ | ||||||
Use: "user-blocks", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please put it under There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a subcommand: |
||||||
Short: "Manage brute-force protection user blocks.", | ||||||
} | ||||||
|
||||||
cmd.SetUsageTemplate(resourceUsageTemplate()) | ||||||
cmd.AddCommand(listUserBlocksByUserIdCmd(cli)) | ||||||
cmd.AddCommand(deleteUserBlocksByUserIdCmd(cli)) | ||||||
return cmd | ||||||
} | ||||||
|
||||||
func listUserBlocksByUserIdCmd(cli *cli) *cobra.Command { | ||||||
var inputs struct { | ||||||
user_id string | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please do not use snake_case |
||||||
} | ||||||
|
||||||
cmd := &cobra.Command{ | ||||||
Use: "listByUserId", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can list by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The command should accept any of these as a single argument, and then disambiguate. It's the easiest for the user, that remains unaware (as they should) of those implementation details. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the end user, there's no difference. |
||||||
Args: cobra.MaximumNArgs(1), | ||||||
Short: "List user-blocks by user_id", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please do not include the API2 entities as-is, instead describe what the command does in the context of a single user. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assume the user knows nothing about API2. |
||||||
Long: `List user-blocks by user_id: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. |
||||||
|
||||||
auth0 user-blocks listByUserId <user_id> | ||||||
`, | ||||||
PreRun: func(cmd *cobra.Command, args []string) { | ||||||
prepareInteractivity(cmd) | ||||||
}, | ||||||
RunE: func(cmd *cobra.Command, args []string) error { | ||||||
if len(args) > 0 { | ||||||
inputs.user_id = args[0] | ||||||
} else { | ||||||
return errors.New("user_id is required.") | ||||||
} | ||||||
|
||||||
var userBlocks []*management.UserBlock | ||||||
|
||||||
err := ansi.Waiting(func() error { | ||||||
var err error | ||||||
userBlocks, err = cli.api.User.Blocks(inputs.user_id) | ||||||
return err | ||||||
}) | ||||||
|
||||||
if err != nil { | ||||||
return fmt.Errorf("Unable to load user blocks %v, error: %w", inputs.user_id, err) | ||||||
} | ||||||
|
||||||
cli.renderer.UserBlocksList(userBlocks) | ||||||
return nil | ||||||
}, | ||||||
} | ||||||
|
||||||
return cmd | ||||||
} | ||||||
|
||||||
func deleteUserBlocksByUserIdCmd(cli *cli) *cobra.Command { | ||||||
var inputs struct { | ||||||
user_id string | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please do not use snake_case. |
||||||
} | ||||||
|
||||||
cmd := &cobra.Command{ | ||||||
Use: "deleteByUserId", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use |
||||||
Args: cobra.MaximumNArgs(1), | ||||||
Short: "Delete all user-blocks by user_id", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please do not include the API2 entities as-is, instead describe what the command does in the context of a single user. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assume the user knows nothing about API2. |
||||||
Long: `Delete all user-blocks by user_id: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. |
||||||
|
||||||
auth0 user-blocks deleteByUserId <user_id> | ||||||
`, | ||||||
PreRun: func(cmd *cobra.Command, args []string) { | ||||||
prepareInteractivity(cmd) | ||||||
}, | ||||||
RunE: func(cmd *cobra.Command, args []string) error { | ||||||
if len(args) > 0 { | ||||||
inputs.user_id = args[0] | ||||||
} else { | ||||||
return errors.New("user_id is required.") | ||||||
} | ||||||
|
||||||
err := ansi.Spinner("Deleting blocks for user...", func() error { | ||||||
return cli.api.User.Unblock(inputs.user_id) | ||||||
}) | ||||||
|
||||||
if err != nil { | ||||||
return err | ||||||
} | ||||||
|
||||||
return nil | ||||||
}, | ||||||
} | ||||||
|
||||||
return cmd | ||||||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,56 @@ | ||||||
package display | ||||||
|
||||||
import ( | ||||||
"gopkg.in/auth0.v5/management" | ||||||
) | ||||||
|
||||||
type userBlockView struct { | ||||||
Identifier string | ||||||
IP string | ||||||
} | ||||||
|
||||||
func (v *userBlockView) AsTableHeader() []string { | ||||||
return []string{"Identifier", "IP"} | ||||||
} | ||||||
|
||||||
func (v *userBlockView) AsTableRow() []string { | ||||||
return []string{v.Identifier, v.IP} | ||||||
} | ||||||
|
||||||
func (v *userBlockView) KeyValues() [][]string { | ||||||
return [][]string{ | ||||||
[]string{"Identifier", v.Identifier}, | ||||||
[]string{"IP", v.IP}, | ||||||
} | ||||||
} | ||||||
|
||||||
func (r *Renderer) UserBlocksList(userBlocks []*management.UserBlock) { | ||||||
resource := "userBlocks" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
r.Heading(resource) | ||||||
|
||||||
if len(userBlocks) == 0 { | ||||||
r.EmptyState(resource) | ||||||
r.Infof("No blocks for user.") | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
return | ||||||
} | ||||||
|
||||||
var res []View | ||||||
|
||||||
for _, userBlock := range userBlocks { | ||||||
res = append(res, &userBlockView{ | ||||||
Identifier: *userBlock.Identifier, | ||||||
IP: *userBlock.IP, | ||||||
}) | ||||||
} | ||||||
|
||||||
r.Results(res) | ||||||
|
||||||
} | ||||||
|
||||||
func makeUserBlockView(userBlock *management.UserBlock) *userBlockView { | ||||||
return &userBlockView{ | ||||||
Identifier: userBlock.GetIdentifier(), | ||||||
IP: userBlock.GetIP(), | ||||||
} | ||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.