Skip to content

Commit

Permalink
[CLOUDTRUST-2264] Replace GetUser parameters in kyc API
Browse files Browse the repository at this point in the history
  • Loading branch information
fperot74 committed Feb 13, 2020
1 parent 4d3a1bc commit e0a8bc5
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 74 deletions.
30 changes: 15 additions & 15 deletions Gopkg.lock

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

6 changes: 2 additions & 4 deletions Gopkg.toml
Expand Up @@ -27,13 +27,11 @@

[[constraint]]
name = "github.com/cloudtrust/common-service"
# version = "v1.2.4"
branch = "validation"
branch = "master"

[[constraint]]
name = "github.com/cloudtrust/keycloak-client"
# version = "v1.2.7"
branch = "validation"
branch = "dev"

[[constraint]]
name = "github.com/go-kit/kit"
Expand Down
45 changes: 39 additions & 6 deletions api/kyc/swagger-api_kyc.yaml
Expand Up @@ -31,7 +31,7 @@ paths:
get:
tags:
- KYC
summary: Gets a user
summary: Gets a user (search by username)
security:
- openId: []
parameters:
Expand All @@ -41,6 +41,12 @@ paths:
required: true
schema:
type: string
- name: groupIds
in: query
description: list of groupId the users may belong to (list comma seperated)
required: true
schema:
type: string
responses:
200:
description: Successful operation. Returns the generated username
Expand All @@ -50,9 +56,29 @@ paths:
$ref: '#/components/schemas/User'
403:
description: No permission to call this operation
404:
description: User not found
/kyc/users/{userId}:
get:
tags:
- KYC
summary: Gets a user
security:
- openId: []
parameters:
- name: userId
in: path
description: user id
required: true
schema:
type: string
responses:
200:
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
403:
description: No permission to call this operation
put:
tags:
- KYC
Expand All @@ -75,7 +101,7 @@ paths:
$ref: '#/components/schemas/User'
responses:
200:
description: Successful operation. Returns the generated username
description: Successful operation
content:
application/json:
schema:
Expand All @@ -97,9 +123,12 @@ components:
type: object
required: [gender, firstName, lastName, emailAddress, phoneNumber]
properties:
id:
userId:
type: string
description: Ignored by PUT user
username:
type: string
description: User ID is used by GET user, ignored by PUT user
description: Ignored by PUT user
gender:
type: string
firstName:
Expand All @@ -108,12 +137,16 @@ components:
type: string
emailAddress:
type: string
description: Ignored by PUT user
emailAddressVerified:
type: boolean
description: Ignored by PUT user
phoneNumber:
type: string
description: Ignored by PUT user
phoneNumberVerified:
type: boolean
description: Ignored by PUT user
birthDate:
type: string
description: format is DD.MM.YYYY
Expand Down
11 changes: 7 additions & 4 deletions cmd/keycloakb/keycloak_bridge.go
Expand Up @@ -660,9 +660,10 @@ func main() {
kycComponent = kyc.MakeAuthorizationRegisterComponentMW(registerRealm, log.With(kycLogger, "mw", "endpoint"), authorizationManager)(kycComponent)

kycEndpoints = kyc.Endpoints{
GetActions: prepareEndpoint(kyc.MakeGetActionsEndpoint(kycComponent), "register_get_actions", influxMetrics, kycLogger, tracer, rateLimit["kyc"]),
GetUser: prepareEndpoint(kyc.MakeGetUserEndpoint(kycComponent), "get_user", influxMetrics, kycLogger, tracer, rateLimit["kyc"]),
ValidateUser: prepareEndpoint(kyc.MakeValidateUserEndpoint(kycComponent), "validate_user", influxMetrics, kycLogger, tracer, rateLimit["kyc"]),
GetActions: prepareEndpoint(kyc.MakeGetActionsEndpoint(kycComponent), "register_get_actions", influxMetrics, kycLogger, tracer, rateLimit["kyc"]),
GetUser: prepareEndpoint(kyc.MakeGetUserEndpoint(kycComponent), "get_user", influxMetrics, kycLogger, tracer, rateLimit["kyc"]),
GetUserByUsername: prepareEndpoint(kyc.MakeGetUserByUsernameEndpoint(kycComponent), "get_user_by_username", influxMetrics, kycLogger, tracer, rateLimit["kyc"]),
ValidateUser: prepareEndpoint(kyc.MakeValidateUserEndpoint(kycComponent), "validate_user", influxMetrics, kycLogger, tracer, rateLimit["kyc"]),
}
}

