Skip to content
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

[CLOUDTRUST-2295] Bridge endpoint to self-ask for an email validation #183

Merged
merged 1 commit into from
Feb 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 34 additions & 18 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@

[[constraint]]
name = "github.com/cloudtrust/common-service"
version = "v2.0.0"
branch = "master"

[[constraint]]
name = "github.com/cloudtrust/keycloak-client"
version = "v1.2.9"
branch = "master"

[[constraint]]
name = "github.com/go-kit/kit"
Expand Down
17 changes: 16 additions & 1 deletion api/account/swagger-api_account.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,22 @@ paths:
responses:
200:
description: Successful operation.

/account/verify-email:
put:
tags:
- Account
summary: Request an email verification
responses:
200:
description: successful operation
/account/verify-phone-number:
put:
tags:
- Account
summary: Request a phone number verification
responses:
200:
description: successful operation
components:
schemas:
UpdatePassword:
Expand Down
2 changes: 1 addition & 1 deletion api/management/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ type RealmCustomConfiguration struct {
DefaultRedirectURI *string `json:"default_redirect_uri"`
APISelfAuthenticatorDeletionEnabled *bool `json:"api_self_authenticator_deletion_enabled"`
APISelfPasswordChangeEnabled *bool `json:"api_self_password_change_enabled"`
APISelfMailEditingEnabled *bool `json:"api_self_mail_editing_enabled"`
APISelfAccountEditingEnabled *bool `json:"api_self_account_editing_enabled"`
APISelfAccountDeletionEnabled *bool `json:"api_self_account_deletion_enabled"`
ShowAuthenticatorsTab *bool `json:"show_authenticators_tab"`
ShowPasswordTab *bool `json:"show_password_tab"`
Expand Down
7 changes: 7 additions & 0 deletions cmd/keycloakb/keycloak_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,8 @@ func main() {
UpdateLabelCredential: prepareEndpoint(account.MakeUpdateLabelCredentialEndpoint(accountComponent), "update_label_credential", influxMetrics, accountLogger, tracer, rateLimit["account"]),
MoveCredential: prepareEndpoint(account.MakeMoveCredentialEndpoint(accountComponent), "move_credential", influxMetrics, accountLogger, tracer, rateLimit["account"]),
GetConfiguration: prepareEndpoint(account.MakeGetConfigurationEndpoint(accountComponent), "get_configuration", influxMetrics, accountLogger, tracer, rateLimit["account"]),
SendVerifyEmail: prepareEndpoint(account.MakeSendVerifyEmailEndpoint(accountComponent), "send_verify_email", influxMetrics, accountLogger, tracer, rateLimit["account"]),
SendVerifyPhoneNumber: prepareEndpoint(account.MakeSendVerifyPhoneNumberEndpoint(accountComponent), "send_verify_phone_number", influxMetrics, accountLogger, tracer, rateLimit["account"]),
}
}

