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-2297] Add flag for user accreditations #194

Merged
merged 1 commit into from
Mar 12, 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
55 changes: 38 additions & 17 deletions api/account/api.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
package account

import (
"encoding/json"

"github.com/cloudtrust/common-service/validation"
"github.com/cloudtrust/keycloak-bridge/internal/constants"
msg "github.com/cloudtrust/keycloak-bridge/internal/constants"
"github.com/cloudtrust/keycloak-bridge/internal/keycloakb"
kc "github.com/cloudtrust/keycloak-client"
)

// AccountRepresentation struct
type AccountRepresentation struct {
Username *string `json:"username,omitempty"`
Email *string `json:"email,omitempty"`
EmailVerified *bool `json:"emailVerified,omitempty"`
Gender *string `json:"gender,omitempty"`
FirstName *string `json:"firstName,omitempty"`
LastName *string `json:"lastName,omitempty"`
PhoneNumber *string `json:"phoneNumber,omitempty"`
PhoneNumberVerified *bool `json:"phoneNumberVerified,omitempty"`
BirthDate *string `json:"birthDate,omitempty"`
BirthLocation *string `json:"birthLocation,omitempty"`
IDDocumentType *string `json:"idDocumentType,omitempty"`
IDDocumentNumber *string `json:"idDocumentNumber,omitempty"`
IDDocumentExpiration *string `json:"idDocumentExpiration,omitempty"`
Locale *string `json:"locale,omitempty"`
Username *string `json:"username,omitempty"`
Email *string `json:"email,omitempty"`
EmailVerified *bool `json:"emailVerified,omitempty"`
Gender *string `json:"gender,omitempty"`
FirstName *string `json:"firstName,omitempty"`
LastName *string `json:"lastName,omitempty"`
PhoneNumber *string `json:"phoneNumber,omitempty"`
PhoneNumberVerified *bool `json:"phoneNumberVerified,omitempty"`
BirthDate *string `json:"birthDate,omitempty"`
BirthLocation *string `json:"birthLocation,omitempty"`
IDDocumentType *string `json:"idDocumentType,omitempty"`
IDDocumentNumber *string `json:"idDocumentNumber,omitempty"`
IDDocumentExpiration *string `json:"idDocumentExpiration,omitempty"`
Locale *string `json:"locale,omitempty"`
Accreditations *[]AccreditationRepresentation `json:"accreditations,omitempty"`
}

// AccreditationRepresentation is a representation of accreditations
type AccreditationRepresentation struct {
Type *string `json:"type"`
ExpiryDate *string `json:"expiryDate"`
Expired *bool `json:"expired,omitempty"`
}

// CredentialRepresentation struct
Expand Down Expand Up @@ -72,7 +83,7 @@ func ConvertCredential(credKc *kc.CredentialRepresentation) CredentialRepresenta
return cred
}

