Skip to content

Commit

Permalink
[CLOUDTRUST-2108] Physical identication API
Browse files Browse the repository at this point in the history
  • Loading branch information
fperot74 committed Jan 31, 2020
1 parent 3c88294 commit 6dfdfca
Show file tree
Hide file tree
Showing 41 changed files with 2,131 additions and 354 deletions.
6 changes: 3 additions & 3 deletions Gopkg.lock

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

27 changes: 19 additions & 8 deletions api/account/api.go
Expand Up @@ -10,11 +10,17 @@ import (

// AccountRepresentation struct
type AccountRepresentation struct {
Username *string `json:"username,omitempty"`
Email *string `json:"email,omitempty"`
FirstName *string `json:"firstName,omitempty"`
LastName *string `json:"lastName,omitempty"`
PhoneNumber *string `json:"phoneNumber,omitempty"`
Username *string `json:"username,omitempty"`
Email *string `json:"email,omitempty"`
Gender *string `json:"gender,omitempty"`
FirstName *string `json:"firstName,omitempty"`
LastName *string `json:"lastName,omitempty"`
PhoneNumber *string `json:"phoneNumber,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"`
}

// CredentialRepresentation struct
Expand Down Expand Up @@ -74,9 +80,14 @@ func ConvertToAPIAccount(userKc kc.UserRepresentation) AccountRepresentation {
if userKc.Attributes != nil {
var m = *userKc.Attributes

if m["phoneNumber"] != nil {
var phoneNumber = m["phoneNumber"][0]
userRep.PhoneNumber = &phoneNumber
if value, ok := m["phoneNumber"]; ok && len(value) > 0 {
userRep.PhoneNumber = &value[0]
}
if value, ok := m["gender"]; ok && len(value) > 0 {
userRep.Gender = &value[0]
}
if value, ok := m["birthDate"]; ok && len(value) > 0 {
userRep.BirthDate = &value[0]
}
}
return userRep
Expand Down
8 changes: 7 additions & 1 deletion api/account/api_test.go
Expand Up @@ -35,8 +35,14 @@ func TestConvertToAPIAccount(t *testing.T) {
assert.Nil(t, nil, ConvertToAPIAccount(kcUser).PhoneNumber)

attributes["phoneNumber"] = []string{"+41221234567"}
attributes["gender"] = []string{"M"}
attributes["birthDate"] = []string{"15.02.1920"}
kcUser = kc.UserRepresentation{Attributes: &attributes}
assert.Equal(t, "+41221234567", *ConvertToAPIAccount(kcUser).PhoneNumber)

var user = ConvertToAPIAccount(kcUser)
assert.Equal(t, "+41221234567", *user.PhoneNumber)
assert.Equal(t, "M", *user.Gender)
assert.Equal(t, "15.02.1920", *user.BirthDate)
}

func TestConvertToKCUser(t *testing.T) {
Expand Down
19 changes: 19 additions & 0 deletions api/account/swagger-api_account.yaml
Expand Up @@ -196,12 +196,31 @@ components:
type: string
email:
type: string
gender:
type: string
description: only returned by /account
firstName:
type: string
lastName:
type: string
phoneNumber:
type: string
birthDate:
type: string
description: only returned by /account. format is DD.MM.YYYY
birthLocation:
type: string
description: only returned by /account
idDocumentType:
type: string
enum: [ID_CARD, PASSPORT, RESIDENCE_PERMIT]
description: only returned by /account
idDocumentNumber:
type: string
description: only returned by /account
idDocumentExpiration:
type: string
description: only returned by /account
Configuration:
type: object
properties:
Expand Down
203 changes: 203 additions & 0 deletions api/kyc/api.go
@@ -0,0 +1,203 @@
package apikyc

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

"github.com/cloudtrust/keycloak-bridge/internal/keycloakb"
kc "github.com/cloudtrust/keycloak-client"
)

// ActionRepresentation struct
type ActionRepresentation struct {
Name *string `json:"name"`
Scope *string `json:"scope"`
}

// 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"`
Validation *string `json:"validation,omitempty"`
}

// Parameter references
const (
prmUserGender = "user_gender"
prmUserFirstName = "user_firstName"
prmUserLastName = "user_lastName"
prmUserEmail = "user_emailAddress"
prmUserPhoneNumber = "user_phoneNumber"
prmUserBirthDate = "user_birthDate"
prmUserBirthLocation = "user_birthLocation"
prmUserIDDocumentType = "user_idDocType"
prmUserIDDocumentNumber = "user_idDocNumber"
prmUserIDDocumentExpiration = "user_idDocExpiration"

regExpNames = `^([\wàáâäçèéêëìíîïñòóôöùúûüß]+([ '-][\wàáâäçèéêëìíîïñòóôöùúûüß]+)*){1,50}$`
regExpFirstName = regExpNames
regExpLastName = regExpNames
regExpEmail = `^.+\@.+\..+$`
regExpBirthLocation = regExpNames
// Multiple values with digits and letters separated by a single separator (space, dash)
regExpIDDocumentNumber = `^([\w\d]+([ -][\w\d]+)*){1,50}$`

dateLayout = "02.01.2006"
)

var (
allowedGender = map[string]bool{"M": true, "F": true}
allowedDocumentType = map[string]bool{"ID_CARD": true, "PASSPORT": true, "RESIDENCE_PERMIT": true}
)

// UserFromJSON creates a User using its json representation
func UserFromJSON(jsonRep string) (UserRepresentation, error) {
var user UserRepresentation
dec := json.NewDecoder(strings.NewReader(jsonRep))
dec.DisallowUnknownFields()
err := dec.Decode(&user)
return user, err
}

// UserToJSON returns a json representation of a given User
func (u *UserRepresentation) UserToJSON() string {
var bytes, _ = json.Marshal(u)
return string(bytes)
}

// ExportToKeycloak exports user details into a Keycloak UserRepresentation
func (u *UserRepresentation) ExportToKeycloak(kcUser *kc.UserRepresentation) {
var bFalse = false
var bTrue = true
var attributes = make(map[string][]string)

if kcUser.Attributes != nil {
attributes = *kcUser.Attributes
}

if u.Gender != nil {
attributes["gender"] = []string{*u.Gender}
}
if u.PhoneNumber != nil {
if value, ok := attributes["phoneNumber"]; !ok || (len(value) > 0 && value[0] != *u.PhoneNumber) {
attributes["phoneNumber"] = []string{*u.PhoneNumber}
attributes["phoneNumberVerified"] = []string{"false"}
}
}
if u.BirthDate != nil {
attributes["birthDate"] = []string{*u.BirthDate}
}

if u.Username != nil {
kcUser.Username = u.Username
}
if u.EmailAddress != nil && (kcUser.Email == nil || *kcUser.Email != *u.EmailAddress) {
kcUser.Email = u.EmailAddress
kcUser.EmailVerified = &bFalse
}
if u.FirstName != nil {
kcUser.FirstName = u.FirstName
}
if u.LastName != nil {
kcUser.LastName = u.LastName
}
kcUser.Attributes = &attributes
kcUser.Enabled = &bTrue
}

// ImportFromKeycloak import details from Keycloak
func (u *UserRepresentation) ImportFromKeycloak(kcUser *kc.UserRepresentation) {
var phoneNumber = u.PhoneNumber
var phoneNumberVerified = u.PhoneNumberVerified
var gender = u.Gender
var birthdate = u.BirthDate

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]
}
}

