diff --git a/Gopkg.lock b/Gopkg.lock index 2688ff8..d6a0544 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,12 +2,12 @@ [[projects]] - digest = "1:20690205a93404efad5860668c0b6cf7cdc9679989458cd87a3e0b9f0b5d5704" + digest = "1:197b0f793d4f7785f3964486181efeb62dd8e1fa5556107c6282aa62ab39384f" name = "github.com/cloudtrust/common-service" packages = ["errors"] pruneopts = "" - revision = "aff8ca00d4492ff31a45b1dcefd52741b710e36b" - version = "2.2.4" + revision = "b54d0cf9445b6eae7c7bee5611b3ca0ec81adc75" + version = "v2.3.0" [[projects]] digest = "1:bb7f91ab4d1c44a3bb2651c613463c134165bda0282fca891a63b88d1b501997" @@ -96,14 +96,14 @@ [[projects]] branch = "master" - digest = "1:0d440384a8c19e7db4a75f5b5e81e48264e95ae987154b12d9981a282bae7a28" + digest = "1:3957a6d09f51e1efa16c86156e22521402e6c13867213fd45fe5a37508013021" name = "github.com/pquerna/cachecontrol" packages = [ ".", "cacheobject", ] pruneopts = "" - revision = "858c6e7e6b7e879f681b8ced4da529d4b2918ab6" + revision = "ac21108117ac345f5739431ee1e9a5fd7f82ae1c" [[projects]] digest = "1:688428eeb1ca80d92599eb3254bdf91b51d7e232fead3a73844c1f201a281e51" @@ -123,7 +123,7 @@ [[projects]] branch = "master" - digest = "1:2fa141193d48eaf88d36ca91bffbc8902c9155e55cf103ec6f51532ba6c4fa37" + digest = "1:f74c0976313d2d7055c7948741e6bab73f6e26a13d98e55114b49e4761205f59" name = "golang.org/x/crypto" packages = [ "ed25519", @@ -131,11 +131,11 @@ "pbkdf2", ] pruneopts = "" - revision = "84dcc777aaee85807c99afb056f496a3a8b3d8de" + revision = "5f87f3452ae96c4850ab9af7783f2517b643061b" [[projects]] branch = "master" - digest = "1:5453f914eb6e6469edf6699be760a363ad72c7a580ca2fcef5e957efa72492b6" + digest = "1:d62380c64b72460879e53710b38bf6a00817d8989b7a68c20691d79766a23bfd" name = "golang.org/x/net" packages = [ "context", @@ -144,21 +144,21 @@ "publicsuffix", ] pruneopts = "" - revision = "4f7140c49acb4c7e276e0b67dea953d5344ae064" + revision = "ac852fbbde11df194bfd5004603c7c8e117901f2" [[projects]] branch = "master" - digest = "1:db6b3ebfd8658790fcd62d57df504d212b97048ddd6f3da525200e2030f91f70" + digest = "1:c0011696901c7225be0462e51bf060038194814fcc1363e867c51593ff834ab8" name = "golang.org/x/oauth2" packages = [ ".", "internal", ] pruneopts = "" - revision = "5d25da1a8d43b66f2898c444f899c7bcfd6a407e" + revision = "08078c50e5b5244ec123a6b69facdbc13b21a548" [[projects]] - digest = "1:fccda34e4c58111b1908d8d69bf8d57c41c8e2542bc18ec8cd38c4fa21057f71" + digest = "1:fddc0a63dca46ccbb24699dad1f8a9ac28ebe295c8826f7c251cd86b385ebd39" name = "golang.org/x/text" packages = [ "collate", @@ -179,8 +179,8 @@ "unicode/rangetable", ] pruneopts = "" - revision = "23ae387dee1f90d29a23c0e87ee0b46038fbed0e" - version = "v0.3.3" + revision = "22f1617af38ed4cd65b3b96e02bab267e560155c" + version = "v0.3.4" [[projects]] digest = "1:13ee408d4cf721c5b576dbaff8d88ced35aadc9675274cc6b4ad009ac0372955" diff --git a/Gopkg.toml b/Gopkg.toml index beffdf7..dd13b5a 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -22,7 +22,7 @@ [[constraint]] name = "github.com/cloudtrust/common-service" - version = "2.2.4" + version = "2.3.0" [[constraint]] name = "github.com/pkg/errors" diff --git a/Jenkinsfile b/Jenkinsfile index e19f26e..6629c46 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,7 +19,7 @@ pipeline { if (!env.CHANGE_ID) { isBranch = " || true" } - withCredentials([usernamePassword(credentialsId: 'sonarqube', usernameVariable: 'USER', passwordVariable: 'PASS')]) { + withCredentials([usernamePassword(credentialsId: 'cloudtrust-cicd-sonarqube', usernameVariable: 'USER', passwordVariable: 'PASS')]) { sh """ set -eo pipefail diff --git a/api/recovery_code.go b/api/recovery_code.go index affbac7..3a8ed7c 100644 --- a/api/recovery_code.go +++ b/api/recovery_code.go @@ -7,7 +7,8 @@ import ( ) const ( - recoveryCodePath = "/auth/realms/:realm/recovery-code" + recoveryCodePath = "/auth/realms/:realm/recovery-code" + activationCodePath = "/auth/realms/:realm/activation-code" ) // CreateRecoveryCode creates a new recovery code authenticator and returns the code. @@ -17,3 +18,11 @@ func (c *Client) CreateRecoveryCode(accessToken string, realmName string, userID _, err := c.post(accessToken, &resp, query.Add("userId", userID), url.Path(recoveryCodePath), url.Param("realm", realmName)) return resp, err } + +// CreateActivationCode creates a new activation code authenticator and returns the code. +func (c *Client) CreateActivationCode(accessToken string, realmName string, userID string) (keycloak.ActivationCodeRepresentation, error) { + var resp = keycloak.ActivationCodeRepresentation{} + + _, err := c.post(accessToken, &resp, query.Add("userId", userID), url.Path(activationCodePath), url.Param("realm", realmName)) + return resp, err +} diff --git a/api/users.go b/api/users.go index 6936480..caaf5d2 100644 --- a/api/users.go +++ b/api/users.go @@ -9,17 +9,20 @@ import ( ) const ( - userPath = "/auth/admin/realms/:realm/users" - usersAdminExtensionAPIPath = "/auth/realms/:realmReq/api/admin/realms/:realm/users" - userCountPath = userPath + "/count" - userIDPath = userPath + "/:id" - userGroupsPath = userIDPath + "/groups" - userGroupIDPath = userGroupsPath + "/:groupId" - executeActionsEmailPath = userIDPath + "/execute-actions-email" - sendReminderEmailPath = "/auth/realms/:realm/onboarding/sendReminderEmail" - smsAPI = "/auth/realms/:realm/smsApi" - sendNewEnrolmentCode = smsAPI + "/sendNewCode" - shadowUser = userIDPath + "/federated-identity/:provider" + userPath = "/auth/admin/realms/:realm/users" + adminExtensionAPIPath = "/auth/realms/:realmReq/api/admin/realms/:realm" + usersAdminExtensionAPIPath = adminExtensionAPIPath + "/users" + sendEmailAdminExtensionAPIPath = adminExtensionAPIPath + "/send-email" + userCountPath = userPath + "/count" + userIDPath = userPath + "/:id" + userGroupsPath = userIDPath + "/groups" + userGroupIDPath = userGroupsPath + "/:groupId" + executeActionsEmailPath = userIDPath + "/execute-actions-email" + sendReminderEmailPath = "/auth/realms/:realm/onboarding/sendReminderEmail" + smsAPI = "/auth/realms/:realm/smsApi" + sendSmsCode = smsAPI + "/sendNewCode" + sendSMSPath = smsAPI + "/sendSms" + shadowUser = userIDPath + "/federated-identity/:provider" ) // GetUsers returns a list of users, filtered according to the query parameters. @@ -94,11 +97,11 @@ func (c *Client) ExecuteActionsEmail(accessToken string, realmName string, userI return c.put(accessToken, plugins...) } -// SendNewEnrolmentCode sends a new enrolment code and return it -func (c *Client) SendNewEnrolmentCode(accessToken string, realmName string, userID string) (keycloak.SmsCodeRepresentation, error) { +// SendSmsCode sends a SMS code and return it +func (c *Client) SendSmsCode(accessToken string, realmName string, userID string) (keycloak.SmsCodeRepresentation, error) { var paramKV []string paramKV = append(paramKV, "userid", userID) - var plugins = append(createQueryPlugins(paramKV...), url.Path(sendNewEnrolmentCode), url.Param("realm", realmName)) + var plugins = append(createQueryPlugins(paramKV...), url.Path(sendSmsCode), url.Param("realm", realmName)) var resp = keycloak.SmsCodeRepresentation{} _, err := c.post(accessToken, &resp, plugins...) @@ -124,3 +127,15 @@ func (c *Client) LinkShadowUser(accessToken string, reqRealmName string, userID _, err := c.post(accessToken, nil, url.Path(shadowUser), url.Param("realm", reqRealmName), url.Param("id", userID), url.Param("provider", provider), body.JSON(fedIDKC)) return err } + +// SendEmail sends an email to a user +func (c *Client) SendEmail(accessToken string, reqRealmName string, realmName string, emailRep keycloak.EmailRepresentation) error { + _, err := c.post(accessToken, nil, url.Path(sendEmailAdminExtensionAPIPath), url.Param("realmReq", reqRealmName), url.Param("realm", realmName), body.JSON(emailRep)) + return err +} + +// SendSMS sends an SMS to a user +func (c *Client) SendSMS(accessToken string, realmName string, smsRep keycloak.SMSRepresentation) error { + _, err := c.post(accessToken, nil, url.Path(sendSMSPath), url.Param("realm", realmName), body.JSON(smsRep)) + return err +} diff --git a/definitions.go b/definitions.go index bba81a8..a52b3db 100644 --- a/definitions.go +++ b/definitions.go @@ -752,3 +752,44 @@ type StatisticsUsersRepresentation struct { type RecoveryCodeRepresentation struct { Code *string `json:"code,omitempty"` } + +// ActivationCodeRepresentation struct +type ActivationCodeRepresentation struct { + Code *string `json:"code,omitempty"` +} + +// EmailRepresentation struct +type EmailRepresentation struct { + Recipient *string `json:"recipient,omitempty"` + Theming *EmailThemingRepresentation `json:"theming,omitempty"` + Attachments *[]AttachementRepresentation `json:"attachments,omitempty"` +} + +// EmailThemingRepresentation struct +type EmailThemingRepresentation struct { + SubjectKey *string `json:"subjectKey,omitempty"` + SubjectParameters *[]string `json:"subjectParameters,omitempty"` + Template *string `json:"template,omitempty"` + TemplateParameters *map[string]string `json:"templateParameters,omitempty"` + Locale *string `json:"locale,omitempty"` +} + +// AttachementRepresentation struct +type AttachementRepresentation struct { + Filename *string `json:"filename,omitempty"` + ContentType *string `json:"contentType,omitempty"` + Content *string `json:"content,omitempty"` +} + +// SMSRepresentation struct +type SMSRepresentation struct { + MSISDN *string `json:"msisdn,omitempty"` + Theming *SMSThemingRepresentation `json:"theming,omitempty"` +} + +// SMSThemingRepresentation struct +type SMSThemingRepresentation struct { + MessageKey *string `json:"messageKey,omitempty"` + MessageParameters *[]string `json:"messageParameters,omitempty"` + Locale *string `json:"locale,omitempty"` +}