From e98cfd57d8f66c39660de4a2aef8f6ef2b6e95bb Mon Sep 17 00:00:00 2001 From: rpo Date: Mon, 9 Sep 2019 13:21:56 +0200 Subject: [PATCH] Self delete API --- Gopkg.lock | 26 ++++++++++----------- Gopkg.toml | 3 ++- api/account/swagger-api_account.yaml | 7 ++++++ cmd/keycloakb/keycloak_bridge.go | 3 +++ pkg/account/component.go | 16 +++++++++++++ pkg/account/component_test.go | 35 ++++++++++++++++++++++++++++ pkg/account/endpoint.go | 9 +++++++ pkg/account/endpoint_test.go | 13 +++++++++++ 8 files changed, 98 insertions(+), 14 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 9ee1125a..6042668a 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -37,12 +37,12 @@ version = "v1.0-rc6" [[projects]] - digest = "1:46022f907405f86d36dbb41b6cbc81f894d06a4be72cf2e25b01004beb16163f" + branch = "CLOUDTRUST-1646_Self-deleteAPI" + digest = "1:c208ec31409d2ce6b646ef0f3da4489e1992ce03c0c97093757cf41652d49b7e" name = "github.com/cloudtrust/keycloak-client" packages = ["."] pruneopts = "UT" - revision = "509d5f3b96d2e449c2476ba3edca58bb6d027e7c" - version = "v1.0-rc4" + revision = "23bde87d86817a4c80ecad870e0cbf65689229e4" [[projects]] digest = "1:d64c893fc7d2c3d395f421b00d21f0adb8ceffc4d3c90299e732b3985ca16eb4" @@ -170,7 +170,7 @@ version = "v1.0.0" [[projects]] - digest = "1:3c6faaeb500b7e6fadbe52c0b3fd62b6eed7801ed0d74bb3bd9577017df8d2f4" + digest = "1:4ffdbf6b310da314d1d171f356012e16157ceb43869c7e43e0f3c438c0c3d5d3" name = "github.com/influxdata/influxdb" packages = [ "client/v2", @@ -178,8 +178,8 @@ "pkg/escape", ] pruneopts = "UT" - revision = "f8fdf652f348fc9980997fe1c972e2b79ddd13b0" - version = "v1.7.7" + revision = "ff383cdc0420217e3460dabe17db54f8557d95b6" + version = "v1.7.8" [[projects]] branch = "master" @@ -350,12 +350,12 @@ version = "v2.17.0" [[projects]] - digest = "1:c9d69a04f7fa171f50360bbcc32196b4de8ab8837ef772f6302d0140a1e3e7f6" + digest = "1:d7b6fd08442b8d26882fae2c859a0d63962d72a533476a217d46743ed30cb803" name = "github.com/uber/jaeger-lib" packages = ["metrics"] pruneopts = "UT" - revision = "0e30338a695636fe5bcf7301e8030ce8dd2a8530" - version = "v2.0.0" + revision = "ddfc2ce1aed400905f44214f07a8ed78a20bff44" + version = "v2.1.1" [[projects]] branch = "master" @@ -367,7 +367,7 @@ "pbkdf2", ] pruneopts = "UT" - revision = "9756ffdc24725223350eb3266ffb92590d28f278" + revision = "094676da4a83be5288d281081bba63a173ce6772" [[projects]] branch = "master" @@ -380,7 +380,7 @@ "publicsuffix", ] pruneopts = "UT" - revision = "ba9fcec4b297b415637633c5a6e8fa592e4a16c3" + revision = "a7b16738d86b947dd0fadb08ca2c2342b51958b6" [[projects]] branch = "master" @@ -395,11 +395,11 @@ [[projects]] branch = "master" - digest = "1:767025ef5997eeba9a3b7fba288b8b9e71b44f0e3a2ec6dcd01f144d3dc8f173" + digest = "1:4ec1b768c44e807ef27625da30de71233819c218c07bd4f0337b439461ccf690" name = "golang.org/x/sys" packages = ["unix"] pruneopts = "UT" - revision = "43c01164e93111c754a278ab423ba01063c44917" + revision = "f460065e899abee61eb86816fd1fd684ea5a0f26" [[projects]] digest = "1:8d8faad6b12a3a4c819a3f9618cb6ee1fa1cfc33253abeeea8b55336721e3405" diff --git a/Gopkg.toml b/Gopkg.toml index 64ec36ad..2d22e3c8 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -31,7 +31,8 @@ [[constraint]] name = "github.com/cloudtrust/keycloak-client" - version = "v1.0-rc4" + #version = "v1.0-rc4" + branch = "CLOUDTRUST-1646_Self-deleteAPI" [[constraint]] name = "github.com/go-kit/kit" diff --git a/api/account/swagger-api_account.yaml b/api/account/swagger-api_account.yaml index f30ecb84..2c04cf28 100644 --- a/api/account/swagger-api_account.yaml +++ b/api/account/swagger-api_account.yaml @@ -50,6 +50,13 @@ paths: responses: 200: description: successful operation + delete: + tags: + - Account + summary: Delete account + responses: + 200: + description: successful operation components: schemas: UpdatePassword: diff --git a/cmd/keycloakb/keycloak_bridge.go b/cmd/keycloakb/keycloak_bridge.go index c46a153c..8942acc3 100644 --- a/cmd/keycloakb/keycloak_bridge.go +++ b/cmd/keycloakb/keycloak_bridge.go @@ -452,6 +452,7 @@ func main() { UpdatePassword: prepareEndpoint(account.MakeUpdatePasswordEndpoint(accountComponent), "update_password", influxMetrics, accountLogger, tracer, rateLimit["account"]), GetAccount: prepareEndpoint(account.MakeGetAccountEndpoint(accountComponent), "get_account", influxMetrics, accountLogger, tracer, rateLimit["account"]), UpdateAccount: prepareEndpoint(account.MakeUpdateAccountEndpoint(accountComponent), "update_account", influxMetrics, accountLogger, tracer, rateLimit["account"]), + DeleteAccount: prepareEndpoint(account.MakeDeleteAccountEndpoint(accountComponent), "delete_account", influxMetrics, accountLogger, tracer, rateLimit["account"]), } } @@ -635,10 +636,12 @@ func main() { var updatePasswordHandler = configureAccountHandler(ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(accountEndpoints.UpdatePassword) var getAccountHandler = configureAccountHandler(ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(accountEndpoints.GetAccount) var updateAccountHandler = configureAccountHandler(ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(accountEndpoints.UpdateAccount) + var deleteAccountHandler = configureAccountHandler(ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(accountEndpoints.DeleteAccount) route.Path("/account/credentials/password").Methods("POST").Handler(updatePasswordHandler) route.Path("/account").Methods("GET").Handler(getAccountHandler) route.Path("/account").Methods("POST").Handler(updateAccountHandler) + route.Path("/account").Methods("DELETE").Handler(deleteAccountHandler) c := cors.New(corsOptions) errc <- http.ListenAndServe(httpAddrAccount, c.Handler(route)) diff --git a/pkg/account/component.go b/pkg/account/component.go index 4ac3f5e8..fd9c3e46 100644 --- a/pkg/account/component.go +++ b/pkg/account/component.go @@ -19,6 +19,7 @@ type KeycloakClient interface { UpdatePassword(accessToken, realm, currentPassword, newPassword, confirmPassword string) (string, error) UpdateAccount(accessToken, realm string, user kc.UserRepresentation) error GetAccount(accessToken, realm string) (kc.UserRepresentation, error) + DeleteAccount(accessToken, realm string) error } // Component interface exposes methods used by the bridge API @@ -26,6 +27,7 @@ type Component interface { UpdatePassword(ctx context.Context, currentPassword, newPassword, confirmPassword string) error GetAccount(ctx context.Context) (api.AccountRepresentation, error) UpdateAccount(context.Context, api.AccountRepresentation) error + DeleteAccount(context.Context) error } // Component is the management component. @@ -182,3 +184,17 @@ func (c *component) UpdateAccount(ctx context.Context, user api.AccountRepresent return nil } + +func (c *component) DeleteAccount(ctx context.Context) error { + var accessToken = ctx.Value(cs.CtContextAccessToken).(string) + var realm = ctx.Value(cs.CtContextRealm).(string) + + err := c.keycloakClient.DeleteAccount(accessToken, realm) + + if err != nil { + c.logger.Warn("err", err.Error()) + return err + } + + return nil +} diff --git a/pkg/account/component_test.go b/pkg/account/component_test.go index f1711fba..d23514cc 100644 --- a/pkg/account/component_test.go +++ b/pkg/account/component_test.go @@ -362,3 +362,38 @@ func TestGetUser(t *testing.T) { assert.NotNil(t, err) } } + +func TestDeleteUser(t *testing.T) { + var mockCtrl = gomock.NewController(t) + defer mockCtrl.Finish() + mockKeycloakClient := mock.NewAccKeycloakClient(mockCtrl) + mockEventDBModule := mock.NewEventsDBModule(mockCtrl) + var mockLogger = log.NewNopLogger() + + var accountComponent = NewComponent(mockKeycloakClient, mockEventDBModule, mockLogger) + + var accessToken = "TOKEN==" + var realmName = "master" + var username = "username" + + var ctx = context.WithValue(context.Background(), cs.CtContextAccessToken, accessToken) + ctx = context.WithValue(ctx, cs.CtContextRealm, realmName) + ctx = context.WithValue(ctx, cs.CtContextUsername, username) + + // Delete user with succces + { + mockKeycloakClient.EXPECT().DeleteAccount(accessToken, realmName).Return(nil).Times(1) + + err := accountComponent.DeleteAccount(ctx) + + assert.Nil(t, err) + } + + //Error + { + mockKeycloakClient.EXPECT().DeleteAccount(accessToken, realmName).Return(fmt.Errorf("Unexpected error")).Times(1) + err := accountComponent.DeleteAccount(ctx) + + assert.NotNil(t, err) + } +} diff --git a/pkg/account/endpoint.go b/pkg/account/endpoint.go index 1cd76d11..d6f1c767 100644 --- a/pkg/account/endpoint.go +++ b/pkg/account/endpoint.go @@ -15,6 +15,7 @@ type Endpoints struct { UpdatePassword endpoint.Endpoint GetAccount endpoint.Endpoint UpdateAccount endpoint.Endpoint + DeleteAccount endpoint.Endpoint } // UpdatePasswordBody is the definition of the expected body content of UpdatePassword method @@ -29,6 +30,7 @@ type AccountComponent interface { UpdatePassword(ctx context.Context, currentPassword, newPassword, confirmPassword string) error GetAccount(ctx context.Context) (api.AccountRepresentation, error) UpdateAccount(ctx context.Context, account api.AccountRepresentation) error + DeleteAccount(ctx context.Context) error } // MakeUpdatePasswordEndpoint makes the UpdatePassword endpoint to update connected user's own password. @@ -71,3 +73,10 @@ func MakeUpdateAccountEndpoint(component AccountComponent) cs.Endpoint { return nil, component.UpdateAccount(ctx, body) } } + +// MakeDeleteAccountEndpoint makes the DeleteAccount endpoint to delete connected user. +func MakeDeleteAccountEndpoint(component AccountComponent) cs.Endpoint { + return func(ctx context.Context, req interface{}) (interface{}, error) { + return nil, component.DeleteAccount(ctx) + } +} diff --git a/pkg/account/endpoint_test.go b/pkg/account/endpoint_test.go index 5e10205d..f27af990 100644 --- a/pkg/account/endpoint_test.go +++ b/pkg/account/endpoint_test.go @@ -72,3 +72,16 @@ func TestMakeUpdateAccountEndpoint(t *testing.T) { assert.NotNil(t, err) } } + +func TestMakeDeleteAccountEndpoint(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + mockAccountComponent := mock.NewAccountComponent(mockCtrl) + mockAccountComponent.EXPECT().DeleteAccount(gomock.Any()).Return(nil).Times(1) + + { + _, err := MakeDeleteAccountEndpoint(mockAccountComponent)(context.Background(), nil) + assert.Nil(t, err) + } +}