u.UserID = kcUser.Id
u.Username = kcUser.Username
u.Gender = gender
u.FirstName = kcUser.FirstName
u.LastName = kcUser.LastName
u.EmailAddress = kcUser.Email
u.EmailAddressVerified = kcUser.EmailVerified
u.PhoneNumber = phoneNumber
u.PhoneNumberVerified = phoneNumberVerified
u.BirthDate = birthdate
}

// Validate checks the validity of the given User
func (u *UserRepresentation) Validate() error {
var err = keycloakb.ValidateParameterIn(prmUserGender, u.Gender, allowedGender, true)
if err != nil {
return err
}

err = keycloakb.ValidateParameterRegExp(prmUserFirstName, u.FirstName, regExpFirstName, true)
if err != nil {
return err
}
err = keycloakb.ValidateParameterRegExp(prmUserLastName, u.LastName, regExpLastName, true)
if err != nil {
return err
}
err = keycloakb.ValidateParameterRegExp(prmUserEmail, u.EmailAddress, regExpEmail, true)
if err != nil {
return err
}
err = keycloakb.ValidateParameterPhoneNumber(prmUserPhoneNumber, u.PhoneNumber)
if err != nil {
return err
}
err = keycloakb.ValidateParameterDate(prmUserBirthDate, u.BirthDate, dateLayout, true)
if err != nil {
return err
}
err = keycloakb.ValidateParameterRegExp(prmUserBirthLocation, u.BirthLocation, regExpBirthLocation, true)
if err != nil {
return err
}
err = keycloakb.ValidateParameterIn(prmUserIDDocumentType, u.IDDocumentType, allowedDocumentType, true)
if err != nil {
return err
}
err = keycloakb.ValidateParameterRegExp(prmUserIDDocumentNumber, u.IDDocumentNumber, regExpIDDocumentNumber, true)
if err != nil {
return err
}
err = keycloakb.ValidateParameterDate(prmUserIDDocumentExpiration, u.IDDocumentExpiration, dateLayout, true)
if err != nil {
return err
}
return nil
}

0 comments on commit 6dfdfca

Please sign in to comment.