Expand Down Expand Up @@ -939,6 +941,8 @@ func main() {
var updateAccountHandler = configureAccountHandler(keycloakb.ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(accountEndpoints.UpdateAccount)
var deleteAccountHandler = configureAccountHandler(keycloakb.ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(accountEndpoints.DeleteAccount)
var getConfigurationHandler = configureAccountHandler(keycloakb.ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(accountEndpoints.GetConfiguration)
var sendVerifyEmailHandler = configureAccountHandler(keycloakb.ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(accountEndpoints.SendVerifyEmail)
var sendVerifyPhoneNumberHandler = configureAccountHandler(keycloakb.ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(accountEndpoints.SendVerifyPhoneNumber)

route.Path("/account").Methods("GET").Handler(getAccountHandler)
route.Path("/account").Methods("POST").Handler(updateAccountHandler)
Expand All @@ -953,6 +957,9 @@ func main() {
route.Path("/account/credentials/{credentialID}").Methods("PUT").Handler(updateLabelCredentialHandler)
route.Path("/account/credentials/{credentialID}/after/{previousCredentialID}").Methods("POST").Handler(moveCredentialHandler)

route.Path("/account/verify-email").Methods("PUT").Handler(sendVerifyEmailHandler)
route.Path("/account/verify-phone-number").Methods("PUT").Handler(sendVerifyPhoneNumberHandler)

var handler http.Handler = route

if accessLogsEnabled {
Expand Down
12 changes: 11 additions & 1 deletion pkg/account/authorization.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (c *authorizationComponentMW) UpdateAccount(ctx context.Context, account ap
return err
}

if !isEnabled(config.APISelfMailEditingEnabled) {
if !isEnabled(config.APISelfAccountEditingEnabled) {
infos, _ := json.Marshal(map[string]string{
"Action": action,
"currentRealm": currentRealm,
Expand Down Expand Up @@ -184,6 +184,16 @@ func (c *authorizationComponentMW) GetConfiguration(ctx context.Context, realmID
return c.next.GetConfiguration(ctx, realmIDOverride)
}

func (c *authorizationComponentMW) SendVerifyEmail(ctx context.Context) error {
// No restriction for this call
return c.next.SendVerifyEmail(ctx)
}

func (c *authorizationComponentMW) SendVerifyPhoneNumber(ctx context.Context) error {
// No restriction for this call
return c.next.SendVerifyPhoneNumber(ctx)
}

func isEnabled(booleanPtr *bool) bool {
return booleanPtr != nil && *booleanPtr
}
82 changes: 53 additions & 29 deletions pkg/account/authorization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestNoRestrictions(t *testing.T) {

var mockLogger = log.NewNopLogger()
var mockConfigurationDBModule = mock.NewConfigurationDBModule(mockCtrl)
var mockAccountComponent = mock.NewAccountComponent(mockCtrl)
var mockAccountComponent = mock.NewComponent(mockCtrl)

var accessToken = "TOKEN=="
var realmName = "master"
Expand All @@ -37,29 +37,53 @@ func TestNoRestrictions(t *testing.T) {
var ctx = context.WithValue(context.Background(), cs.CtContextAccessToken, accessToken)
ctx = context.WithValue(ctx, cs.CtContextRealm, realmName)

mockAccountComponent.EXPECT().GetCredentials(ctx).Return([]api.CredentialRepresentation{}, nil).Times(1)
_, err = authorizationMW.GetCredentials(ctx)
assert.Nil(t, err)

mockAccountComponent.EXPECT().GetCredentialRegistrators(ctx).Return([]string{}, nil).Times(1)
_, err = authorizationMW.GetCredentialRegistrators(ctx)
assert.Nil(t, err)

mockAccountComponent.EXPECT().UpdateLabelCredential(ctx, credentialID, "newLabel").Return(nil).Times(1)
err = authorizationMW.UpdateLabelCredential(ctx, credentialID, "newLabel")
assert.Nil(t, err)

mockAccountComponent.EXPECT().MoveCredential(ctx, credentialID, credentialID).Return(nil).Times(1)
err = authorizationMW.MoveCredential(ctx, credentialID, credentialID)
assert.Nil(t, err)

mockAccountComponent.EXPECT().GetAccount(ctx).Return(api.AccountRepresentation{}, nil).Times(1)
_, err = authorizationMW.GetAccount(ctx)
assert.Nil(t, err)

mockAccountComponent.EXPECT().GetConfiguration(ctx, "").Return(api.Configuration{}, nil).Times(1)
_, err = authorizationMW.GetConfiguration(ctx, "")
assert.Nil(t, err)
t.Run("GetCredentials", func(t *testing.T) {
mockAccountComponent.EXPECT().GetCredentials(ctx).Return([]api.CredentialRepresentation{}, nil).Times(1)
_, err = authorizationMW.GetCredentials(ctx)
assert.Nil(t, err)
})

t.Run("GetCredentialRegistrators", func(t *testing.T) {
mockAccountComponent.EXPECT().GetCredentialRegistrators(ctx).Return([]string{}, nil).Times(1)
_, err = authorizationMW.GetCredentialRegistrators(ctx)
assert.Nil(t, err)
})

t.Run("UpdateLabelCredential", func(t *testing.T) {
mockAccountComponent.EXPECT().UpdateLabelCredential(ctx, credentialID, "newLabel").Return(nil).Times(1)
err = authorizationMW.UpdateLabelCredential(ctx, credentialID, "newLabel")
assert.Nil(t, err)
})

t.Run("MoveCredential", func(t *testing.T) {
mockAccountComponent.EXPECT().MoveCredential(ctx, credentialID, credentialID).Return(nil).Times(1)
err = authorizationMW.MoveCredential(ctx, credentialID, credentialID)
assert.Nil(t, err)
})

t.Run("GetAccount", func(t *testing.T) {
mockAccountComponent.EXPECT().GetAccount(ctx).Return(api.AccountRepresentation{}, nil).Times(1)
_, err = authorizationMW.GetAccount(ctx)
assert.Nil(t, err)
})

t.Run("GetConfiguration", func(t *testing.T) {
mockAccountComponent.EXPECT().GetConfiguration(ctx, "").Return(api.Configuration{}, nil).Times(1)
_, err = authorizationMW.GetConfiguration(ctx, "")
assert.Nil(t, err)
})

t.Run("SendVerifyEmail", func(t *testing.T) {
mockAccountComponent.EXPECT().SendVerifyEmail(ctx).Return(nil).Times(1)
err = authorizationMW.SendVerifyEmail(ctx)
assert.Nil(t, err)
})

t.Run("SendVerifyPhoneNumber", func(t *testing.T) {
mockAccountComponent.EXPECT().SendVerifyPhoneNumber(ctx).Return(nil).Times(1)
err = authorizationMW.SendVerifyPhoneNumber(ctx)
assert.Nil(t, err)
})
}
}

Expand All @@ -69,7 +93,7 @@ func TestDeny(t *testing.T) {

var mockLogger = log.NewNopLogger()
var mockConfigurationDBModule = mock.NewConfigurationDBModule(mockCtrl)
var mockAccountComponent = mock.NewAccountComponent(mockCtrl)
var mockAccountComponent = mock.NewComponent(mockCtrl)

var accessToken = "TOKEN=="
var realmName = "master"
Expand All @@ -81,8 +105,8 @@ func TestDeny(t *testing.T) {
DefaultClientID: new(string),
DefaultRedirectURI: new(string),
APISelfAuthenticatorDeletionEnabled: &falseBool,
APISelfAccountEditingEnabled: &falseBool,
APISelfAccountDeletionEnabled: &falseBool,
APISelfMailEditingEnabled: &falseBool,
APISelfPasswordChangeEnabled: &falseBool,
}

Expand Down Expand Up @@ -117,7 +141,7 @@ func TestAllowed(t *testing.T) {

var mockLogger = log.NewNopLogger()
var mockConfigurationDBModule = mock.NewConfigurationDBModule(mockCtrl)
var mockAccountComponent = mock.NewAccountComponent(mockCtrl)
var mockAccountComponent = mock.NewComponent(mockCtrl)

var accessToken = "TOKEN=="
var realmName = "master"
Expand All @@ -129,8 +153,8 @@ func TestAllowed(t *testing.T) {
DefaultClientID: new(string),
DefaultRedirectURI: new(string),
APISelfAuthenticatorDeletionEnabled: &trueBool,
APISelfAccountEditingEnabled: &trueBool,
APISelfAccountDeletionEnabled: &trueBool,
APISelfMailEditingEnabled: &trueBool,
APISelfPasswordChangeEnabled: &trueBool,
}

Expand Down Expand Up @@ -170,7 +194,7 @@ func TestError(t *testing.T) {

var mockLogger = log.NewNopLogger()
var mockConfigurationDBModule = mock.NewConfigurationDBModule(mockCtrl)
var mockAccountComponent = mock.NewAccountComponent(mockCtrl)
var mockAccountComponent = mock.NewComponent(mockCtrl)

var accessToken = "TOKEN=="
var realmName = "master"
Expand Down
Loading