Skip to content

Commit

Permalink
Prevent user create or import to continue if connection is disabled
Browse files Browse the repository at this point in the history
  • Loading branch information
sergiught committed Nov 22, 2023
1 parent 1423190 commit 6ad3978
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 26 deletions.
53 changes: 39 additions & 14 deletions internal/cli/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,7 @@ func createUserCmd(cli *cli) *cobra.Command {
auth0 users create --name "John Doe" --email [email protected] --connection-name "Username-Password-Authentication" --username "example"
auth0 users create -n "John Doe" -e [email protected] -c "Username-Password-Authentication" -u "example" --json`,
RunE: func(cmd *cobra.Command, args []string) error {
// Users API currently only supports database connections.
options, err := cli.dbConnectionPickerOptions(cmd.Context())
options, err := cli.databaseAndPasswordlessConnectionOptions(cmd.Context())
if err != nil {
return err
}
Expand All @@ -239,17 +238,26 @@ func createUserCmd(cli *cli) *cobra.Command {
return err
}

// Prompt for user's name
connection, err := cli.api.Connection.ReadByName(cmd.Context(), inputs.ConnectionName)
if err != nil {
return fmt.Errorf("failed to find connection with name %q: %w", inputs.ConnectionName, err)
}

if len(connection.GetEnabledClients()) == 0 {
return fmt.Errorf(
"failed to continue due to the connection with name %q being disabled, enable an application on this connection and try again",
inputs.ConnectionName,
)
}

if err := userName.Ask(cmd, &inputs.Name, nil); err != nil {
return err
}

// Prompt for user email
if err := userEmail.Ask(cmd, &inputs.Email, nil); err != nil {
return err
}

// Prompt for user password
if err := userPassword.AskPassword(cmd, &inputs.Password); err != nil {
return err
}
Expand Down Expand Up @@ -562,7 +570,7 @@ The file size limit for a bulk import is 500KB. You will need to start multiple
auth0 users import -c "Username-Password-Authentication" -t "Basic Example" --upsert=false --email-results=false`,
RunE: func(cmd *cobra.Command, args []string) error {
// Users API currently only supports database connections.
dbConnectionOptions, err := cli.dbConnectionPickerOptions(cmd.Context())
dbConnectionOptions, err := cli.databaseAndPasswordlessConnectionOptions(cmd.Context())
if err != nil {
return err
}
Expand All @@ -576,6 +584,13 @@ The file size limit for a bulk import is 500KB. You will need to start multiple
return fmt.Errorf("failed to find connection with name %q: %w", inputs.ConnectionName, err)
}

if len(connection.GetEnabledClients()) == 0 {
return fmt.Errorf(
"failed to continue due to the connection with name %q being disabled, enable an application on this connection and try again",
inputs.ConnectionName,
)
}

inputs.ConnectionID = connection.GetID()

pipedUsersBody := iostream.PipedInput()
Expand Down Expand Up @@ -657,22 +672,32 @@ func formatUserDetailsPath(id string) string {
return fmt.Sprintf("users/%s", id)
}

func (c *cli) dbConnectionPickerOptions(ctx context.Context) ([]string, error) {
list, err := c.api.Connection.List(ctx, management.Parameter("strategy", management.ConnectionStrategyAuth0))
func (c *cli) databaseAndPasswordlessConnectionOptions(ctx context.Context) ([]string, error) {
connectionList, err := c.api.Connection.List(
ctx,
management.Parameter("strategy[0]", management.ConnectionStrategyAuth0),
management.Parameter("strategy[1]", management.ConnectionStrategyEmail),
management.Parameter("strategy[2]", management.ConnectionStrategySMS),
management.PerPage(100),
)
if err != nil {
return nil, err
}

var res []string
for _, conn := range list.Connections {
res = append(res, conn.GetName())
var connectionNames []string
for _, connection := range connectionList.Connections {
if len(connection.GetEnabledClients()) == 0 {
continue
}

connectionNames = append(connectionNames, connection.GetName())
}

if len(res) == 0 {
return nil, errors.New("There are currently no database connections.")
if len(connectionNames) == 0 {
return nil, errors.New("there are currently no active database or passwordless connections to choose from")
}

return res, nil
return connectionNames, nil
}

func (c *cli) getUserConnection(users *management.User) []string {
Expand Down
78 changes: 66 additions & 12 deletions internal/cli/users_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,57 @@ func TestConnectionsPickerOptions(t *testing.T) {
name: "happy path",
connections: []*management.Connection{
{
Name: auth0.String("some-name-1"),
Strategy: auth0.String("auth0"),
Name: auth0.String("some-name-1"),
Strategy: auth0.String("auth0"),
EnabledClients: &[]string{"1"},
},
{
Name: auth0.String("some-name-2"),
Strategy: auth0.String("auth0"),
Name: auth0.String("some-name-2"),
Strategy: auth0.String("auth0"),
EnabledClients: &[]string{"1"},
},
{
Name: auth0.String("some-name-3"),
Strategy: auth0.String("sms"),
EnabledClients: &[]string{"1"},
},
{
Name: auth0.String("some-name-4"),
Strategy: auth0.String("email"),
EnabledClients: &[]string{"1"},
},
},
assertOutput: func(t testing.TB, options []string) {
assert.Len(t, options, 4)
assert.Equal(t, "some-name-1", options[0])
assert.Equal(t, "some-name-2", options[1])
assert.Equal(t, "some-name-3", options[2])
assert.Equal(t, "some-name-4", options[3])
},
assertError: func(t testing.TB, err error) {
t.Fail()
},
},
{
name: "happy path: returning only active connections",
connections: []*management.Connection{
{
Name: auth0.String("some-name-1"),
Strategy: auth0.String("auth0"),
EnabledClients: &[]string{"1"},
},
{
Name: auth0.String("some-name-2"),
Strategy: auth0.String("auth0"),
EnabledClients: &[]string{"1"},
},
{
Name: auth0.String("some-name-3"),
Strategy: auth0.String("sms"),
},
{
Name: auth0.String("some-name-4"),
Strategy: auth0.String("email"),
},
},
assertOutput: func(t testing.TB, options []string) {
Expand All @@ -50,7 +95,7 @@ func TestConnectionsPickerOptions(t *testing.T) {
t.Fail()
},
assertError: func(t testing.TB, err error) {
assert.ErrorContains(t, err, "There are currently no database connections.")
assert.ErrorContains(t, err, "there are currently no active database or passwordless connections to choose from")
},
},
{
Expand All @@ -67,26 +112,35 @@ func TestConnectionsPickerOptions(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ctx := context.TODO()

ctrl := gomock.NewController(t)
defer ctrl.Finish()

connectionAPI := mock.NewMockConnectionAPI(ctrl)
connectionAPI.EXPECT().
List(gomock.Any(), gomock.Any()).
Return(&management.ConnectionList{
Connections: test.connections}, test.apiError)
List(ctx, gomock.Any()).
Return(
&management.ConnectionList{
Connections: test.connections,
},
test.apiError,
)

cli := &cli{
api: &auth0.API{Connection: connectionAPI},
api: &auth0.API{
Connection: connectionAPI,
},
}

options, err := cli.dbConnectionPickerOptions(context.Background())
options, err := cli.databaseAndPasswordlessConnectionOptions(ctx)

if err != nil {
test.assertError(t, err)
} else {
test.assertOutput(t, options)
return
}

test.assertOutput(t, options)
})
}
}

0 comments on commit 6ad3978

Please sign in to comment.