Expand Down Expand Up @@ -829,6 +830,7 @@ func main() {
// KYC handlers
var kycGetActionsHandler = configureKYCHandler(keycloakb.ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(kycEndpoints.GetActions)
var kycGetUserHandler = configureKYCHandler(keycloakb.ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(kycEndpoints.GetUser)
var kycGetUserByUsernameHandler = configureKYCHandler(keycloakb.ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(kycEndpoints.GetUserByUsername)
var kycValidateUserHandler = configureKYCHandler(keycloakb.ComponentName, ComponentID, idGenerator, keycloakClient, audienceRequired, tracer, logger)(kycEndpoints.ValidateUser)

// actions
Expand Down Expand Up @@ -893,7 +895,8 @@ func main() {

// KYC methods
route.Path("/kyc/actions").Methods("GET").Handler(kycGetActionsHandler)
route.Path("/kyc/users").Methods("GET").Handler(kycGetUserHandler)
route.Path("/kyc/users").Methods("GET").Handler(kycGetUserByUsernameHandler)
route.Path("/kyc/users/{userId}").Methods("GET").Handler(kycGetUserHandler)
route.Path("/kyc/users/{userId}").Methods("PUT").Handler(kycValidateUserHandler)

var handler http.Handler = route
Expand Down
27 changes: 20 additions & 7 deletions pkg/kyc/authorization.go
Expand Up @@ -27,9 +27,10 @@ const (

// Creates constants for API method names
var (
KYCGetActions = newAction("KYC_GetActions", security.ScopeGlobal)
KYCGetUser = newAction("KYC_GetUser", security.ScopeGroup)
KYCValidateUser = newAction("KYC_ValidateUser", security.ScopeGroup)
KYCGetActions = newAction("KYC_GetActions", security.ScopeGlobal)
KYCGetUser = newAction("KYC_GetUser", security.ScopeGroup)
KYCGetUserByUsername = newAction("KYC_GetUserByUsername", security.ScopeGroup)
KYCValidateUser = newAction("KYC_ValidateUser", security.ScopeGroup)
)

type authorizationComponentMW struct {
Expand Down Expand Up @@ -63,16 +64,28 @@ func (c *authorizationComponentMW) GetActions(ctx context.Context) ([]apikyc.Act
return c.next.GetActions(ctx)
}

func (c *authorizationComponentMW) GetUser(ctx context.Context, username string) (apikyc.UserRepresentation, error) {
func (c *authorizationComponentMW) GetUserByUsername(ctx context.Context, username string, groupIDs []string) (apikyc.UserRepresentation, error) {
var action = KYCGetUserByUsername.String()
var targetRealm = c.realmName

for _, groupID := range groupIDs {
if err := c.authManager.CheckAuthorizationOnTargetGroupID(ctx, action, targetRealm, groupID); err != nil {
return apikyc.UserRepresentation{}, err
}
}

return c.next.GetUserByUsername(ctx, username, groupIDs)
}

func (c *authorizationComponentMW) GetUser(ctx context.Context, userID string) (apikyc.UserRepresentation, error) {
var action = KYCGetUser.String()
var targetRealm = c.realmName
var groupID = RegistrationOfficer

if err := c.authManager.CheckAuthorizationOnTargetGroup(ctx, action, targetRealm, groupID); err != nil {
if err := c.authManager.CheckAuthorizationOnTargetUser(ctx, action, targetRealm, userID); err != nil {
return apikyc.UserRepresentation{}, err
}

return c.next.GetUser(ctx, username)
return c.next.GetUser(ctx, userID)
}

func (c *authorizationComponentMW) ValidateUser(ctx context.Context, userID string, user apikyc.UserRepresentation) error {
Expand Down
34 changes: 25 additions & 9 deletions pkg/kyc/authorization_test.go
Expand Up @@ -22,7 +22,9 @@ func TestMakeAuthorizationRegisterComponentMW(t *testing.T) {
var ctx = context.TODO()
var realm = "master"
var user = apikyc.UserRepresentation{}
var username = "user4673"
var userID = "user4673"
var groupIDs = []string{"group1", "group2"}
var username = "username"
var group = RegistrationOfficer
var expectedErr = errors.New("")

Expand All @@ -42,28 +44,42 @@ func TestMakeAuthorizationRegisterComponentMW(t *testing.T) {
})

t.Run("GetUser - not authorized", func(t *testing.T) {
mockAuthManager.EXPECT().CheckAuthorizationOnTargetGroup(ctx, KYCGetUser.String(), realm, group).Return(expectedErr)
var _, err = component.GetUser(ctx, username)
mockAuthManager.EXPECT().CheckAuthorizationOnTargetUser(ctx, KYCGetUser.String(), realm, userID).Return(expectedErr)
var _, err = component.GetUser(ctx, userID)
assert.Equal(t, expectedErr, err)
})

t.Run("GetUser - authorized", func(t *testing.T) {
mockAuthManager.EXPECT().CheckAuthorizationOnTargetGroup(ctx, KYCGetUser.String(), realm, group).Return(nil)
mockComponent.EXPECT().GetUser(ctx, username).Return(apikyc.UserRepresentation{}, expectedErr).Times(1)
var _, err = component.GetUser(ctx, username)
mockAuthManager.EXPECT().CheckAuthorizationOnTargetUser(ctx, KYCGetUser.String(), realm, userID).Return(nil)
mockComponent.EXPECT().GetUser(ctx, userID).Return(apikyc.UserRepresentation{}, expectedErr).Times(1)
var _, err = component.GetUser(ctx, userID)
assert.Equal(t, expectedErr, err)
})

t.Run("GetUserByUsername - not authorized", func(t *testing.T) {
mockAuthManager.EXPECT().CheckAuthorizationOnTargetGroupID(ctx, KYCGetUserByUsername.String(), realm, gomock.Any()).
Return(nil).Return(expectedErr)
var _, err = component.GetUserByUsername(ctx, username, groupIDs)
assert.Equal(t, expectedErr, err)
})

t.Run("GetUserByUsername - authorized", func(t *testing.T) {
mockAuthManager.EXPECT().CheckAuthorizationOnTargetGroupID(ctx, KYCGetUserByUsername.String(), realm, gomock.Any()).Return(nil).Times(2)
mockComponent.EXPECT().GetUserByUsername(ctx, username, groupIDs).Return(apikyc.UserRepresentation{}, expectedErr).Times(1)
var _, err = component.GetUserByUsername(ctx, username, groupIDs)
assert.Equal(t, expectedErr, err)
})

t.Run("ValidateUser - not authorized", func(t *testing.T) {
mockAuthManager.EXPECT().CheckAuthorizationOnTargetGroup(ctx, KYCValidateUser.String(), realm, group).Return(expectedErr)
var err = component.ValidateUser(ctx, username, user)
var err = component.ValidateUser(ctx, userID, user)
assert.Equal(t, expectedErr, err)
})

t.Run("ValidateUser - authorized", func(t *testing.T) {
mockAuthManager.EXPECT().CheckAuthorizationOnTargetGroup(ctx, KYCValidateUser.String(), realm, group).Return(nil)
mockComponent.EXPECT().ValidateUser(ctx, username, user).Return(expectedErr).Times(1)
var err = component.ValidateUser(ctx, username, user)
mockComponent.EXPECT().ValidateUser(ctx, userID, user).Return(expectedErr).Times(1)
var err = component.ValidateUser(ctx, userID, user)
assert.Equal(t, expectedErr, err)
})
}
22 changes: 18 additions & 4 deletions pkg/kyc/component.go
Expand Up @@ -39,7 +39,8 @@ type EventsDBModule interface {
// Component is the register component interface.
type Component interface {
GetActions(ctx context.Context) ([]apikyc.ActionRepresentation, error)
GetUser(ctx context.Context, username string) (apikyc.UserRepresentation, error)
GetUser(ctx context.Context, userID string) (apikyc.UserRepresentation, error)
GetUserByUsername(ctx context.Context, username string, groupIDs []string) (apikyc.UserRepresentation, error)
ValidateUser(ctx context.Context, userID string, user apikyc.UserRepresentation) error
}

Expand Down Expand Up @@ -87,16 +88,29 @@ func (c *component) GetActions(ctx context.Context) ([]apikyc.ActionRepresentati
return apiActions, nil
}

func (c *component) GetUser(ctx context.Context, username string) (apikyc.UserRepresentation, error) {
func (c *component) GetUserByUsername(ctx context.Context, username string, _ []string) (apikyc.UserRepresentation, error) {
var accessToken = ctx.Value(cs.CtContextAccessToken).(string)
var kcUser, err = c.getUserByUsername(accessToken, c.socialRealmName, c.socialRealmName, username)
if err != nil {
c.logger.Info(ctx, "msg", "GetUser: can't find user in Keycloak", "err", err.Error())
return apikyc.UserRepresentation{}, errorhandler.CreateInternalServerError("keycloak")
}
return c.getUser(ctx, *kcUser.Id, kcUser)
}

var dbUser *dto.DBUser
dbUser, err = c.usersDBModule.GetUser(ctx, c.socialRealmName, *kcUser.Id)
func (c *component) GetUser(ctx context.Context, userID string) (apikyc.UserRepresentation, error) {
var accessToken = ctx.Value(cs.CtContextAccessToken).(string)

var kcUser, err = c.keycloakClient.GetUser(accessToken, c.socialRealmName, userID)
if err != nil {
c.logger.Info(ctx, "msg", "GetUser: can't find user in Keycloak", "err", err.Error())
return apikyc.UserRepresentation{}, errorhandler.CreateInternalServerError("keycloak")
}
return c.getUser(ctx, userID, kcUser)
}

func (c *component) getUser(ctx context.Context, userID string, kcUser kc.UserRepresentation) (apikyc.UserRepresentation, error) {
var dbUser, err = c.usersDBModule.GetUser(ctx, c.socialRealmName, *kcUser.Id)
if err != nil {
c.logger.Info(ctx, "msg", "GetUser: can't find user in keycloak")
return apikyc.UserRepresentation{}, err
Expand Down

0 comments on commit e0a8bc5

Please sign in to comment.