diff --git a/Gopkg.lock b/Gopkg.lock index 58cab34..2aa51b0 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,7 +2,6 @@ [[projects]] - branch = "master" digest = "1:f5259fbdb0775d08aa60d3ac55b0f1aa810c5f22097a18942eabc437a15dc81a" name = "github.com/cloudtrust/common-service" packages = [ @@ -12,6 +11,7 @@ ] pruneopts = "" revision = "3a38f0fb73305dc93ec4d0d8a3b6ec1cfb98fa5b" + version = "v2.1.1" [[projects]] digest = "1:bb7f91ab4d1c44a3bb2651c613463c134165bda0282fca891a63b88d1b501997" diff --git a/Gopkg.toml b/Gopkg.toml index c6e8c4f..bb91ea5 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -22,7 +22,7 @@ [[constraint]] name = "github.com/cloudtrust/common-service" - branch = "master" + version = "v2.1.1" [[constraint]] name = "github.com/pkg/errors" diff --git a/account.go b/api/account.go similarity index 94% rename from account.go rename to api/account.go index f36f4e7..2082bee 100644 --- a/account.go +++ b/api/account.go @@ -1,6 +1,7 @@ -package keycloak +package api import ( + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/headers" "gopkg.in/h2non/gentleman.v2/plugins/url" @@ -19,8 +20,8 @@ const ( ) // GetCredentials returns the list of credentials of the user -func (c *AccountClient) GetCredentials(accessToken string, realmName string) ([]CredentialRepresentation, error) { - var resp = []CredentialRepresentation{} +func (c *AccountClient) GetCredentials(accessToken string, realmName string) ([]keycloak.CredentialRepresentation, error) { + var resp = []keycloak.CredentialRepresentation{} var err = c.client.get(accessToken, &resp, url.Path(accountCredentialsPath), url.Param("realm", realmName), headers.Set("Accept", "application/json")) return resp, err } @@ -62,14 +63,14 @@ func (c *AccountClient) UpdatePassword(accessToken, realm, currentPassword, newP } // GetAccount provides the user's information -func (c *AccountClient) GetAccount(accessToken string, realm string) (UserRepresentation, error) { - var resp = UserRepresentation{} +func (c *AccountClient) GetAccount(accessToken string, realm string) (keycloak.UserRepresentation, error) { + var resp = keycloak.UserRepresentation{} var err = c.client.get(accessToken, &resp, url.Path(accountExtensionAPIPath), url.Param("realm", realm), headers.Set("Accept", "application/json")) return resp, err } // UpdateAccount updates the user's information -func (c *AccountClient) UpdateAccount(accessToken string, realm string, user UserRepresentation) error { +func (c *AccountClient) UpdateAccount(accessToken string, realm string, user keycloak.UserRepresentation) error { _, err := c.client.post(accessToken, nil, url.Path(accountExtensionAPIPath), url.Param("realm", realm), body.JSON(user)) return err } diff --git a/attack_detection.go b/api/attack_detection.go similarity index 98% rename from attack_detection.go rename to api/attack_detection.go index d137d57..dc8a884 100644 --- a/attack_detection.go +++ b/api/attack_detection.go @@ -1,4 +1,4 @@ -package keycloak +package api import ( "gopkg.in/h2non/gentleman.v2/plugins/url" diff --git a/authentication_management.go b/api/authentication_management.go similarity index 86% rename from authentication_management.go rename to api/authentication_management.go index 45a3de1..feb7f40 100644 --- a/authentication_management.go +++ b/api/authentication_management.go @@ -1,6 +1,7 @@ -package keycloak +package api import ( + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/url" ) @@ -24,21 +25,21 @@ func (c *Client) GetClientAuthenticatorProviders(accessToken string, realmName s } // GetAuthenticatorProviderConfig returns the authenticator provider’s configuration description. -func (c *Client) GetAuthenticatorProviderConfig(accessToken string, realmName, providerID string) (AuthenticatorConfigInfoRepresentation, error) { - var resp = AuthenticatorConfigInfoRepresentation{} +func (c *Client) GetAuthenticatorProviderConfig(accessToken string, realmName, providerID string) (keycloak.AuthenticatorConfigInfoRepresentation, error) { + var resp = keycloak.AuthenticatorConfigInfoRepresentation{} var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/config-description/:providerID"), url.Param("realm", realmName), url.Param("providerID", providerID)) return resp, err } // GetAuthenticatorConfig returns the authenticator configuration. -func (c *Client) GetAuthenticatorConfig(accessToken string, realmName, configID string) (AuthenticatorConfigRepresentation, error) { - var resp = AuthenticatorConfigRepresentation{} +func (c *Client) GetAuthenticatorConfig(accessToken string, realmName, configID string) (keycloak.AuthenticatorConfigRepresentation, error) { + var resp = keycloak.AuthenticatorConfigRepresentation{} var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID)) return resp, err } // UpdateAuthenticatorConfig updates the authenticator configuration. -func (c *Client) UpdateAuthenticatorConfig(accessToken string, realmName, configID string, config AuthenticatorConfigRepresentation) error { +func (c *Client) UpdateAuthenticatorConfig(accessToken string, realmName, configID string, config keycloak.AuthenticatorConfigRepresentation) error { return c.put(accessToken, url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID), body.JSON(config)) } @@ -48,7 +49,7 @@ func (c *Client) DeleteAuthenticatorConfig(accessToken string, realmName, config } // CreateAuthenticationExecution add new authentication execution -func (c *Client) CreateAuthenticationExecution(accessToken string, realmName string, authExec AuthenticationExecutionRepresentation) (string, error) { +func (c *Client) CreateAuthenticationExecution(accessToken string, realmName string, authExec keycloak.AuthenticationExecutionRepresentation) (string, error) { return c.post(accessToken, nil, url.Path(authenticationManagementPath+"/executions"), url.Param("realm", realmName), body.JSON(authExec)) } @@ -58,7 +59,7 @@ func (c *Client) DeleteAuthenticationExecution(accessToken string, realmName, ex } // UpdateAuthenticationExecution update execution with new configuration. -func (c *Client) UpdateAuthenticationExecution(accessToken string, realmName, executionID string, authConfig AuthenticatorConfigRepresentation) error { +func (c *Client) UpdateAuthenticationExecution(accessToken string, realmName, executionID string, authConfig keycloak.AuthenticatorConfigRepresentation) error { _, err := c.post(accessToken, nil, url.Path(authenticationManagementPath+"/executions/:id/config"), url.Param("realm", realmName), url.Param("id", executionID), body.JSON(authConfig)) return err } @@ -76,14 +77,14 @@ func (c *Client) RaiseExecutionPriority(accessToken string, realmName, execution } // CreateAuthenticationFlow creates a new authentication flow. -func (c *Client) CreateAuthenticationFlow(accessToken string, realmName string, authFlow AuthenticationFlowRepresentation) error { +func (c *Client) CreateAuthenticationFlow(accessToken string, realmName string, authFlow keycloak.AuthenticationFlowRepresentation) error { _, err := c.post(accessToken, nil, url.Path(authenticationManagementPath+"/flows"), url.Param("realm", realmName), body.JSON(authFlow)) return err } // GetAuthenticationFlows returns a list of authentication flows. -func (c *Client) GetAuthenticationFlows(accessToken string, realmName string) ([]AuthenticationFlowRepresentation, error) { - var resp = []AuthenticationFlowRepresentation{} +func (c *Client) GetAuthenticationFlows(accessToken string, realmName string) ([]keycloak.AuthenticationFlowRepresentation, error) { + var resp = []keycloak.AuthenticationFlowRepresentation{} var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/flows"), url.Param("realm", realmName)) return resp, err } @@ -98,14 +99,14 @@ func (c *Client) CopyExistingAuthenticationFlow(accessToken string, realmName, f } // GetAuthenticationExecutionForFlow returns the authentication executions for a flow. -func (c *Client) GetAuthenticationExecutionForFlow(accessToken string, realmName, flowAlias string) (AuthenticationExecutionInfoRepresentation, error) { - var resp = AuthenticationExecutionInfoRepresentation{} +func (c *Client) GetAuthenticationExecutionForFlow(accessToken string, realmName, flowAlias string) (keycloak.AuthenticationExecutionInfoRepresentation, error) { + var resp = keycloak.AuthenticationExecutionInfoRepresentation{} var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/flows/:flowAlias/executions"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias)) return resp, err } // UpdateAuthenticationExecutionForFlow updates the authentication executions of a flow. -func (c *Client) UpdateAuthenticationExecutionForFlow(accessToken string, realmName, flowAlias string, authExecInfo AuthenticationExecutionInfoRepresentation) error { +func (c *Client) UpdateAuthenticationExecutionForFlow(accessToken string, realmName, flowAlias string, authExecInfo keycloak.AuthenticationExecutionInfoRepresentation) error { return c.put(accessToken, url.Path(authenticationManagementPath+"/flows/:flowAlias/executions"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(authExecInfo)) } @@ -124,8 +125,8 @@ func (c *Client) CreateFlowWithExecutionForExistingFlow(accessToken string, real } // GetAuthenticationFlow gets the authentication flow for id. -func (c *Client) GetAuthenticationFlow(accessToken string, realmName, flowID string) (AuthenticationFlowRepresentation, error) { - var resp = AuthenticationFlowRepresentation{} +func (c *Client) GetAuthenticationFlow(accessToken string, realmName, flowID string) (keycloak.AuthenticationFlowRepresentation, error) { + var resp = keycloak.AuthenticationFlowRepresentation{} var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/flows/:id"), url.Param("realm", realmName), url.Param("id", flowID)) return resp, err } @@ -164,21 +165,21 @@ func (c *Client) RegisterRequiredAction(accessToken string, realmName, providerI } // GetRequiredActions returns a list of required actions. -func (c *Client) GetRequiredActions(accessToken string, realmName string) ([]RequiredActionProviderRepresentation, error) { - var resp = []RequiredActionProviderRepresentation{} +func (c *Client) GetRequiredActions(accessToken string, realmName string) ([]keycloak.RequiredActionProviderRepresentation, error) { + var resp = []keycloak.RequiredActionProviderRepresentation{} var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/required-actions"), url.Param("realm", realmName)) return resp, err } // GetRequiredAction returns the required action for the alias. -func (c *Client) GetRequiredAction(accessToken string, realmName, actionAlias string) (RequiredActionProviderRepresentation, error) { - var resp = RequiredActionProviderRepresentation{} +func (c *Client) GetRequiredAction(accessToken string, realmName, actionAlias string) (keycloak.RequiredActionProviderRepresentation, error) { + var resp = keycloak.RequiredActionProviderRepresentation{} var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias)) return resp, err } // UpdateRequiredAction updates the required action. -func (c *Client) UpdateRequiredAction(accessToken string, realmName, actionAlias string, action RequiredActionProviderRepresentation) error { +func (c *Client) UpdateRequiredAction(accessToken string, realmName, actionAlias string, action keycloak.RequiredActionProviderRepresentation) error { return c.put(accessToken, url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias), body.JSON(action)) } diff --git a/client_attribute_certificate.go b/api/client_attribute_certificate.go similarity index 77% rename from client_attribute_certificate.go rename to api/client_attribute_certificate.go index 0cdfe4e..edb8676 100644 --- a/client_attribute_certificate.go +++ b/api/client_attribute_certificate.go @@ -1,8 +1,9 @@ -package keycloak +package api import ( "bytes" + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/url" ) @@ -12,43 +13,43 @@ const ( ) // GetKeyInfo returns the key info. idClient is the id of client (not client-id). -func (c *Client) GetKeyInfo(accessToken string, realmName, idClient, attr string) (CertificateRepresentation, error) { - var resp = CertificateRepresentation{} +func (c *Client) GetKeyInfo(accessToken string, realmName, idClient, attr string) (keycloak.CertificateRepresentation, error) { + var resp = keycloak.CertificateRepresentation{} var err = c.get(accessToken, &resp, url.Path(clientAttrCertPath), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr)) return resp, err } // GetKeyStore returns a keystore file for the client, containing private key and public certificate. idClient is the id of client (not client-id). -func (c *Client) GetKeyStore(accessToken string, realmName, idClient, attr string, keyStoreConfig KeyStoreConfig) ([]byte, error) { +func (c *Client) GetKeyStore(accessToken string, realmName, idClient, attr string, keyStoreConfig keycloak.KeyStoreConfig) ([]byte, error) { var resp = []byte{} _, err := c.post(accessToken, &resp, url.Path(clientAttrCertPath+"/download"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.JSON(keyStoreConfig)) return resp, err } // GenerateCertificate generates a new certificate with new key pair. idClient is the id of client (not client-id). -func (c *Client) GenerateCertificate(accessToken string, realmName, idClient, attr string) (CertificateRepresentation, error) { - var resp = CertificateRepresentation{} +func (c *Client) GenerateCertificate(accessToken string, realmName, idClient, attr string) (keycloak.CertificateRepresentation, error) { + var resp = keycloak.CertificateRepresentation{} _, err := c.post(accessToken, &resp, url.Path(clientAttrCertPath+"/generate"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr)) return resp, err } // GenerateKeyPairAndCertificate generates a keypair and certificate and serves the private key in a specified keystore format. -func (c *Client) GenerateKeyPairAndCertificate(accessToken string, realmName, idClient, attr string, keyStoreConfig KeyStoreConfig) ([]byte, error) { +func (c *Client) GenerateKeyPairAndCertificate(accessToken string, realmName, idClient, attr string, keyStoreConfig keycloak.KeyStoreConfig) ([]byte, error) { var resp = []byte{} _, err := c.post(accessToken, &resp, url.Path(clientAttrCertPath+"/generate-and-download"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.JSON(keyStoreConfig)) return resp, err } // UploadCertificatePrivateKey uploads a certificate and eventually a private key. -func (c *Client) UploadCertificatePrivateKey(accessToken string, realmName, idClient, attr string, file []byte) (CertificateRepresentation, error) { - var resp = CertificateRepresentation{} +func (c *Client) UploadCertificatePrivateKey(accessToken string, realmName, idClient, attr string, file []byte) (keycloak.CertificateRepresentation, error) { + var resp = keycloak.CertificateRepresentation{} _, err := c.post(accessToken, &resp, url.Path(clientAttrCertPath+"/upload"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.Reader(bytes.NewReader(file))) return resp, err } // UploadCertificate uploads only a certificate, not the private key. -func (c *Client) UploadCertificate(accessToken string, realmName, idClient, attr string, file []byte) (CertificateRepresentation, error) { - var resp = CertificateRepresentation{} +func (c *Client) UploadCertificate(accessToken string, realmName, idClient, attr string, file []byte) (keycloak.CertificateRepresentation, error) { + var resp = keycloak.CertificateRepresentation{} _, err := c.post(accessToken, &resp, url.Path(clientAttrCertPath+"/upload-certificate"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.Reader(bytes.NewReader(file))) return resp, err } diff --git a/client_initial_access.go b/api/client_initial_access.go similarity index 74% rename from client_initial_access.go rename to api/client_initial_access.go index 1c9a1b9..6eec6cc 100644 --- a/client_initial_access.go +++ b/api/client_initial_access.go @@ -1,6 +1,7 @@ -package keycloak +package api import ( + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/url" ) @@ -10,15 +11,15 @@ const ( ) // CreateClientInitialAccess creates a new initial access token. -func (c *Client) CreateClientInitialAccess(accessToken string, realmName string, access ClientInitialAccessCreatePresentation) (ClientInitialAccessPresentation, error) { - var resp = ClientInitialAccessPresentation{} +func (c *Client) CreateClientInitialAccess(accessToken string, realmName string, access keycloak.ClientInitialAccessCreatePresentation) (keycloak.ClientInitialAccessPresentation, error) { + var resp = keycloak.ClientInitialAccessPresentation{} _, err := c.post(accessToken, &resp, nil, url.Path(clientInitialAccessPath), url.Param("realm", realmName), body.JSON(access)) return resp, err } // GetClientInitialAccess returns a list of clients initial access. -func (c *Client) GetClientInitialAccess(accessToken string, realmName string) ([]ClientInitialAccessPresentation, error) { - var resp = []ClientInitialAccessPresentation{} +func (c *Client) GetClientInitialAccess(accessToken string, realmName string) ([]keycloak.ClientInitialAccessPresentation, error) { + var resp = []keycloak.ClientInitialAccessPresentation{} var err = c.get(accessToken, &resp, url.Path(clientInitialAccessPath), url.Param("realm", realmName)) return resp, err } diff --git a/client_registration_policy.go b/api/client_registration_policy.go similarity index 63% rename from client_registration_policy.go rename to api/client_registration_policy.go index 72f8fdb..4b75e87 100644 --- a/client_registration_policy.go +++ b/api/client_registration_policy.go @@ -1,14 +1,17 @@ -package keycloak +package api -import "gopkg.in/h2non/gentleman.v2/plugins/url" +import ( + "github.com/cloudtrust/keycloak-client" + "gopkg.in/h2non/gentleman.v2/plugins/url" +) const ( clientRegistrationPolicyPath = "/auth/admin/realms/:realm/client-registration-policy/providers" ) // GetClientRegistrationPolicy is the base path to retrieve providers with the configProperties properly filled. -func (c *Client) GetClientRegistrationPolicy(accessToken string, realmName, configID string) ([]ComponentTypeRepresentation, error) { - var resp = []ComponentTypeRepresentation{} +func (c *Client) GetClientRegistrationPolicy(accessToken string, realmName, configID string) ([]keycloak.ComponentTypeRepresentation, error) { + var resp = []keycloak.ComponentTypeRepresentation{} var err = c.get(accessToken, &resp, url.Path(clientRegistrationPolicyPath), url.Param("realm", realmName)) return resp, err } diff --git a/client_role_mappings.go b/api/client_role_mappings.go similarity index 81% rename from client_role_mappings.go rename to api/client_role_mappings.go index 6c448ed..5c82559 100644 --- a/client_role_mappings.go +++ b/api/client_role_mappings.go @@ -1,6 +1,7 @@ -package keycloak +package api import ( + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/url" ) @@ -11,14 +12,14 @@ const ( ) // AddClientRolesToUserRoleMapping add client-level roles to the user role mapping. -func (c *Client) AddClientRolesToUserRoleMapping(accessToken string, realmName, userID, clientID string, roles []RoleRepresentation) error { +func (c *Client) AddClientRolesToUserRoleMapping(accessToken string, realmName, userID, clientID string, roles []keycloak.RoleRepresentation) error { _, err := c.post(accessToken, nil, url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", userID), url.Param("client", clientID), body.JSON(roles)) return err } // GetClientRoleMappings gets client-level role mappings for the user, and the app. -func (c *Client) GetClientRoleMappings(accessToken string, realmName, userID, clientID string) ([]RoleRepresentation, error) { - var resp = []RoleRepresentation{} +func (c *Client) GetClientRoleMappings(accessToken string, realmName, userID, clientID string) ([]keycloak.RoleRepresentation, error) { + var resp = []keycloak.RoleRepresentation{} var err = c.get(accessToken, &resp, url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", userID), url.Param("client", clientID)) return resp, err } @@ -29,8 +30,8 @@ func (c *Client) DeleteClientRolesFromUserRoleMapping(accessToken string, realmN } // GetRealmLevelRoleMappings gets realm level role mappings -func (c *Client) GetRealmLevelRoleMappings(accessToken string, realmName, userID string) ([]RoleRepresentation, error) { - var resp = []RoleRepresentation{} +func (c *Client) GetRealmLevelRoleMappings(accessToken string, realmName, userID string) ([]keycloak.RoleRepresentation, error) { + var resp = []keycloak.RoleRepresentation{} var err = c.get(accessToken, &resp, url.Path(realmRoleMappingPath), url.Param("realm", realmName), url.Param("id", userID)) return resp, err } diff --git a/clients.go b/api/clients.go similarity index 71% rename from clients.go rename to api/clients.go index bfdb7fb..caaf0b9 100644 --- a/clients.go +++ b/api/clients.go @@ -1,8 +1,9 @@ -package keycloak +package api import ( "errors" + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/url" ) @@ -16,33 +17,34 @@ const ( // GetClients returns a list of clients belonging to the realm. // Parameters: clientId (filter by clientId), // viewableOnly (filter clients that cannot be viewed in full by admin, default="false") -func (c *Client) GetClients(accessToken string, realmName string, paramKV ...string) ([]ClientRepresentation, error) { +func (c *Client) GetClients(accessToken string, realmName string, paramKV ...string) ([]keycloak.ClientRepresentation, error) { if len(paramKV)%2 != 0 { - return nil, errors.New(MsgErrInvalidParam + "." + EvenParams) + return nil, errors.New(keycloak.MsgErrInvalidParam + "." + keycloak.EvenParams) } - var resp = []ClientRepresentation{} + var resp = []keycloak.ClientRepresentation{} var plugins = append(createQueryPlugins(paramKV...), url.Path(clientsPath), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, plugins...) return resp, err } // GetClient get the representation of the client. idClient is the id of client (not client-id). -func (c *Client) GetClient(accessToken string, realmName, idClient string) (ClientRepresentation, error) { - var resp = ClientRepresentation{} +func (c *Client) GetClient(accessToken string, realmName, idClient string) (keycloak.ClientRepresentation, error) { + var resp = keycloak.ClientRepresentation{} var err = c.get(accessToken, &resp, url.Path(clientIDPath), url.Param("realm", realmName), url.Param("id", idClient)) return resp, err } -func (c *Client) GetClientMappers(accessToke string, realmName, idClient string) ([]ClientMapperRepresentation, error) { - var resp = []ClientMapperRepresentation{} +// GetClientMappers gets mappers of the client specified by id +func (c *Client) GetClientMappers(accessToke string, realmName, idClient string) ([]keycloak.ClientMapperRepresentation, error) { + var resp = []keycloak.ClientMapperRepresentation{} var err = c.get(accessToke, &resp, url.Path(clientMappersPath), url.Param("realm", realmName), url.Param("id", idClient)) return resp, err } // GetSecret get the client secret. idClient is the id of client (not client-id). -func (c *Client) GetSecret(accessToken string, realmName, idClient string) (CredentialRepresentation, error) { - var resp = CredentialRepresentation{} +func (c *Client) GetSecret(accessToken string, realmName, idClient string) (keycloak.CredentialRepresentation, error) { + var resp = keycloak.CredentialRepresentation{} var err = c.get(accessToken, &resp, url.Path(clientSecret), url.Param("realm", realmName), url.Param("id", idClient)) return resp, err } diff --git a/credentials.go b/api/credentials.go similarity index 93% rename from credentials.go rename to api/credentials.go index d563511..7700e45 100644 --- a/credentials.go +++ b/api/credentials.go @@ -1,6 +1,7 @@ -package keycloak +package api import ( + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/headers" "gopkg.in/h2non/gentleman.v2/plugins/url" @@ -17,13 +18,13 @@ const ( ) // ResetPassword resets password of the user. -func (c *Client) ResetPassword(accessToken string, realmName, userID string, cred CredentialRepresentation) error { +func (c *Client) ResetPassword(accessToken string, realmName, userID string, cred keycloak.CredentialRepresentation) error { return c.put(accessToken, url.Path(resetPasswordPath), url.Param("realm", realmName), url.Param("id", userID), body.JSON(cred)) } // GetCredentials returns the list of credentials of the user -func (c *Client) GetCredentials(accessToken string, realmName string, userID string) ([]CredentialRepresentation, error) { - var resp = []CredentialRepresentation{} +func (c *Client) GetCredentials(accessToken string, realmName string, userID string) ([]keycloak.CredentialRepresentation, error) { + var resp = []keycloak.CredentialRepresentation{} var err = c.get(accessToken, &resp, url.Path(credentialsPath), url.Param("realm", realmName), url.Param("id", userID)) return resp, err diff --git a/groups.go b/api/groups.go similarity index 79% rename from groups.go rename to api/groups.go index c0d5a0a..1a98066 100644 --- a/groups.go +++ b/api/groups.go @@ -1,6 +1,7 @@ -package keycloak +package api import ( + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/url" ) @@ -13,21 +14,21 @@ const ( ) // GetGroups gets all groups for the realm -func (c *Client) GetGroups(accessToken string, realmName string) ([]GroupRepresentation, error) { - var resp = []GroupRepresentation{} +func (c *Client) GetGroups(accessToken string, realmName string) ([]keycloak.GroupRepresentation, error) { + var resp = []keycloak.GroupRepresentation{} var err = c.get(accessToken, &resp, url.Path(groupsPath), url.Param("realm", realmName)) return resp, err } // GetGroup gets a specific group’s representation -func (c *Client) GetGroup(accessToken string, realmName string, groupID string) (GroupRepresentation, error) { - var resp = GroupRepresentation{} +func (c *Client) GetGroup(accessToken string, realmName string, groupID string) (keycloak.GroupRepresentation, error) { + var resp = keycloak.GroupRepresentation{} var err = c.get(accessToken, &resp, url.Path(groupByIDPath), url.Param("realm", realmName), url.Param("id", groupID)) return resp, err } // CreateGroup creates the group from its GroupRepresentation. The group name must be unique. -func (c *Client) CreateGroup(accessToken string, reqRealmName string, group GroupRepresentation) (string, error) { +func (c *Client) CreateGroup(accessToken string, reqRealmName string, group keycloak.GroupRepresentation) (string, error) { return c.post(accessToken, nil, url.Path(groupsPath), url.Param("realm", reqRealmName), body.JSON(group)) } @@ -37,26 +38,26 @@ func (c *Client) DeleteGroup(accessToken string, realmName string, groupID strin } // AssignClientRole assigns client roles to a specific group -func (c *Client) AssignClientRole(accessToken string, realmName string, groupID string, clientID string, roles []RoleRepresentation) error { +func (c *Client) AssignClientRole(accessToken string, realmName string, groupID string, clientID string, roles []keycloak.RoleRepresentation) error { _, err := c.post(accessToken, nil, url.Path(groupClientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("clientId", clientID), body.JSON(roles)) return err } // RemoveClientRole deletes client roles from a specific group -func (c *Client) RemoveClientRole(accessToken string, realmName string, groupID string, clientID string, roles []RoleRepresentation) error { +func (c *Client) RemoveClientRole(accessToken string, realmName string, groupID string, clientID string, roles []keycloak.RoleRepresentation) error { return c.delete(accessToken, url.Path(groupClientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("clientId", clientID), body.JSON(roles)) } // GetGroupClientRoles gets client roles assigned to a specific group -func (c *Client) GetGroupClientRoles(accessToken string, realmName string, groupID string, clientID string) ([]RoleRepresentation, error) { - var roles = []RoleRepresentation{} +func (c *Client) GetGroupClientRoles(accessToken string, realmName string, groupID string, clientID string) ([]keycloak.RoleRepresentation, error) { + var roles = []keycloak.RoleRepresentation{} var err = c.get(accessToken, &roles, url.Path(groupClientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("clientId", clientID)) return roles, err } // GetAvailableGroupClientRoles gets client roles available in a specific group -func (c *Client) GetAvailableGroupClientRoles(accessToken string, realmName string, groupID string, clientID string) ([]RoleRepresentation, error) { - var roles = []RoleRepresentation{} +func (c *Client) GetAvailableGroupClientRoles(accessToken string, realmName string, groupID string, clientID string) ([]keycloak.RoleRepresentation, error) { + var roles = []keycloak.RoleRepresentation{} var err = c.get(accessToken, &roles, url.Path(availableGroupClientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("clientId", clientID)) return roles, err } diff --git a/identity_providers.go b/api/identity_providers.go similarity index 57% rename from identity_providers.go rename to api/identity_providers.go index f0828f0..d61db00 100644 --- a/identity_providers.go +++ b/api/identity_providers.go @@ -1,6 +1,7 @@ -package keycloak +package api import ( + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/url" ) @@ -10,20 +11,23 @@ const ( idpMappersPath = idpAliasPath + "/mappers" ) -func (c *Client) GetIdps(accessToken string, realmName string) ([]IdentityProviderRepresentation, error) { - var resp = []IdentityProviderRepresentation{} +// GetIdps gets the list of identity providers +func (c *Client) GetIdps(accessToken string, realmName string) ([]keycloak.IdentityProviderRepresentation, error) { + var resp = []keycloak.IdentityProviderRepresentation{} var err = c.get(accessToken, &resp, url.Path(idpsPath), url.Param("realm", realmName)) return resp, err } -func (c *Client) GetIdp(accessToken string, realmName string, idpAlias string) (IdentityProviderRepresentation, error) { - var resp = IdentityProviderRepresentation{} +// GetIdp gets an identity provider matching the given alias +func (c *Client) GetIdp(accessToken string, realmName string, idpAlias string) (keycloak.IdentityProviderRepresentation, error) { + var resp = keycloak.IdentityProviderRepresentation{} var err = c.get(accessToken, &resp, url.Path(idpAliasPath), url.Param("realm", realmName), url.Param("alias", idpAlias)) return resp, err } -func (c *Client) GetIdpMappers(accessToken string, realmName string, idpAlias string) ([]IdentityProviderMapperRepresentation, error) { - var resp = []IdentityProviderMapperRepresentation{} +// GetIdpMappers gets the mappers of the specified identity provider +func (c *Client) GetIdpMappers(accessToken string, realmName string, idpAlias string) ([]keycloak.IdentityProviderMapperRepresentation, error) { + var resp = []keycloak.IdentityProviderMapperRepresentation{} var err = c.get(accessToken, &resp, url.Path(idpMappersPath), url.Param("realm", realmName), url.Param("alias", idpAlias)) return resp, err } diff --git a/keycloak_client.go b/api/keycloak_client.go similarity index 79% rename from keycloak_client.go rename to api/keycloak_client.go index 5f49bad..3f0b206 100644 --- a/keycloak_client.go +++ b/api/keycloak_client.go @@ -1,17 +1,17 @@ -package keycloak +package api import ( "context" "encoding/json" "regexp" - "strconv" "fmt" "net/http" "net/url" - "time" commonhttp "github.com/cloudtrust/common-service/errors" + "github.com/cloudtrust/keycloak-client" + "github.com/cloudtrust/keycloak-client/toolbox" "github.com/pkg/errors" "gopkg.in/h2non/gentleman.v2" "gopkg.in/h2non/gentleman.v2/plugin" @@ -21,21 +21,12 @@ import ( jwt "github.com/gbrlsnchs/jwt" ) -// Config is the keycloak client http config. -type Config struct { - AddrTokenProvider string - AddrAPI string - Timeout time.Duration - CacheTTL time.Duration - ErrorTolerance time.Duration -} - // Client is the keycloak client. type Client struct { apiURL *url.URL httpClient *gentleman.Client account *AccountClient - issuerManager IssuerManager + issuerManager toolbox.IssuerManager } // AccountClient structure @@ -43,24 +34,14 @@ type AccountClient struct { client *Client } -// HTTPError is returned when an error occured while contacting the keycloak instance. -type HTTPError struct { - HTTPStatus int - Message string -} - -func (e HTTPError) Error() string { - return strconv.Itoa(e.HTTPStatus) + ":" + e.Message -} - // New returns a keycloak client. -func New(config Config) (*Client, error) { - var issuerMgr IssuerManager +func New(config keycloak.Config) (*Client, error) { + var issuerMgr toolbox.IssuerManager { var err error - issuerMgr, err = NewIssuerManager(config) + issuerMgr, err = toolbox.NewIssuerManager(config) if err != nil { - return nil, errors.Wrap(err, MsgErrCannotParse+"."+TokenProviderURL) + return nil, errors.Wrap(err, keycloak.MsgErrCannotParse+"."+keycloak.TokenProviderURL) } } @@ -69,7 +50,7 @@ func New(config Config) (*Client, error) { var err error uAPI, err = url.Parse(config.AddrAPI) if err != nil { - return nil, errors.Wrap(err, MsgErrCannotParse+"."+APIURL) + return nil, errors.Wrap(err, keycloak.MsgErrCannotParse+"."+keycloak.APIURL) } } @@ -109,7 +90,7 @@ func (c *Client) GetToken(realm string, username string, password string) (strin var err error resp, err = req.Do() if err != nil { - return "", errors.Wrap(err, MsgErrCannotObtain+"."+TokenMsg) + return "", errors.Wrap(err, keycloak.MsgErrCannotObtain+"."+keycloak.TokenMsg) } } defer resp.Close() @@ -119,7 +100,7 @@ func (c *Client) GetToken(realm string, username string, password string) (strin var err error err = resp.JSON(&unmarshalledBody) if err != nil { - return "", errors.Wrap(err, MsgErrCannotUnmarshal+"."+Response) + return "", errors.Wrap(err, keycloak.MsgErrCannotUnmarshal+"."+keycloak.Response) } } @@ -128,7 +109,7 @@ func (c *Client) GetToken(realm string, username string, password string) (strin var ok bool accessToken, ok = unmarshalledBody["access_token"] if !ok { - return "", fmt.Errorf(MsgErrMissingParam + "." + AccessToken) + return "", fmt.Errorf(keycloak.MsgErrMissingParam + "." + keycloak.AccessToken) } } @@ -173,12 +154,12 @@ func (c *Client) get(accessToken string, data interface{}, plugins ...plugin.Plu var err error resp, err = req.Do() if err != nil { - return errors.Wrap(err, MsgErrCannotObtain+"."+Response) + return errors.Wrap(err, keycloak.MsgErrCannotObtain+"."+keycloak.Response) } switch { case resp.StatusCode == http.StatusUnauthorized: - return HTTPError{ + return keycloak.HTTPError{ HTTPStatus: resp.StatusCode, Message: string(resp.Bytes()), } @@ -192,10 +173,10 @@ func (c *Client) get(accessToken string, data interface{}, plugins ...plugin.Plu data = resp.Bytes() return nil default: - return fmt.Errorf("%s.%v", MsgErrUnkownHTTPContentType, resp.Header.Get("Content-Type")) + return fmt.Errorf("%s.%v", keycloak.MsgErrUnkownHTTPContentType, resp.Header.Get("Content-Type")) } default: - return fmt.Errorf("%s.%v", MsgErrUnknownResponseStatusCode, resp.StatusCode) + return fmt.Errorf("%s.%v", keycloak.MsgErrUnknownResponseStatusCode, resp.StatusCode) } } } @@ -215,12 +196,12 @@ func (c *Client) post(accessToken string, data interface{}, plugins ...plugin.Pl var err error resp, err = req.Do() if err != nil { - return "", errors.Wrap(err, MsgErrCannotObtain+"."+Response) + return "", errors.Wrap(err, keycloak.MsgErrCannotObtain+"."+keycloak.Response) } switch { case resp.StatusCode == http.StatusUnauthorized: - return "", HTTPError{ + return "", keycloak.HTTPError{ HTTPStatus: resp.StatusCode, Message: string(resp.Bytes()), } @@ -239,7 +220,7 @@ func (c *Client) post(accessToken string, data interface{}, plugins ...plugin.Pl return location, nil } default: - return "", fmt.Errorf("%s.%v", MsgErrUnknownResponseStatusCode, resp.StatusCode) + return "", fmt.Errorf("%s.%v", keycloak.MsgErrUnknownResponseStatusCode, resp.StatusCode) } } } @@ -259,12 +240,12 @@ func (c *Client) delete(accessToken string, plugins ...plugin.Plugin) error { var err error resp, err = req.Do() if err != nil { - return errors.Wrap(err, MsgErrCannotObtain+"."+Response) + return errors.Wrap(err, keycloak.MsgErrCannotObtain+"."+keycloak.Response) } switch { case resp.StatusCode == http.StatusUnauthorized: - return HTTPError{ + return keycloak.HTTPError{ HTTPStatus: resp.StatusCode, Message: string(resp.Bytes()), } @@ -273,7 +254,7 @@ func (c *Client) delete(accessToken string, plugins ...plugin.Plugin) error { case resp.StatusCode >= 200: return nil default: - return HTTPError{ + return keycloak.HTTPError{ HTTPStatus: resp.StatusCode, Message: string(resp.Bytes()), } @@ -296,12 +277,12 @@ func (c *Client) put(accessToken string, plugins ...plugin.Plugin) error { var err error resp, err = req.Do() if err != nil { - return errors.Wrap(err, MsgErrCannotObtain+"."+Response) + return errors.Wrap(err, keycloak.MsgErrCannotObtain+"."+keycloak.Response) } switch { case resp.StatusCode == http.StatusUnauthorized: - return HTTPError{ + return keycloak.HTTPError{ HTTPStatus: resp.StatusCode, Message: string(resp.Bytes()), } @@ -310,7 +291,7 @@ func (c *Client) put(accessToken string, plugins ...plugin.Plugin) error { case resp.StatusCode >= 200: return nil default: - return HTTPError{ + return keycloak.HTTPError{ HTTPStatus: resp.StatusCode, Message: string(resp.Bytes()), } @@ -354,7 +335,7 @@ func extractHostFromToken(token string) (string, error) { var err error u, err = url.Parse(issuer) if err != nil { - return "", errors.Wrap(err, MsgErrCannotParse+"."+TokenProviderURL) + return "", errors.Wrap(err, keycloak.MsgErrCannotParse+"."+keycloak.TokenProviderURL) } } @@ -365,13 +346,13 @@ func extractIssuerFromToken(token string) (string, error) { payload, _, err := jwt.Parse(token) if err != nil { - return "", errors.Wrap(err, MsgErrCannotParse+"."+TokenMsg) + return "", errors.Wrap(err, keycloak.MsgErrCannotParse+"."+keycloak.TokenMsg) } var jot Token if err = jwt.Unmarshal(payload, &jot); err != nil { - return "", errors.Wrap(err, MsgErrCannotUnmarshal+"."+TokenMsg) + return "", errors.Wrap(err, keycloak.MsgErrCannotUnmarshal+"."+keycloak.TokenMsg) } return jot.Issuer, nil @@ -398,7 +379,7 @@ func treatErrorStatus(resp *gentleman.Response) error { if message, ok := response["errorMessage"]; ok && err == nil { return whitelistErrors(resp.StatusCode, message.(string)) } - return HTTPError{ + return keycloak.HTTPError{ HTTPStatus: resp.StatusCode, Message: string(resp.Bytes()), } @@ -408,12 +389,12 @@ func whitelistErrors(statusCode int, message string) error { // whitelist errors from Keycloak reg := regexp.MustCompile("invalidPassword[a-zA-Z]*Message") errorMessages := map[string]string{ - "User exists with same username or email": MsgErrExistingValue + "." + UserOrEmail, - "usernameExistsMessage": MsgErrExistingValue + "." + UserOrEmail, - "emailExistsMessage": MsgErrExistingValue + "." + UserOrEmail, - "User exists with same username": MsgErrExistingValue + "." + Username, - "User exists with same email": MsgErrExistingValue + "." + Email, - "readOnlyUsernameMessage": MsgErrReadOnly + "." + Username, + "User exists with same username or email": keycloak.MsgErrExistingValue + "." + keycloak.UserOrEmail, + "usernameExistsMessage": keycloak.MsgErrExistingValue + "." + keycloak.UserOrEmail, + "emailExistsMessage": keycloak.MsgErrExistingValue + "." + keycloak.UserOrEmail, + "User exists with same username": keycloak.MsgErrExistingValue + "." + keycloak.Username, + "User exists with same email": keycloak.MsgErrExistingValue + "." + keycloak.Email, + "readOnlyUsernameMessage": keycloak.MsgErrReadOnly + "." + keycloak.Username, } switch { @@ -431,7 +412,7 @@ func whitelistErrors(statusCode int, message string) error { Message: "keycloak." + errorMessages[message], } default: - return HTTPError{ + return keycloak.HTTPError{ HTTPStatus: statusCode, Message: message, } diff --git a/realm.go b/api/realm.go similarity index 80% rename from realm.go rename to api/realm.go index 27eae0c..3bc7256 100644 --- a/realm.go +++ b/api/realm.go @@ -1,6 +1,7 @@ -package keycloak +package api import ( + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/headers" "gopkg.in/h2non/gentleman.v2/plugins/url" @@ -15,28 +16,28 @@ const ( // GetRealms get the top level represention of all the realms. Nested information like users are // not included. -func (c *Client) GetRealms(accessToken string) ([]RealmRepresentation, error) { - var resp = []RealmRepresentation{} +func (c *Client) GetRealms(accessToken string) ([]keycloak.RealmRepresentation, error) { + var resp = []keycloak.RealmRepresentation{} var err = c.get(accessToken, &resp, url.Path(realmRootPath)) return resp, err } // CreateRealm creates the realm from its RealmRepresentation. -func (c *Client) CreateRealm(accessToken string, realm RealmRepresentation) (string, error) { +func (c *Client) CreateRealm(accessToken string, realm keycloak.RealmRepresentation) (string, error) { return c.post(accessToken, nil, url.Path(realmRootPath), body.JSON(realm)) } // GetRealm get the top level represention of the realm. Nested information like users are // not included. -func (c *Client) GetRealm(accessToken string, realmName string) (RealmRepresentation, error) { - var resp = RealmRepresentation{} +func (c *Client) GetRealm(accessToken string, realmName string) (keycloak.RealmRepresentation, error) { + var resp = keycloak.RealmRepresentation{} var err = c.get(accessToken, &resp, url.Path(realmPath), url.Param("realm", realmName)) return resp, err } // UpdateRealm update the top lovel information of the realm. Any user, role or client information // from the realm representation will be ignored. -func (c *Client) UpdateRealm(accessToken string, realmName string, realm RealmRepresentation) error { +func (c *Client) UpdateRealm(accessToken string, realmName string, realm keycloak.RealmRepresentation) error { return c.put(accessToken, url.Path(realmPath), url.Param("realm", realmName), body.JSON(realm)) } @@ -46,8 +47,8 @@ func (c *Client) DeleteRealm(accessToken string, realmName string) error { } // ExportRealm recovers the full realm. -func (c *Client) ExportRealm(accessToken string, realmName string) (RealmRepresentation, error) { - var resp = RealmRepresentation{} +func (c *Client) ExportRealm(accessToken string, realmName string) (keycloak.RealmRepresentation, error) { + var resp = keycloak.RealmRepresentation{} var err = c.get(accessToken, &resp, url.Path(exportRealmPath), url.Param("realm", realmName)) return resp, err } diff --git a/recovery_code.go b/api/recovery_code.go similarity index 65% rename from recovery_code.go rename to api/recovery_code.go index 25f7c31..affbac7 100644 --- a/recovery_code.go +++ b/api/recovery_code.go @@ -1,6 +1,7 @@ -package keycloak +package api import ( + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/query" "gopkg.in/h2non/gentleman.v2/plugins/url" ) @@ -9,14 +10,9 @@ const ( recoveryCodePath = "/auth/realms/:realm/recovery-code" ) -// RecoveryCodeRepresentation struct -type RecoveryCodeRepresentation struct { - Code *string `json:"code,omitempty"` -} - // CreateRecoveryCode creates a new recovery code authenticator and returns the code. -func (c *Client) CreateRecoveryCode(accessToken string, realmName string, userID string) (RecoveryCodeRepresentation, error) { - var resp = RecoveryCodeRepresentation{} +func (c *Client) CreateRecoveryCode(accessToken string, realmName string, userID string) (keycloak.RecoveryCodeRepresentation, error) { + var resp = keycloak.RecoveryCodeRepresentation{} _, err := c.post(accessToken, &resp, query.Add("userId", userID), url.Path(recoveryCodePath), url.Param("realm", realmName)) return resp, err diff --git a/roles.go b/api/roles.go similarity index 76% rename from roles.go rename to api/roles.go index c0fdbc9..504ec85 100644 --- a/roles.go +++ b/api/roles.go @@ -1,6 +1,7 @@ -package keycloak +package api import ( + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/url" ) @@ -12,27 +13,27 @@ const ( ) // GetClientRoles gets all roles for the realm or client -func (c *Client) GetClientRoles(accessToken string, realmName, idClient string) ([]RoleRepresentation, error) { - var resp = []RoleRepresentation{} +func (c *Client) GetClientRoles(accessToken string, realmName, idClient string) ([]keycloak.RoleRepresentation, error) { + var resp = []keycloak.RoleRepresentation{} var err = c.get(accessToken, &resp, url.Path(clientRolePath), url.Param("realm", realmName), url.Param("id", idClient)) return resp, err } // CreateClientRole creates a new role for the realm or client -func (c *Client) CreateClientRole(accessToken string, realmName, clientID string, role RoleRepresentation) (string, error) { +func (c *Client) CreateClientRole(accessToken string, realmName, clientID string, role keycloak.RoleRepresentation) (string, error) { return c.post(accessToken, nil, url.Path(clientRolePath), url.Param("realm", realmName), url.Param("id", clientID), body.JSON(role)) } // GetRoles gets all roles for the realm or client -func (c *Client) GetRoles(accessToken string, realmName string) ([]RoleRepresentation, error) { - var resp = []RoleRepresentation{} +func (c *Client) GetRoles(accessToken string, realmName string) ([]keycloak.RoleRepresentation, error) { + var resp = []keycloak.RoleRepresentation{} var err = c.get(accessToken, &resp, url.Path(rolePath), url.Param("realm", realmName)) return resp, err } // GetRole gets a specific role’s representation -func (c *Client) GetRole(accessToken string, realmName string, roleID string) (RoleRepresentation, error) { - var resp = RoleRepresentation{} +func (c *Client) GetRole(accessToken string, realmName string, roleID string) (keycloak.RoleRepresentation, error) { + var resp = keycloak.RoleRepresentation{} var err = c.get(accessToken, &resp, url.Path(roleByIDPath), url.Param("realm", realmName), url.Param("id", roleID)) return resp, err } diff --git a/statistics.go b/api/statistics.go similarity index 71% rename from statistics.go rename to api/statistics.go index 7919f1f..9f48caf 100644 --- a/statistics.go +++ b/api/statistics.go @@ -1,6 +1,7 @@ -package keycloak +package api import ( + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/url" ) @@ -10,16 +11,9 @@ const ( statisticsCredentials = statisticsPath + "/credentials" ) -// StatisticsUsersRepresentation elements returned by GetStatisticsUsers -type StatisticsUsersRepresentation struct { - Total int64 `json:"total,omitempty"` - Disabled int64 `json:"disabled,omitempty"` - Inactive int64 `json:"inactive,omitempty"` -} - // GetStatisticsUsers returns statisctics on the total number of users and on their status -func (c *Client) GetStatisticsUsers(accessToken string, realmName string) (StatisticsUsersRepresentation, error) { - var resp = StatisticsUsersRepresentation{} +func (c *Client) GetStatisticsUsers(accessToken string, realmName string) (keycloak.StatisticsUsersRepresentation, error) { + var resp = keycloak.StatisticsUsersRepresentation{} var err = c.get(accessToken, &resp, url.Path(statisticsUsers), url.Param("realm", realmName)) return resp, err } diff --git a/users.go b/api/users.go similarity index 84% rename from users.go rename to api/users.go index 23b8e06..6936480 100644 --- a/users.go +++ b/api/users.go @@ -1,8 +1,9 @@ -package keycloak +package api import ( "errors" + "github.com/cloudtrust/keycloak-client" "gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/url" ) @@ -25,10 +26,10 @@ const ( // Parameters: email, first (paging offset, int), firstName, lastName, username, // max (maximum result size, default = 100), // search (string contained in username, firstname, lastname or email) -func (c *Client) GetUsers(accessToken string, reqRealmName, targetRealmName string, paramKV ...string) (UsersPageRepresentation, error) { - var resp UsersPageRepresentation +func (c *Client) GetUsers(accessToken string, reqRealmName, targetRealmName string, paramKV ...string) (keycloak.UsersPageRepresentation, error) { + var resp keycloak.UsersPageRepresentation if len(paramKV)%2 != 0 { - return resp, errors.New(MsgErrInvalidParam + "." + EvenParams) + return resp, errors.New(keycloak.MsgErrInvalidParam + "." + keycloak.EvenParams) } var plugins = append(createQueryPlugins(paramKV...), url.Path(usersAdminExtensionAPIPath), url.Param("realmReq", reqRealmName), url.Param("realm", targetRealmName)) @@ -37,7 +38,7 @@ func (c *Client) GetUsers(accessToken string, reqRealmName, targetRealmName stri } // CreateUser creates the user from its UserRepresentation. The username must be unique. -func (c *Client) CreateUser(accessToken string, reqRealmName, targetRealmName string, user UserRepresentation) (string, error) { +func (c *Client) CreateUser(accessToken string, reqRealmName, targetRealmName string, user keycloak.UserRepresentation) (string, error) { return c.post(accessToken, nil, url.Path(usersAdminExtensionAPIPath), url.Param("realmReq", reqRealmName), url.Param("realm", targetRealmName), body.JSON(user)) } @@ -49,15 +50,15 @@ func (c *Client) CountUsers(accessToken string, realmName string) (int, error) { } // GetUser gets the represention of the user. -func (c *Client) GetUser(accessToken string, realmName, userID string) (UserRepresentation, error) { - var resp = UserRepresentation{} +func (c *Client) GetUser(accessToken string, realmName, userID string) (keycloak.UserRepresentation, error) { + var resp = keycloak.UserRepresentation{} var err = c.get(accessToken, &resp, url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID)) return resp, err } // GetGroupsOfUser gets the groups of the user. -func (c *Client) GetGroupsOfUser(accessToken string, realmName, userID string) ([]GroupRepresentation, error) { - var resp = []GroupRepresentation{} +func (c *Client) GetGroupsOfUser(accessToken string, realmName, userID string) ([]keycloak.GroupRepresentation, error) { + var resp = []keycloak.GroupRepresentation{} var err = c.get(accessToken, &resp, url.Path(userGroupsPath), url.Param("realm", realmName), url.Param("id", userID)) return resp, err } @@ -73,7 +74,7 @@ func (c *Client) DeleteGroupFromUser(accessToken string, realmName, userID, grou } // UpdateUser updates the user. -func (c *Client) UpdateUser(accessToken string, realmName, userID string, user UserRepresentation) error { +func (c *Client) UpdateUser(accessToken string, realmName, userID string, user keycloak.UserRepresentation) error { return c.put(accessToken, url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID), body.JSON(user)) } @@ -85,7 +86,7 @@ func (c *Client) DeleteUser(accessToken string, realmName, userID string) error // ExecuteActionsEmail sends an update account email to the user. An email contains a link the user can click to perform a set of required actions. func (c *Client) ExecuteActionsEmail(accessToken string, realmName string, userID string, actions []string, paramKV ...string) error { if len(paramKV)%2 != 0 { - return errors.New(MsgErrInvalidParam + "." + EvenParams) + return errors.New(keycloak.MsgErrInvalidParam + "." + keycloak.EvenParams) } var plugins = append(createQueryPlugins(paramKV...), url.Path(executeActionsEmailPath), url.Param("realm", realmName), url.Param("id", userID), body.JSON(actions)) @@ -94,11 +95,11 @@ func (c *Client) ExecuteActionsEmail(accessToken string, realmName string, userI } // SendNewEnrolmentCode sends a new enrolment code and return it -func (c *Client) SendNewEnrolmentCode(accessToken string, realmName string, userID string) (SmsCodeRepresentation, error) { +func (c *Client) SendNewEnrolmentCode(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 resp = SmsCodeRepresentation{} + var resp = keycloak.SmsCodeRepresentation{} _, err := c.post(accessToken, &resp, plugins...) @@ -108,7 +109,7 @@ func (c *Client) SendNewEnrolmentCode(accessToken string, realmName string, user // SendReminderEmail sends a reminder email to a user func (c *Client) SendReminderEmail(accessToken string, realmName string, userID string, paramKV ...string) error { if len(paramKV)%2 != 0 { - return errors.New(MsgErrInvalidParam + "." + EvenParams) + return errors.New(keycloak.MsgErrInvalidParam + "." + keycloak.EvenParams) } var newParamKV = append(paramKV, "userid", userID) @@ -119,7 +120,7 @@ func (c *Client) SendReminderEmail(accessToken string, realmName string, userID } // LinkShadowUser links shadow user to a realm in the context of brokering -func (c *Client) LinkShadowUser(accessToken string, reqRealmName string, userID string, provider string, fedIDKC FederatedIdentityRepresentation) error { +func (c *Client) LinkShadowUser(accessToken string, reqRealmName string, userID string, provider string, fedIDKC keycloak.FederatedIdentityRepresentation) error { _, 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 } diff --git a/config.go b/config.go new file mode 100644 index 0000000..094cf84 --- /dev/null +++ b/config.go @@ -0,0 +1,14 @@ +package keycloak + +import ( + "time" +) + +// Config is the keycloak client http config. +type Config struct { + AddrTokenProvider string + AddrAPI string + Timeout time.Duration + CacheTTL time.Duration + ErrorTolerance time.Duration +} diff --git a/definitions.go b/definitions.go index c4e2c04..bba81a8 100644 --- a/definitions.go +++ b/definitions.go @@ -5,7 +5,7 @@ type AdminEventRepresentation struct { AuthDetails *AuthDetailsRepresentation `json:"authDetails,omitempty"` Error *string `json:"error,omitempty"` OperationType *string `json:"operationType,omitempty"` - RealmId *string `json:"realmId,omitempty"` + RealmID *string `json:"realmId,omitempty"` Representation *string `json:"representation,omitempty"` ResourcePath *string `json:"resourcePath,omitempty"` ResourceType *string `json:"resourceType,omitempty"` @@ -14,10 +14,10 @@ type AdminEventRepresentation struct { // AuthDetailsRepresentation struct type AuthDetailsRepresentation struct { - ClientId *string `json:"clientId,omitempty"` - IpAddress *string `json:"ipAddress,omitempty"` - RealmId *string `json:"realmId,omitempty"` - UserId *string `json:"userId,omitempty"` + ClientID *string `json:"clientId,omitempty"` + IPAddress *string `json:"ipAddress,omitempty"` + RealmID *string `json:"realmId,omitempty"` + UserID *string `json:"userId,omitempty"` } // AuthenticationExecutionExportRepresentation struct @@ -39,11 +39,11 @@ type AuthenticationExecutionInfoRepresentation struct { AuthenticationFlow *bool `json:"authenticationFlow,omitempty"` Configurable *bool `json:"configurable,omitempty"` DisplayName *string `json:"displayName,omitempty"` - FlowId *string `json:"flowId,omitempty"` - Id *string `json:"id,omitempty"` + FlowID *string `json:"flowId,omitempty"` + ID *string `json:"id,omitempty"` Index *int32 `json:"index,omitempty"` Level *int32 `json:"level,omitempty"` - ProviderId *string `json:"providerId,omitempty"` + ProviderID *string `json:"providerId,omitempty"` Requirement *string `json:"requirement,omitempty"` RequirementChoices *[]string `json:"requirementChoices,omitempty"` } @@ -54,8 +54,8 @@ type AuthenticationExecutionRepresentation struct { AuthenticatorConfig *string `json:"authenticatorConfig,omitempty"` AuthenticatorFlow *bool `json:"authenticatorFlow,omitempty"` AutheticatorFlow *bool `json:"autheticatorFlow,omitempty"` - FlowId *string `json:"flowId,omitempty"` - Id *string `json:"id,omitempty"` + FlowID *string `json:"flowId,omitempty"` + ID *string `json:"id,omitempty"` ParentFlow *string `json:"parentFlow,omitempty"` Priority *int32 `json:"priority,omitempty"` Requirement *string `json:"requirement,omitempty"` @@ -67,8 +67,8 @@ type AuthenticationFlowRepresentation struct { AuthenticationExecutions *[]AuthenticationExecutionExportRepresentation `json:"authenticationExecutions,omitempty"` BuiltIn *bool `json:"builtIn,omitempty"` Description *string `json:"description,omitempty"` - Id *string `json:"id,omitempty"` - ProviderId *string `json:"providerId,omitempty"` + ID *string `json:"id,omitempty"` + ProviderID *string `json:"providerId,omitempty"` TopLevel *bool `json:"topLevel,omitempty"` } @@ -77,14 +77,14 @@ type AuthenticatorConfigInfoRepresentation struct { HelpText *string `json:"helpText,omitempty"` Name *string `json:"name,omitempty"` Properties *[]ConfigPropertyRepresentation `json:"properties,omitempty"` - ProviderId *string `json:"providerId,omitempty"` + ProviderID *string `json:"providerId,omitempty"` } // AuthenticatorConfigRepresentation struct type AuthenticatorConfigRepresentation struct { Alias *string `json:"alias,omitempty"` Config *map[string]interface{} `json:"config,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` } // CertificateRepresentation struct @@ -105,7 +105,7 @@ type ClientInitialAccessCreatePresentation struct { type ClientInitialAccessPresentation struct { Count *int32 `json:"count,omitempty"` Expiration *int32 `json:"expiration,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` RemainingCount *int32 `json:"remainingCount,omitempty"` Timestamp *int32 `json:"timestamp,omitempty"` Token *string `json:"token,omitempty"` @@ -114,10 +114,10 @@ type ClientInitialAccessPresentation struct { // ClientMapperRepresentation struct // https://www.keycloak.org/docs-api/9.0/rest-api/index.html#_clientscopeevaluateresource-protocolmapperevaluationrepresentation type ClientMapperRepresentation struct { - ContainerId *string `json:"containerId,omitempty"` + ContainerID *string `json:"containerId,omitempty"` ContainerName *string `json:"containerName,omitempty"` ContainerType *string `json:"containerType,omitempty"` - MapperId *string `json:"mapperId,omitempty"` + MapperID *string `json:"mapperId,omitempty"` MapperName *string `json:"mapperName,omitempty"` ProtocolMapper *string `json:"protocolMapper,omitempty"` } @@ -125,21 +125,21 @@ type ClientMapperRepresentation struct { // ClientMappingsRepresentation struct type ClientMappingsRepresentation struct { Client *string `json:"client,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` Mappings *[]RoleRepresentation `json:"mappings,omitempty"` } // ClientRepresentation struct type ClientRepresentation struct { Access *map[string]interface{} `json:"access,omitempty"` - AdminUrl *string `json:"adminUrl,omitempty"` + AdminURL *string `json:"adminUrl,omitempty"` Attributes *map[string]interface{} `json:"attributes,omitempty"` AuthorizationServicesEnabled *bool `json:"authorizationServicesEnabled,omitempty"` AuthorizationSettings *ResourceServerRepresentation `json:"authorizationSettings,omitempty"` - BaseUrl *string `json:"baseUrl,omitempty"` + BaseURL *string `json:"baseUrl,omitempty"` BearerOnly *bool `json:"bearerOnly,omitempty"` ClientAuthenticatorType *string `json:"clientAuthenticatorType,omitempty"` - ClientId *string `json:"clientId,omitempty"` + ClientID *string `json:"clientId,omitempty"` ClientTemplate *string `json:"clientTemplate,omitempty"` ConsentRequired *bool `json:"consentRequired,omitempty"` DefaultRoles *[]string `json:"defaultRoles,omitempty"` @@ -148,7 +148,7 @@ type ClientRepresentation struct { Enabled *bool `json:"enabled,omitempty"` FrontchannelLogout *bool `json:"frontchannelLogout,omitempty"` FullScopeAllowed *bool `json:"fullScopeAllowed,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` ImplicitFlowEnabled *bool `json:"implicitFlowEnabled,omitempty"` Name *string `json:"name,omitempty"` NodeReRegistrationTimeout *int32 `json:"nodeReRegistrationTimeout,omitempty"` @@ -159,7 +159,7 @@ type ClientRepresentation struct { RedirectUris *[]string `json:"redirectUris,omitempty"` RegisteredNodes *map[string]interface{} `json:"registeredNodes,omitempty"` RegistrationAccessToken *string `json:"registrationAccessToken,omitempty"` - RootUrl *string `json:"rootUrl,omitempty"` + RootURL *string `json:"rootUrl,omitempty"` Secret *string `json:"secret,omitempty"` ServiceAccountsEnabled *bool `json:"serviceAccountsEnabled,omitempty"` StandardFlowEnabled *bool `json:"standardFlowEnabled,omitempty"` @@ -179,7 +179,7 @@ type ClientTemplateRepresentation struct { DirectAccessGrantsEnabled *bool `json:"directAccessGrantsEnabled,omitempty"` FrontchannelLogout *bool `json:"frontchannelLogout,omitempty"` FullScopeAllowed *bool `json:"fullScopeAllowed,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` ImplicitFlowEnabled *bool `json:"implicitFlowEnabled,omitempty"` Name *string `json:"name,omitempty"` Protocol *string `json:"protocol,omitempty"` @@ -192,9 +192,9 @@ type ClientTemplateRepresentation struct { // ComponentExportRepresentation struct type ComponentExportRepresentation struct { Config *MultivaluedHashMap `json:"config,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` - ProviderId *string `json:"providerId,omitempty"` + ProviderID *string `json:"providerId,omitempty"` SubComponents *MultivaluedHashMap `json:"subComponents,omitempty"` SubType *string `json:"subType,omitempty"` } @@ -202,10 +202,10 @@ type ComponentExportRepresentation struct { // ComponentRepresentation struct type ComponentRepresentation struct { Config *MultivaluedHashMap `json:"config,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` - ParentId *string `json:"parentId,omitempty"` - ProviderId *string `json:"providerId,omitempty"` + ParentID *string `json:"parentId,omitempty"` + ProviderID *string `json:"providerId,omitempty"` ProviderType *string `json:"providerType,omitempty"` SubType *string `json:"subType,omitempty"` } @@ -213,7 +213,7 @@ type ComponentRepresentation struct { // ComponentTypeRepresentation struct type ComponentTypeRepresentation struct { HelpText *string `json:"helpText,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` Metadata *map[string]interface{} `json:"metadata,omitempty"` Properties *[]ConfigPropertyRepresentation `json:"properties,omitempty"` } @@ -231,7 +231,7 @@ type ConfigPropertyRepresentation struct { // CredentialRepresentation struct type CredentialRepresentation struct { - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` Type *string `json:"type,omitempty"` UserLabel *string `json:"userLabel,omitempty"` CreatedDate *int64 `json:"createdDate,omitempty"` @@ -242,21 +242,21 @@ type CredentialRepresentation struct { // EventRepresentation struct type EventRepresentation struct { - ClientId *string `json:"clientId,omitempty"` + ClientID *string `json:"clientId,omitempty"` Details *map[string]interface{} `json:"details,omitempty"` Error *string `json:"error,omitempty"` - IpAddress *string `json:"ipAddress,omitempty"` - RealmId *string `json:"realmId,omitempty"` - SessionId *string `json:"sessionId,omitempty"` + IPAddress *string `json:"ipAddress,omitempty"` + RealmID *string `json:"realmId,omitempty"` + SessionID *string `json:"sessionId,omitempty"` Time *int64 `json:"time,omitempty"` Type *string `json:"type,omitempty"` - UserId *string `json:"userId,omitempty"` + UserID *string `json:"userId,omitempty"` } // FederatedIdentityRepresentation struct type FederatedIdentityRepresentation struct { IdentityProvider *string `json:"identityProvider,omitempty"` - UserId *string `json:"userId,omitempty"` + UserID *string `json:"userId,omitempty"` UserName *string `json:"userName,omitempty"` } @@ -271,7 +271,7 @@ type GroupRepresentation struct { Access *map[string]interface{} `json:"access,omitempty"` Attributes *map[string]interface{} `json:"attributes,omitempty"` ClientRoles *map[string]interface{} `json:"clientRoles,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` Path *string `json:"path,omitempty"` RealmRoles *[]string `json:"realmRoles,omitempty"` @@ -281,7 +281,7 @@ type GroupRepresentation struct { // IdentityProviderMapperRepresentation struct type IdentityProviderMapperRepresentation struct { Config *map[string]interface{} `json:"config,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` IdentityProviderAlias *string `json:"identityProviderAlias,omitempty"` IdentityProviderMapper *string `json:"identityProviderMapper,omitempty"` Name *string `json:"name,omitempty"` @@ -295,10 +295,10 @@ type IdentityProviderRepresentation struct { DisplayName *string `json:"displayName,omitempty"` Enabled *bool `json:"enabled,omitempty"` FirstBrokerLoginFlowAlias *string `json:"firstBrokerLoginFlowAlias,omitempty"` - InternalId *string `json:"internalId,omitempty"` + InternalID *string `json:"internalId,omitempty"` LinkOnly *bool `json:"linkOnly,omitempty"` PostBrokerLoginFlowAlias *string `json:"postBrokerLoginFlowAlias,omitempty"` - ProviderId *string `json:"providerId,omitempty"` + ProviderID *string `json:"providerId,omitempty"` StoreToken *bool `json:"storeToken,omitempty"` TrustEmail *bool `json:"trustEmail,omitempty"` } @@ -313,7 +313,7 @@ type KeysMetadataRepresentation struct { type KeysMetadataRepresentationKeyMetadataRepresentation struct { Certificate *string `json:"certificate,omitempty"` Kid *string `json:"kid,omitempty"` - ProviderId *string `json:"providerId,omitempty"` + ProviderID *string `json:"providerId,omitempty"` ProviderPriority *int64 `json:"providerPriority,omitempty"` PublicKey *string `json:"publicKey,omitempty"` Status *string `json:"status,omitempty"` @@ -377,7 +377,7 @@ type PasswordPolicyTypeRepresentation struct { ConfigType *string `json:"configType,omitempty"` DefaultValue *string `json:"defaultValue,omitempty"` DisplayName *string `json:"displayName,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` MultipleSupported *bool `json:"multipleSupported,omitempty"` } @@ -386,7 +386,7 @@ type PolicyRepresentation struct { Config *map[string]interface{} `json:"config,omitempty"` DecisionStrategy *string `json:"decisionStrategy,omitempty"` Description *string `json:"description,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` Logic *string `json:"logic,omitempty"` Name *string `json:"name,omitempty"` Policies *[]string `json:"policies,omitempty"` @@ -406,7 +406,7 @@ type ProtocolMapperRepresentation struct { Config *map[string]interface{} `json:"config,omitempty"` ConsentRequired *bool `json:"consentRequired,omitempty"` ConsentText *string `json:"consentText,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` Protocol *string `json:"protocol,omitempty"` ProtocolMapper *string `json:"protocolMapper,omitempty"` @@ -457,7 +457,7 @@ type RealmRepresentation struct { DefaultRoles *[]string `json:"defaultRoles,omitempty"` DirectGrantFlow *string `json:"directGrantFlow,omitempty"` DisplayName *string `json:"displayName,omitempty"` - DisplayNameHtml *string `json:"displayNameHtml,omitempty"` + DisplayNameHTML *string `json:"displayNameHtml,omitempty"` DockerAuthenticationFlow *string `json:"dockerAuthenticationFlow,omitempty"` DuplicateEmailsAllowed *bool `json:"duplicateEmailsAllowed,omitempty"` EditUsernameAllowed *bool `json:"editUsernameAllowed,omitempty"` @@ -470,7 +470,7 @@ type RealmRepresentation struct { FailureFactor *int32 `json:"failureFactor,omitempty"` FederatedUsers *[]UserRepresentation `json:"federatedUsers,omitempty"` Groups *[]GroupRepresentation `json:"groups,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` IdentityProviderMappers *[]IdentityProviderMapperRepresentation `json:"identityProviderMappers,omitempty"` IdentityProviders *[]IdentityProviderRepresentation `json:"identityProviders,omitempty"` InternationalizationEnabled *bool `json:"internationalizationEnabled,omitempty"` @@ -505,7 +505,7 @@ type RealmRepresentation struct { RevokeRefreshToken *bool `json:"revokeRefreshToken,omitempty"` Roles *RolesRepresentation `json:"roles,omitempty"` ScopeMappings *[]ScopeMappingRepresentation `json:"scopeMappings,omitempty"` - SmtpServer *map[string]interface{} `json:"smtpServer,omitempty"` + SMTPServer *map[string]interface{} `json:"smtpServer,omitempty"` SslRequired *string `json:"sslRequired,omitempty"` SsoSessionIdleTimeout *int32 `json:"ssoSessionIdleTimeout,omitempty"` SsoSessionMaxLifespan *int32 `json:"ssoSessionMaxLifespan,omitempty"` @@ -524,33 +524,33 @@ type RequiredActionProviderRepresentation struct { DefaultAction *bool `json:"defaultAction,omitempty"` Enabled *bool `json:"enabled,omitempty"` Name *string `json:"name,omitempty"` - ProviderId *string `json:"providerId,omitempty"` + ProviderID *string `json:"providerId,omitempty"` } // ResourceOwnerRepresentation struct type ResourceOwnerRepresentation struct { - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` } // ResourceRepresentation struct type ResourceRepresentation struct { - Id *string `json:"id,omitempty"` - Icon_uri *string `json:"icon_uri,omitempty"` + ID *string `json:"id,omitempty"` + IconURI *string `json:"icon_uri,omitempty"` Name *string `json:"name,omitempty"` Owner *ResourceOwnerRepresentation `json:"owner,omitempty"` Policies *[]PolicyRepresentation `json:"policies,omitempty"` Scopes *[]ScopeRepresentation `json:"scopes,omitempty"` Type *string `json:"type,omitempty"` TypedScopes *[]ScopeRepresentation `json:"typedScopes,omitempty"` - Uri *string `json:"uri,omitempty"` + URI *string `json:"uri,omitempty"` } // ResourceServerRepresentation struct type ResourceServerRepresentation struct { AllowRemoteResourceManagement *bool `json:"allowRemoteResourceManagement,omitempty"` - ClientId *string `json:"clientId,omitempty"` - Id *string `json:"id,omitempty"` + ClientID *string `json:"clientId,omitempty"` + ID *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` Policies *[]PolicyRepresentation `json:"policies,omitempty"` PolicyEnforcementMode *string `json:"policyEnforcementMode,omitempty"` @@ -563,9 +563,9 @@ type RoleRepresentation struct { ClientRole *bool `json:"clientRole,omitempty"` Composite *bool `json:"composite,omitempty"` Composites *RoleRepresentationComposites `json:"composites,omitempty"` - ContainerId *string `json:"containerId,omitempty"` + ContainerID *string `json:"containerId,omitempty"` Description *string `json:"description,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` ScopeParamRequired *bool `json:"scopeParamRequired,omitempty"` } @@ -592,8 +592,8 @@ type ScopeMappingRepresentation struct { // ScopeRepresentation struct type ScopeRepresentation struct { - IconUri *string `json:"iconUri,omitempty"` - Id *string `json:"id,omitempty"` + IconURI *string `json:"iconUri,omitempty"` + ID *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` Policies *[]PolicyRepresentation `json:"policies,omitempty"` Resources *[]ResourceRepresentation `json:"resources,omitempty"` @@ -640,8 +640,8 @@ type SystemInfoRepresentation struct { JavaRuntime *string `json:"javaRuntime,omitempty"` JavaVendor *string `json:"javaVendor,omitempty"` JavaVersion *string `json:"javaVersion,omitempty"` - JavaVm *string `json:"javaVm,omitempty"` - JavaVmVersion *string `json:"javaVmVersion,omitempty"` + JavaVM *string `json:"javaVm,omitempty"` + JavaVMVersion *string `json:"javaVmVersion,omitempty"` OsArchitecture *string `json:"osArchitecture,omitempty"` OsName *string `json:"osName,omitempty"` OsVersion *string `json:"osVersion,omitempty"` @@ -657,7 +657,7 @@ type SystemInfoRepresentation struct { // UserConsentRepresentation struct type UserConsentRepresentation struct { - ClientId *string `json:"clientId,omitempty"` + ClientID *string `json:"clientId,omitempty"` CreatedDate *int64 `json:"createdDate,omitempty"` GrantedClientRoles *map[string]interface{} `json:"grantedClientRoles,omitempty"` GrantedProtocolMappers *map[string]interface{} `json:"grantedProtocolMappers,omitempty"` @@ -670,7 +670,7 @@ type UserFederationMapperRepresentation struct { Config *map[string]interface{} `json:"config,omitempty"` FederationMapperType *string `json:"federationMapperType,omitempty"` FederationProviderDisplayName *string `json:"federationProviderDisplayName,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` } @@ -680,7 +680,7 @@ type UserFederationProviderRepresentation struct { Config *map[string]interface{} `json:"config,omitempty"` DisplayName *string `json:"displayName,omitempty"` FullSyncPeriod *int32 `json:"fullSyncPeriod,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` LastSync *int32 `json:"lastSync,omitempty"` Priority *int32 `json:"priority,omitempty"` ProviderName *string `json:"providerName,omitempty"` @@ -708,14 +708,14 @@ type UserRepresentation struct { FederationLink *string `json:"federationLink,omitempty"` FirstName *string `json:"firstName,omitempty"` Groups *[]string `json:"groups,omitempty"` - Id *string `json:"id,omitempty"` + ID *string `json:"id,omitempty"` LastName *string `json:"lastName,omitempty"` NotBefore *int32 `json:"notBefore,omitempty"` Origin *string `json:"origin,omitempty"` RealmRoles *[]string `json:"realmRoles,omitempty"` RequiredActions *[]string `json:"requiredActions,omitempty"` Self *string `json:"self,omitempty"` - ServiceAccountClientId *string `json:"serviceAccountClientId,omitempty"` + ServiceAccountClientID *string `json:"serviceAccountClientId,omitempty"` Username *string `json:"username,omitempty"` } @@ -728,11 +728,11 @@ type UsersPageRepresentation struct { // UserSessionRepresentation struct type UserSessionRepresentation struct { Clients *map[string]interface{} `json:"clients,omitempty"` - Id *string `json:"id,omitempty"` - IpAddress *string `json:"ipAddress,omitempty"` + ID *string `json:"id,omitempty"` + IPAddress *string `json:"ipAddress,omitempty"` LastAccess *int64 `json:"lastAccess,omitempty"` Start *int64 `json:"start,omitempty"` - UserId *string `json:"userId,omitempty"` + UserID *string `json:"userId,omitempty"` Username *string `json:"username,omitempty"` } @@ -740,3 +740,15 @@ type UserSessionRepresentation struct { type SmsCodeRepresentation struct { Code *string `json:"code,omitempty"` } + +// StatisticsUsersRepresentation elements returned by GetStatisticsUsers +type StatisticsUsersRepresentation struct { + Total int64 `json:"total,omitempty"` + Disabled int64 `json:"disabled,omitempty"` + Inactive int64 `json:"inactive,omitempty"` +} + +// RecoveryCodeRepresentation struct +type RecoveryCodeRepresentation struct { + Code *string `json:"code,omitempty"` +} diff --git a/errormessages.go b/errormessages.go index 6052136..0c31356 100644 --- a/errormessages.go +++ b/errormessages.go @@ -1,5 +1,7 @@ package keycloak +import "strconv" + // Constants for error management const ( MsgErrMissingParam = "missingParameter" @@ -25,3 +27,13 @@ const ( Username = "username" Email = "email" ) + +// HTTPError is returned when an error occured while contacting the keycloak instance. +type HTTPError struct { + HTTPStatus int + Message string +} + +func (e HTTPError) Error() string { + return strconv.Itoa(e.HTTPStatus) + ":" + e.Message +} diff --git a/integration/integration.go b/integration/integration_test.go similarity index 97% rename from integration/integration.go rename to integration/integration_test.go index 0ea2ef0..fbed72d 100644 --- a/integration/integration.go +++ b/integration/integration_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/cloudtrust/keycloak-client" + api "github.com/cloudtrust/keycloak-client/api" "github.com/spf13/pflag" ) @@ -19,7 +20,7 @@ const ( func main() { var conf = getKeycloakConfig() - var client, err = keycloak.New(*conf) + var client, err = api.New(*conf) if err != nil { log.Fatalf("could not create keycloak client: %v", err) } @@ -156,7 +157,7 @@ func main() { log.Fatalf("there should be 50 users") } - user, err := client.GetUser(accessToken, tstRealm, *(users.Users[0].Id)) + user, err := client.GetUser(accessToken, tstRealm, *(users.Users[0].ID)) if err != nil { log.Fatalf("could not get user") } @@ -244,10 +245,10 @@ func main() { if len(users.Users) != 1 { log.Fatalf("there should be 1 users matched by search Maria") } - if users.Users[0].Id == nil { + if users.Users[0].ID == nil { log.Fatalf("user ID should not be nil") } - userID = *users.Users[0].Id + userID = *users.Users[0].ID } // Update user. var username = "Maria" @@ -301,10 +302,10 @@ func main() { if len(users.Users) != 1 { log.Fatalf("there should be 1 users matched by search Toni") } - if users.Users[0].Id == nil { + if users.Users[0].ID == nil { log.Fatalf("user ID should not be nil") } - userID = *users.Users[0].Id + userID = *users.Users[0].ID } // Delete user. { diff --git a/issuer.go b/toolbox/issuer.go similarity index 93% rename from issuer.go rename to toolbox/issuer.go index 732f7ea..4bc4db4 100644 --- a/issuer.go +++ b/toolbox/issuer.go @@ -1,4 +1,4 @@ -package keycloak +package toolbox import ( "context" @@ -9,6 +9,7 @@ import ( "time" cs "github.com/cloudtrust/common-service" + "github.com/cloudtrust/keycloak-client" ) // IssuerManager provides URL according to a given context @@ -31,7 +32,7 @@ func getProtocolAndDomain(URL string) string { } // NewIssuerManager creates a new URLProvider -func NewIssuerManager(config Config) (IssuerManager, error) { +func NewIssuerManager(config keycloak.Config) (IssuerManager, error) { URLs := config.AddrTokenProvider // Use default values when clients are not initializing these values cacheTTL := config.CacheTTL diff --git a/issuer_test.go b/toolbox/issuer_test.go similarity index 88% rename from issuer_test.go rename to toolbox/issuer_test.go index 8b89edc..d3d3ed7 100644 --- a/issuer_test.go +++ b/toolbox/issuer_test.go @@ -1,4 +1,4 @@ -package keycloak +package toolbox import ( "context" @@ -6,6 +6,7 @@ import ( "testing" cs "github.com/cloudtrust/common-service" + "github.com/cloudtrust/keycloak-client" "github.com/stretchr/testify/assert" ) @@ -17,7 +18,7 @@ func TestGetProtocolAndDomain(t *testing.T) { func TestNewIssuerManager(t *testing.T) { { - _, err := NewIssuerManager(Config{AddrTokenProvider: ":"}) + _, err := NewIssuerManager(keycloak.Config{AddrTokenProvider: ":"}) assert.NotNil(t, err) } @@ -26,7 +27,7 @@ func TestNewIssuerManager(t *testing.T) { otherDomainPath := "http://other.domain.com:2120/" allDomains := fmt.Sprintf("%s %s %s", defaultPath, myDomainPath, otherDomainPath) - prov, err := NewIssuerManager(Config{AddrTokenProvider: allDomains}) + prov, err := NewIssuerManager(keycloak.Config{AddrTokenProvider: allDomains}) assert.Nil(t, err) assert.NotNil(t, prov) diff --git a/oidc_connect.go b/toolbox/oidc_connect.go similarity index 94% rename from oidc_connect.go rename to toolbox/oidc_connect.go index 97fc27e..fbe5a44 100644 --- a/oidc_connect.go +++ b/toolbox/oidc_connect.go @@ -1,4 +1,4 @@ -package keycloak +package toolbox import ( "bytes" @@ -12,6 +12,7 @@ import ( errorhandler "github.com/cloudtrust/common-service/errors" "github.com/cloudtrust/common-service/log" + "github.com/cloudtrust/keycloak-client" ) // OidcTokenProvider provides OIDC tokens @@ -45,7 +46,7 @@ const ( ) // NewOidcTokenProvider creates an OidcTokenProvider -func NewOidcTokenProvider(config Config, realm, username, password, clientID string, logger log.Logger) OidcTokenProvider { +func NewOidcTokenProvider(config keycloak.Config, realm, username, password, clientID string, logger log.Logger) OidcTokenProvider { var urls = strings.Split(config.AddrTokenProvider, " ") var keycloakPublicURL = urls[0] diff --git a/oidc_connect_test.go b/toolbox/oidc_connect_test.go similarity index 88% rename from oidc_connect_test.go rename to toolbox/oidc_connect_test.go index 73dbe6e..1a0d590 100644 --- a/oidc_connect_test.go +++ b/toolbox/oidc_connect_test.go @@ -1,4 +1,4 @@ -package keycloak +package toolbox import ( "context" @@ -10,6 +10,7 @@ import ( "time" "github.com/cloudtrust/common-service/log" + "github.com/cloudtrust/keycloak-client" "github.com/gorilla/mux" "github.com/stretchr/testify/assert" ) @@ -45,31 +46,31 @@ func TestCreateToken(t *testing.T) { defer ts.Close() t.Run("No body in HTTP response", func(t *testing.T) { - var p = NewOidcTokenProvider(Config{AddrTokenProvider: ts.URL}, "nobody", "user", "passwd", "clientID", log.NewNopLogger()) + var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL}, "nobody", "user", "passwd", "clientID", log.NewNopLogger()) var _, err = p.ProvideToken(context.TODO()) assert.NotNil(t, err) }) t.Run("Invalid credentials", func(t *testing.T) { - var p = NewOidcTokenProvider(Config{AddrTokenProvider: ts.URL}, "invalid", "user", "passwd", "clientID", log.NewNopLogger()) + var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL}, "invalid", "user", "passwd", "clientID", log.NewNopLogger()) var _, err = p.ProvideToken(context.TODO()) assert.NotNil(t, err) }) t.Run("Invalid JSON", func(t *testing.T) { - var p = NewOidcTokenProvider(Config{AddrTokenProvider: ts.URL}, "bad-json", "user", "passwd", "clientID", log.NewNopLogger()) + var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL}, "bad-json", "user", "passwd", "clientID", log.NewNopLogger()) var _, err = p.ProvideToken(context.TODO()) assert.NotNil(t, err) }) t.Run("No HTTP response", func(t *testing.T) { - var p = NewOidcTokenProvider(Config{AddrTokenProvider: ts.URL + "0"}, "bad-json", "user", "passwd", "clientID", log.NewNopLogger()) + var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL + "0"}, "bad-json", "user", "passwd", "clientID", log.NewNopLogger()) var _, err = p.ProvideToken(context.TODO()) assert.NotNil(t, err) }) t.Run("Valid credentials", func(t *testing.T) { - var p = NewOidcTokenProvider(Config{AddrTokenProvider: ts.URL}, "valid", "user", "passwd", "clientID", log.NewNopLogger()) + var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL}, "valid", "user", "passwd", "clientID", log.NewNopLogger()) var timeStart = time.Now() diff --git a/oidc_verifier.go b/toolbox/oidc_verifier.go similarity index 93% rename from oidc_verifier.go rename to toolbox/oidc_verifier.go index 35f1b39..cc02885 100644 --- a/oidc_verifier.go +++ b/toolbox/oidc_verifier.go @@ -1,4 +1,4 @@ -package keycloak +package toolbox import ( "context" @@ -6,6 +6,7 @@ import ( "net/url" "time" + "github.com/cloudtrust/keycloak-client" oidc "github.com/coreos/go-oidc" "github.com/pkg/errors" ) @@ -55,7 +56,7 @@ func (vc *verifierCache) GetOidcVerifier(realm string) (OidcVerifier, error) { var issuer = fmt.Sprintf("%s/auth/realms/%s", vc.tokenURL.String(), realm) oidcProvider, err = oidc.NewProvider(context.Background(), issuer) if err != nil { - return nil, errors.Wrap(err, MsgErrCannotCreate+"."+OIDCProvider) + return nil, errors.Wrap(err, keycloak.MsgErrCannotCreate+"."+keycloak.OIDCProvider) } } diff --git a/oidc_verifier_test.go b/toolbox/oidc_verifier_test.go similarity index 99% rename from oidc_verifier_test.go rename to toolbox/oidc_verifier_test.go index bf64f43..b765334 100644 --- a/oidc_verifier_test.go +++ b/toolbox/oidc_verifier_test.go @@ -1,4 +1,4 @@ -package keycloak +package toolbox //go:generate mockgen -destination=./mock/authmanager.go -package=mock -mock_names=AuthorizationManager=AuthorizationManager github.com/cloudtrust/common-service/security AuthorizationManager