// ConvertToAPIAccount creates an API account representation from a KC user representation
// ConvertToAPIAccount creates an API account representation from a KC user representation
func ConvertToAPIAccount(userKc kc.UserRepresentation) AccountRepresentation {
var userRep AccountRepresentation

Expand All @@ -85,6 +96,9 @@ func ConvertToAPIAccount(userKc kc.UserRepresentation) AccountRepresentation {
if value := userKc.GetAttributeString(constants.AttrbPhoneNumber); value != nil {
userRep.PhoneNumber = value
}
if verified, err := userKc.GetAttributeBool(constants.AttrbPhoneNumberVerified); err == nil && verified != nil {
userRep.PhoneNumberVerified = verified
}
if value := userKc.GetAttributeString(constants.AttrbGender); value != nil {
userRep.Gender = value
}
Expand All @@ -94,8 +108,15 @@ func ConvertToAPIAccount(userKc kc.UserRepresentation) AccountRepresentation {
if value := userKc.GetAttributeString(constants.AttrbLocale); value != nil {
userRep.Locale = value
}
if verified, err := userKc.GetAttributeBool(constants.AttrbPhoneNumberVerified); err == nil && verified != nil {
userRep.PhoneNumberVerified = verified
if values := userKc.GetAttribute(constants.AttrbAccreditations); len(values) > 0 {
var accreds []AccreditationRepresentation
for _, accredJSON := range values {
var accred AccreditationRepresentation
json.Unmarshal([]byte(accredJSON), &accred)
accred.Expired = keycloakb.IsDateInThePast(accred.ExpiryDate)
accreds = append(accreds, accred)
}
userRep.Accreditations = &accreds
}

return userRep
Expand Down
2 changes: 2 additions & 0 deletions api/account/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func TestConvertToAPIAccount(t *testing.T) {
"birthDate": []string{"15.02.1920"},
"locale": []string{"fr"},
"phoneNumberVerified": []string{"true"},
"accreditations": []string{`{"type":"one","expiryDate":"05.04.2020"}`, `{"type":"two","expiryDate":"05.03.2022"}`},
}

t.Run("Check attributes are copied", func(t *testing.T) {
Expand All @@ -54,6 +55,7 @@ func TestConvertToAPIAccount(t *testing.T) {
assert.Equal(t, "15.02.1920", *user.BirthDate)
assert.Equal(t, "fr", *user.Locale)
assert.True(t, *user.PhoneNumberVerified)
assert.Len(t, *user.Accreditations, 2)
})

t.Run("PhoneNumberVerified is invalid", func(t *testing.T) {
Expand Down
15 changes: 15 additions & 0 deletions api/account/swagger-api_account.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,21 @@ components:
description: only returned by /account
locale:
type: string
accreditations:
type: array
description: only returned by /account
items:
type: object
properties:
type:
type: string
description: accreditation type
expiryDate:
type: string
description: expiry date. format is DD.MM.YYYY
expired:
type: bool
description: true if the expiry date has passed
Configuration:
type: object
properties:
Expand Down
77 changes: 46 additions & 31 deletions api/kyc/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package apikyc

import (
"encoding/json"
"strconv"
"strings"

"github.com/cloudtrust/common-service/validation"
"github.com/cloudtrust/keycloak-bridge/internal/constants"
"github.com/cloudtrust/keycloak-bridge/internal/keycloakb"
kc "github.com/cloudtrust/keycloak-client"
)

Expand All @@ -18,21 +18,29 @@ type ActionRepresentation struct {

// UserRepresentation contains user details
type UserRepresentation struct {
UserID *string `json:"userId,omitempty"`
Username *string `json:"username,omitempty"`
Gender *string `json:"gender,omitempty"`
FirstName *string `json:"firstName,omitempty"`
LastName *string `json:"lastName,omitempty"`
EmailAddress *string `json:"emailAddress,omitempty"`
EmailAddressVerified *bool `json:"emailAddressVerified,omitempty"`
PhoneNumber *string `json:"phoneNumber,omitempty"`
PhoneNumberVerified *bool `json:"phoneNumberVerified,omitempty"`
BirthDate *string `json:"birthDate,omitempty"`
BirthLocation *string `json:"birthLocation,omitempty"`
IDDocumentType *string `json:"idDocumentType,omitempty"`
IDDocumentNumber *string `json:"idDocumentNumber,omitempty"`
IDDocumentExpiration *string `json:"idDocumentExpiration,omitempty"`
Comment *string `json:"comment,omitempty"`
UserID *string `json:"userId,omitempty"`
Username *string `json:"username,omitempty"`
Gender *string `json:"gender,omitempty"`
FirstName *string `json:"firstName,omitempty"`
LastName *string `json:"lastName,omitempty"`
EmailAddress *string `json:"emailAddress,omitempty"`
EmailAddressVerified *bool `json:"emailAddressVerified,omitempty"`
PhoneNumber *string `json:"phoneNumber,omitempty"`
PhoneNumberVerified *bool `json:"phoneNumberVerified,omitempty"`
BirthDate *string `json:"birthDate,omitempty"`
BirthLocation *string `json:"birthLocation,omitempty"`
IDDocumentType *string `json:"idDocumentType,omitempty"`
IDDocumentNumber *string `json:"idDocumentNumber,omitempty"`
IDDocumentExpiration *string `json:"idDocumentExpiration,omitempty"`
Comment *string `json:"comment,omitempty"`
Accreditations *[]AccreditationRepresentation `json:"accreditations,omitempty"`
}

// AccreditationRepresentation is a representation of accreditations
type AccreditationRepresentation struct {
Type *string `json:"type"`
ExpiryDate *string `json:"expiryDate"`
Expired *bool `json:"expired,omitempty"`
}

// Parameter references
Expand Down Expand Up @@ -121,23 +129,29 @@ func (u *UserRepresentation) ImportFromKeycloak(kcUser *kc.UserRepresentation) {
var phoneNumberVerified = u.PhoneNumberVerified
var gender = u.Gender
var birthdate = u.BirthDate
var accreditations = u.Accreditations

if kcUser.Attributes != nil {
var m = *kcUser.Attributes
if value, ok := m["phoneNumber"]; ok && len(value) > 0 {
phoneNumber = &value[0]
}
if value, ok := m["phoneNumberVerified"]; ok && len(value) > 0 {
if verified, err := strconv.ParseBool(value[0]); err == nil {
phoneNumberVerified = &verified
}
}
if value, ok := m["gender"]; ok && len(value) > 0 {
gender = &value[0]
}
if value, ok := m["birthDate"]; ok && len(value) > 0 {
birthdate = &value[0]
if value := kcUser.GetAttributeString(constants.AttrbPhoneNumber); value != nil {
phoneNumber = value
}
if value, err := kcUser.GetAttributeBool(constants.AttrbPhoneNumberVerified); err == nil && value != nil {
phoneNumberVerified = value
}
if value := kcUser.GetAttributeString(constants.AttrbGender); value != nil {
gender = value
}
if value := kcUser.GetAttributeDate(constants.AttrbBirthDate, constants.SupportedDateLayouts); value != nil {
birthdate = value
}
if values := kcUser.GetAttribute(constants.AttrbAccreditations); len(values) > 0 {
var accreds []AccreditationRepresentation
for _, accredJSON := range values {
var accred AccreditationRepresentation
json.Unmarshal([]byte(accredJSON), &accred)
accred.Expired = keycloakb.IsDateInThePast(accred.ExpiryDate)
accreds = append(accreds, accred)
}
accreditations = &accreds
}

u.UserID = kcUser.Id
Expand All @@ -150,6 +164,7 @@ func (u *UserRepresentation) ImportFromKeycloak(kcUser *kc.UserRepresentation) {
u.PhoneNumber = phoneNumber
u.PhoneNumberVerified = phoneNumberVerified
u.BirthDate = birthdate
u.Accreditations = accreditations
}

// Validate checks the validity of the given User
Expand Down
27 changes: 18 additions & 9 deletions api/kyc/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ package apikyc
import (
"testing"

"github.com/cloudtrust/keycloak-bridge/internal/constants"

kc "github.com/cloudtrust/keycloak-client"
"github.com/stretchr/testify/assert"
)

func ptr(value string) *string {
return &value
}

func createValidUser() UserRepresentation {
var (
bFalse = false
Expand All @@ -21,6 +27,9 @@ func createValidUser() UserRepresentation {
idDocType = "PASSPORT"
idDocNumber = "123456789"
idDocExpiration = "23.02.2039"
accred1 = AccreditationRepresentation{Type: ptr("short"), ExpiryDate: ptr("31.12.2024")}
accred2 = AccreditationRepresentation{Type: ptr("long"), ExpiryDate: ptr("31.12.2039")}
creds = []AccreditationRepresentation{accred1, accred2}
)

return UserRepresentation{
Expand All @@ -37,6 +46,7 @@ func createValidUser() UserRepresentation {
IDDocumentType: &idDocType,
IDDocumentNumber: &idDocNumber,
IDDocumentExpiration: &idDocExpiration,
Accreditations: &creds,
}
}

Expand All @@ -51,6 +61,7 @@ func createValidKeycloakUser() kc.UserRepresentation {
"phoneNumber": []string{"00 33 686 550011"},
"phoneNumberVerified": []string{"true"},
"birthDate": []string{"29.02.2020"},
"accreditations": []string{`{"type":"one","expiryDate":"05.04.2020"}`, `{"type":"two","expiryDate":"05.03.2022"}`},
}
)

Expand Down Expand Up @@ -127,19 +138,17 @@ func TestExportToKeycloak(t *testing.T) {
}

func TestImportFromKeycloak(t *testing.T) {
var user = createValidUser()
user.BirthLocation = nil
user.IDDocumentType = nil
user.IDDocumentNumber = nil
user.IDDocumentExpiration = nil

var kcUser kc.UserRepresentation
user.ExportToKeycloak(&kcUser)
var kcUser = createValidKeycloakUser()
kcUser.SetAttributeBool(constants.AttrbPhoneNumberVerified, true)

var imported = UserRepresentation{}
imported.ImportFromKeycloak(&kcUser)

assert.Equal(t, user, imported)
assert.Equal(t, *kcUser.FirstName, *imported.FirstName)
assert.Equal(t, *kcUser.LastName, *imported.LastName)
assert.Equal(t, *kcUser.GetAttributeString(constants.AttrbGender), *imported.Gender)
assert.Len(t, kcUser.GetAttribute(constants.AttrbAccreditations), 2)
assert.True(t, *imported.PhoneNumberVerified)
}

func TestValidateUserRepresentation(t *testing.T) {
Expand Down
15 changes: 15 additions & 0 deletions api/kyc/swagger-api_kyc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,21 @@ components:
validation:
type: string
description: Only provided by getUser
accreditations:
type: array
description: Used only by getUser
items:
type: object
properties:
type:
type: string
description: accreditation type
expiryDate:
type: string
description: expiry date. format is DD.MM.YYYY
expired:
type: bool
description: true if the expiry date has passed
securitySchemes:
openId:
type: openIdConnect
Expand Down
Loading