diff --git a/client.go b/client.go index c06063be..e54aad17 100644 --- a/client.go +++ b/client.go @@ -4507,3 +4507,210 @@ func (g *GoCloak) GetUsersManagementPermissions(ctx context.Context, accessToken return &result, nil } + +// CreateOrganization creates a new Organization +func (g *GoCloak) CreateOrganization(ctx context.Context, token, realm string, organization OrganizationRepresentation) (string, error) { + const errMessage = "could not create organization" + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetBody(organization). + Post(g.getAdminRealmURL(realm, "organizations")) + + if err := checkForError(resp, err, errMessage); err != nil { + return "", err + } + + return getID(resp), nil +} + +// GetOrganizations returns a paginated list of organizations filtered according to the specified parameters +func (g *GoCloak) GetOrganizations(ctx context.Context, token, realm string, params GetOrganizationsParams) ([]*OrganizationRepresentation, error) { + const errMessage = "could not get organizations" + + queryParams, err := GetQueryParams(params) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } + + var result []*OrganizationRepresentation + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetQueryParams(queryParams). + SetResult(&result). + Get(g.getAdminRealmURL(realm, "organizations")) + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + +// DeleteOrganization deletes the organization +func (g *GoCloak) DeleteOrganization(ctx context.Context, token, realm, idOfOrganization string) error { + const errMessage = "could not delete organization" + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "organizations", idOfOrganization)) + + return checkForError(resp, err, errMessage) +} + +// GetOrganizationByID returns the organization representation of the organization with provided ID +func (g *GoCloak) GetOrganizationByID(ctx context.Context, token, realm, idOfOrganization string) (*OrganizationRepresentation, error) { + const errMessage = "could not find organization" + var result *OrganizationRepresentation + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(g.getAdminRealmURL(realm, "organizations", idOfOrganization)) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + +// UpdateOrganization updates the given organization +func (g *GoCloak) UpdateOrganization(ctx context.Context, token, realm string, organization OrganizationRepresentation) error { + const errMessage = "could not update organization" + + if NilOrEmpty(organization.ID) { + return errors.Wrap(errors.New("ID of an organization required"), errMessage) + } + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetBody(organization). + Put(g.getAdminRealmURL(realm, "organizations", PString(organization.ID))) + + return checkForError(resp, err, errMessage) +} + +// InviteUserToOrganizationByID invites an existing user to the organization, using the specified user id +// An invitation email will be sent to the user so SMTP settings are required in keycloak +func (g *GoCloak) InviteUserToOrganizationByID(ctx context.Context, token, realm, idOfOrganization, userID string) error { + const errMessage = "could not invite user to organization by id" + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetFormData(map[string]string{ + "id": userID, + }). + Post(g.getAdminRealmURL(realm, "organizations", idOfOrganization, "members", "invite-existing-user")) + + return checkForError(resp, err, errMessage) +} + +// InviteUserToOrganizationByEmail invites an existing user or sends a registration link to a new user, based on the provided e-mail address. +// If the user with the given e-mail address exists, it sends an invitation link, otherwise it sends a registration link. +// An invitation email will be sent to the user so SMTP settings are required in keycloak +func (g *GoCloak) InviteUserToOrganizationByEmail(ctx context.Context, token, realm, idOfOrganization string, userParams InviteeFormParams) error { + const errMessage = "could not invite user to organization by email" + + if NilOrEmpty(userParams.Email) { + return errors.Wrap(errors.New("Email of invitee required"), errMessage) + } + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetFormData(map[string]string{ + "email": *userParams.Email, + "firstName": *userParams.FirstName, + "lastName": *userParams.LastName, + }). + Post(g.getAdminRealmURL(realm, "organizations", idOfOrganization, "members", "invite-user")) + + return checkForError(resp, err, errMessage) +} + +// AddUserToOrganization adds the user with the specified id as a member of the organization +// Adds, or associates, an existing user with the organization. If no user is found, or if it is already associated with the organization, an error response is returned +// No invitation email is sent to the user +func (g *GoCloak) AddUserToOrganization(ctx context.Context, token, realm, idOfOrganization, idOfUser string) error { + const errMessage = "could not add user to organization" + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetBody(idOfUser). + Post(g.getAdminRealmURL(realm, "organizations", idOfOrganization, "members")) + + return checkForError(resp, err, errMessage) +} + +// RemoveUserFromOrganization removes the user with the specified id from the organization +func (g *GoCloak) RemoveUserFromOrganization(ctx context.Context, token, realm, idOfOrganization, idOfUser string) error { + const errMessage = "could not remove user from organization" + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "organizations", idOfOrganization, "members", idOfUser)) + + return checkForError(resp, err, errMessage) +} + +// GetOrganizationMemberCount returns number of members in the organization. +func (g *GoCloak) GetOrganizationMemberCount(ctx context.Context, token, realm, idOfOrganization string) (int, error) { + const errMessage = "could not get organization members count" + var result int + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(g.getAdminRealmURL(realm, "organizations", idOfOrganization, "members", "count")) + + if err := checkForError(resp, err, errMessage); err != nil { + return -1, errors.Wrap(err, errMessage) + } + + return result, err +} + +// GetOrganizationMemberByID returns the member of the organization with the specified id +// Searches for auser with the given id. If one is found, and is currently a member of the organization, returns it. +// Otherwise,an error response with status NOT_FOUND is returned +func (g *GoCloak) GetOrganizationMemberByID(ctx context.Context, token, realm, idOfOrganization, idOfUser string) (*MemberRepresentation, error) { + const errMessage = "could not get organization member by ID" + var result *MemberRepresentation + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(g.getAdminRealmURL(realm, "organizations", idOfOrganization, "members", idOfUser)) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, err +} + +// GetOrganizationMembers returns a paginated list of organization members filtered according to the specified parameters +func (g *GoCloak) GetOrganizationMembers(ctx context.Context, token, realm, idOfOrganization string, params GetMembersParams) ([]*MemberRepresentation, error) { + const errMessage = "could not get organization members" + + var result []*MemberRepresentation + queryParams, err := GetQueryParams(params) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + SetQueryParams(queryParams). + Get(g.getAdminRealmURL(realm, "organizations", idOfOrganization, "members")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, err +} + +// GetMemberAssociatedOrganizations returns the organizations associated with the user that has the specified id +func (g *GoCloak) GetMemberAssociatedOrganizations(ctx context.Context, token, realm, idOfUser string) ([]*OrganizationRepresentation, error) { + const errMessage = "could not get member's associated organizations" + var result []*OrganizationRepresentation + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(g.getAdminRealmURL(realm, "organizations", "members", idOfUser, "organizations")) + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, err +} diff --git a/client_test.go b/client_test.go index 9a39059a..f4df4e59 100644 --- a/client_test.go +++ b/client_test.go @@ -7112,3 +7112,420 @@ func Test_RevokeToken(t *testing.T) { ) require.NoError(t, err, "Revoke failed") } + +// ----------- +// Organizations +// ----------- + +func CreateOrganization(t *testing.T, client gocloak.GoCloakIface, name, alias, domain string) (func(), string) { + cfg := GetConfig(t) + token := GetAdminToken(t, client) + + org := gocloak.OrganizationRepresentation{ + Name: gocloak.StringP(name), + Alias: gocloak.StringP(alias), + Enable: gocloak.BoolP(true), + Description: gocloak.StringP("Just a test organization"), + Domains: &[]gocloak.OrganizationDomainRepresentation{ + { + Name: gocloak.StringP(domain), + Verified: gocloak.BoolP(true), + }, + }, + } + + orgID, err := client.CreateOrganization( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + org) + + require.NoError(t, err, "CreateOrganization failed") + + org.ID = &orgID + t.Logf("Created Organization: %+v", org) + tearDown := func() { + err := client.DeleteOrganization( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + orgID) + require.NoError(t, err, "DeleteOrganization") + } + + return tearDown, orgID +} + +func Test_CreateOrganization(t *testing.T) { + t.Parallel() + client := NewClientWithDebug(t) + + tearDown, _ := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown() +} + +func Test_GetOrganizations(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + // Create two organizations + tearDown1, _ := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown1() + + tearDown2, _ := CreateOrganization(t, client, "Another Inc", "another-inc", "another.com") + defer tearDown2() + + organizations, err := client.GetOrganizations( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloak.GetOrganizationsParams{}) + require.NoError(t, err, "GetOrganizations failed") + require.Equal(t, 2, len(organizations)) + t.Log(organizations) +} + +func Test_GetOrganizationsByName(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + tearDown, _ := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown() + + organization, err := client.GetOrganizations( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloak.GetOrganizationsParams{ + Search: gocloak.StringP("Test Inc"), + }) + require.NoError(t, err, "GetOrganizationByName failed") + t.Log(organization) +} + +func Test_GetOrganizationsByDomain(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + tearDown, _ := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown() + + organization, err := client.GetOrganizations( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloak.GetOrganizationsParams{ + Search: gocloak.StringP("test-inc.org"), + }) + require.NoError(t, err, "GetOrganizationByDomain failed") + t.Log(organization) +} + +func Test_GetOrganizationByID(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + tearDown, orgID := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown() + + organization, err := client.GetOrganizationByID( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + orgID) + require.NoError(t, err, "GetOrganization failed") + t.Log(organization) +} + +func Test_UpdateOrganization(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + tearDown, orgID := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown() + + organization, err := client.GetOrganizationByID( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + orgID) + require.NoError(t, err, "GetOrganizationByID failed") + + organization.Enable = gocloak.BoolP(false) + + err = client.UpdateOrganization( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + *organization) + require.NoError(t, err, "UpdateOrganization failed") + t.Log(organization) +} + +func Test_InviteUserToOrganizationByID(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + td, userID := CreateUser(t, client) + defer td() + + tearDown, orgID := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown() + + err := client.InviteUserToOrganizationByID( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + orgID, + userID) + require.NoError(t, err, "InviteUserToOrganizationByID failed") +} + +func Test_InviteUserToOrganizationByEmail(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + td, userID := CreateUser(t, client) + defer td() + + tearDown, orgID := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown() + + ctx := context.Background() + user, err := client.GetUserByID( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + userID) + require.NoError(t, err, "GetUserByID failed") + + err = client.InviteUserToOrganizationByEmail( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + orgID, + gocloak.InviteeFormParams{ + Email: user.Email, + FirstName: GetRandomNameP("FirstName"), + LastName: GetRandomNameP("LastName"), + }) + require.NoError(t, err, "InviteUserToOrganizationByEmail failed") +} + +func Test_AddUserToOrganization(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + td, userID := CreateUser(t, client) + defer td() + + tearDown, orgID := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown() + + err := client.AddUserToOrganization( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + orgID, + userID) + require.NoError(t, err, "AddUserToOrganization failed") +} + +func Test_RemoveUserFromOrganization(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + td, userID := CreateUser(t, client) + defer td() + + tearDown, orgID := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown() + + ctx := context.Background() + + err := client.AddUserToOrganization( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + orgID, + userID) + require.NoError(t, err, "AddUserToOrganization failed") + + err = client.RemoveUserFromOrganization( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + orgID, + userID) + require.NoError(t, err, "RemoveUserFromOrganization failed") +} + +func Test_GetOrganizationMemberCount(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + td, userID := CreateUser(t, client) + defer td() + + tearDown, orgID := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown() + + ctx := context.Background() + err := client.AddUserToOrganization( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + orgID, + userID) + require.NoError(t, err, "AddUserToOrganization failed") + + count, err := client.GetOrganizationMemberCount( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + orgID) + + t.Logf("Members in Organization: %d", count) + require.Equal(t, 1, count) + require.NoError(t, err, "GetOrganizationMemberCount failed") +} + +func Test_GetOrganizationMemberByID(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + td, userID := CreateUser(t, client) + defer td() + + tearDown, orgID := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown() + + ctx := context.Background() + err := client.AddUserToOrganization( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + orgID, + userID) + require.NoError(t, err, "AddUserToOrganization failed") + + member, err := client.GetOrganizationMemberByID( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + orgID, + userID) + + require.Equal(t, *member.ID, userID) + require.NoError(t, err, "GetOrganizationMemberByID failed") +} + +func Test_GetOrganizationMembers(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + td, userID := CreateUser(t, client) + defer td() + + td2, userID2 := CreateUser(t, client) + defer td2() + + tearDown, orgID := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown() + + ctx := context.Background() + err := client.AddUserToOrganization( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + orgID, + userID) + require.NoError(t, err, "AddUserToOrganization failed") + + err = client.AddUserToOrganization( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + orgID, + userID2) + require.NoError(t, err, "AddUserToOrganization failed") + + members, err := client.GetOrganizationMembers( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + orgID, + gocloak.GetMembersParams{}) + require.NoError(t, err, "GetOrganizationMembers failed") + + fmt.Println(members) + require.GreaterOrEqual(t, len(members), 1) +} + +func Test_GetMemberAssociatedOrganizations(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + td, userID := CreateUser(t, client) + defer td() + + // Create two organizations + tearDown1, orgID1 := CreateOrganization(t, client, "Test Inc", "test-inc", "test.com") + defer tearDown1() + + tearDown2, orgID2 := CreateOrganization(t, client, "Another Inc", "another-inc", "another.com") + defer tearDown2() + + // Add user to both organizations + ctx := context.Background() + err := client.AddUserToOrganization( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + orgID1, + userID) + require.NoError(t, err, "AddUserToOrganization failed") + + err = client.AddUserToOrganization( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + orgID2, + userID) + require.NoError(t, err, "AddUserToOrganization failed") + + organizations, err := client.GetMemberAssociatedOrganizations( + ctx, + token.AccessToken, + cfg.GoCloak.Realm, + userID) + require.NoError(t, err, "GetMemberAssociatedOrganizations failed") + + require.GreaterOrEqual(t, len(organizations), 1) +} diff --git a/docker-compose.yml b/docker-compose.yml index c467aad6..35f80da6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,4 +19,10 @@ services: retries: 5 volumes: - ./testdata/gocloak-realm.json:/opt/keycloak/data/import/gocloak-realm.json - entrypoint: ["/opt/keycloak/bin/kc.sh", "start-dev", "--features=preview", "--import-realm"] + entrypoint: + [ + "/opt/keycloak/bin/kc.sh", + "start-dev", + "--features=preview", + "--import-realm", + ] diff --git a/gocloak_iface.go b/gocloak_iface.go index 32dbf9b3..f625d7bd 100644 --- a/gocloak_iface.go +++ b/gocloak_iface.go @@ -578,4 +578,37 @@ type GoCloakIface interface { UpdateUsersManagementPermissions(ctx context.Context, accessToken, realm string, managementPermissions ManagementPermissionRepresentation) (*ManagementPermissionRepresentation, error) // GetUsersManagementPermissions returns the management permissions for users GetUsersManagementPermissions(ctx context.Context, accessToken, realm string) (*ManagementPermissionRepresentation, error) + // CreateOrganization creates a new Organization + CreateOrganization(ctx context.Context, token, realm string, organization OrganizationRepresentation) (string, error) + // GetOrganizations returns a paginated list of organizations filtered according to the specified parameters + GetOrganizations(ctx context.Context, token, realm string, params GetOrganizationsParams) ([]*OrganizationRepresentation, error) + // DeleteOrganization deletes the organization + DeleteOrganization(ctx context.Context, token, realm, idOfOrganization string) error + // GetOrganizationByID returns the organization representation of the organization with provided ID + GetOrganizationByID(ctx context.Context, token, realm, idOfOrganization string) (*OrganizationRepresentation, error) + // UpdateOrganization updates the given organization + UpdateOrganization(ctx context.Context, token, realm string, organization OrganizationRepresentation) error + // InviteUserToOrganizationByID invites an existing user to the organization, using the specified user id + // An invitation email will be sent to the user so SMTP settings are required in keycloak + InviteUserToOrganizationByID(ctx context.Context, token, realm, idOfOrganization, userID string) error + // InviteUserToOrganizationByEmail invites an existing user or sends a registration link to a new user, based on the provided e-mail address. + // If the user with the given e-mail address exists, it sends an invitation link, otherwise it sends a registration link. + // An invitation email will be sent to the user so SMTP settings are required in keycloak + InviteUserToOrganizationByEmail(ctx context.Context, token, realm, idOfOrganization string, userParams InviteeFormParams) error + // AddUserToOrganization adds the user with the specified id as a member of the organization + // Adds, or associates, an existing user with the organization. If no user is found, or if it is already associated with the organization, an error response is returned + // No invitation email is sent to the user + AddUserToOrganization(ctx context.Context, token, realm, idOfOrganization, idOfUser string) error + // RemoveUserFromOrganization removes the user with the specified id from the organization + RemoveUserFromOrganization(ctx context.Context, token, realm, idOfOrganization, idOfUser string) error + // GetOrganizationMemberCount returns number of members in the organization. + GetOrganizationMemberCount(ctx context.Context, token, realm, idOfOrganization string) (int, error) + // GetOrganizationMemberByID returns the member of the organization with the specified id + // Searches for auser with the given id. If one is found, and is currently a member of the organization, returns it. + // Otherwise,an error response with status NOT_FOUND is returned + GetOrganizationMemberByID(ctx context.Context, token, realm, idOfOrganization, idOfUser string) (*MemberRepresentation, error) + // GetOrganizationMembers returns a paginated list of organization members filtered according to the specified parameters + GetOrganizationMembers(ctx context.Context, token, realm, idOfOrganization string, params GetMembersParams) ([]*MemberRepresentation, error) + // GetMemberAssociatedOrganizations returns the organizations associated with the user that has the specified id + GetMemberAssociatedOrganizations(ctx context.Context, token, realm, idOfUser string) ([]*OrganizationRepresentation, error) } diff --git a/model_test.go b/model_test.go index 1a5affcc..e0a988ff 100644 --- a/model_test.go +++ b/model_test.go @@ -336,6 +336,9 @@ func TestStringerOmitEmpty(t *testing.T) { &gocloak.RequestingPartyTokenOptions{}, &gocloak.RequestingPartyPermission{}, &gocloak.GetClientUserSessionsParams{}, + &gocloak.GetOrganizationsParams{}, + &gocloak.OrganizationDomainRepresentation{}, + &gocloak.OrganizationRepresentation{}, } for _, custom := range customs { diff --git a/models.go b/models.go index 4d526aeb..8e438d7d 100644 --- a/models.go +++ b/models.go @@ -796,6 +796,8 @@ type RealmRepresentation struct { OfflineSessionIdleTimeout *int `json:"offlineSessionIdleTimeout,omitempty"` OfflineSessionMaxLifespan *int `json:"offlineSessionMaxLifespan,omitempty"` OfflineSessionMaxLifespanEnabled *bool `json:"offlineSessionMaxLifespanEnabled,omitempty"` + OrganizationsEnabled bool `json:"organizationsEnabled,omitempty"` + Organizations *[]interface{} `json:"organizations,omitempty"` OtpPolicyAlgorithm *string `json:"otpPolicyAlgorithm,omitempty"` OtpPolicyDigits *int `json:"otpPolicyDigits,omitempty"` OtpPolicyInitialCounter *int `json:"otpPolicyInitialCounter,omitempty"` @@ -1445,6 +1447,66 @@ type GetClientUserSessionsParams struct { Max *int `json:"max,string,omitempty"` } +// InviteeFormParams represents the form parameters used to invite a user to an organization +type InviteeFormParams struct { + Email *string `json:"email,omitempty"` + FirstName *string `json:"firstname,omitempty"` + LastName *string `json:"lastname,omitempty"` +} + +// GetMembersParams represents the optional parameters for getting members of an organization +type GetMembersParams struct { + Exact *bool `json:"exact,string,omitempty"` + First *int `json:"first,string,omitempty"` + Max *int `json:"max,string,omitempty"` + MembershipType *MembershipType `json:"membershipetype,omitempty"` + Search *string `json:"search,omitempty"` +} + +// MembershipType represent the membership type of an organization member. +// v26: https://www.keycloak.org/docs-api/latest/rest-api/index.html#MembershipType +type MembershipType struct{} + +// MemberRepresentation represents a member of an organization +// v26: https://www.keycloak.org/docs-api/latest/rest-api/index.html#MemberRepresentation +type MemberRepresentation struct { + User + // Type not defined in the Keycloak doc so I left it unexported. Help if you have more information + MembershipType *MembershipType `json:"membershipetype,omitempty"` +} + +// GetOrganizationsParams represents the optional parameters for getting organizations +type GetOrganizationsParams struct { + BriefRepresentation *bool `json:"briefRepresentation,string,omitempty"` + Exact *bool `json:"exact,string,omitempty"` + First *int `json:"first,string,omitempty"` + Max *int `json:"max,string,omitempty"` + Q *string `json:"q,omitempty"` + Search *string `json:"search,omitempty"` +} + +// OrganizationDomainRepresentation is a representation of an organization's domain +// v26: https://www.keycloak.org/docs-api/latest/rest-api/index.html#OrganizationOrganizationDomainRepresentation +type OrganizationDomainRepresentation struct { + Name *string `json:"name,omitempty"` + Verified *bool `json:"verified,omitempty"` +} + +// OrganizationRepresentation is a representation of an organization +// v26: https://www.keycloak.org/docs-api/latest/rest-api/index.html#OrganizationRepresentation +type OrganizationRepresentation struct { + ID *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Alias *string `json:"alias,omitempty"` + Enable *bool `json:"enabled,omitempty"` + Description *string `json:"description,omitempty"` + RedirectURL *string `json:"redirectUrl,omitempty"` + Attributes *map[string][]string `json:"attributes,omitempty"` + Domains *[]OrganizationDomainRepresentation `json:"domains,omitempty"` + Members *[]string `json:"members,omitempty"` + IdentityProviders *[]string `json:"identityProviders,omitempty"` +} + // prettyStringStruct returns struct formatted into pretty string func prettyStringStruct(t interface{}) string { json, err := json.MarshalIndent(t, "", "\t") @@ -1539,3 +1601,10 @@ func (v *CredentialRepresentation) String() string { return pre func (v *RequiredActionProviderRepresentation) String() string { return prettyStringStruct(v) } func (v *BruteForceStatus) String() string { return prettyStringStruct(v) } func (v *GetClientUserSessionsParams) String() string { return prettyStringStruct(v) } +func (v *GetOrganizationsParams) String() string { return prettyStringStruct(v) } +func (v *InviteeFormParams) String() string { return prettyStringStruct(v) } +func (v *GetMembersParams) String() string { return prettyStringStruct(v) } +func (v *MembershipType) String() string { return prettyStringStruct(v) } +func (v *MemberRepresentation) String() string { return prettyStringStruct(v) } +func (v *OrganizationDomainRepresentation) String() string { return prettyStringStruct(v) } +func (v *OrganizationRepresentation) String() string { return prettyStringStruct(v) }