diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/organization/InfinispanOrganizationProvider.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/organization/InfinispanOrganizationProvider.java index 343b0216cb..f3234a225a 100644 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/organization/InfinispanOrganizationProvider.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/organization/InfinispanOrganizationProvider.java @@ -57,9 +57,9 @@ public class InfinispanOrganizationProvider implements OrganizationProvider { } @Override - public OrganizationModel create(String name, String alias) { + public OrganizationModel create(String id, String name, String alias) { registerCountInvalidation(); - return orgDelegate.create(name, alias); + return orgDelegate.create(id, name, alias); } @Override diff --git a/model/jpa/src/main/java/org/keycloak/organization/jpa/JpaOrganizationProvider.java b/model/jpa/src/main/java/org/keycloak/organization/jpa/JpaOrganizationProvider.java index 5d45109e3d..926f6c7b9c 100644 --- a/model/jpa/src/main/java/org/keycloak/organization/jpa/JpaOrganizationProvider.java +++ b/model/jpa/src/main/java/org/keycloak/organization/jpa/JpaOrganizationProvider.java @@ -55,6 +55,7 @@ import org.keycloak.models.jpa.entities.GroupEntity; import org.keycloak.models.jpa.entities.OrganizationEntity; import org.keycloak.models.jpa.entities.UserEntity; import org.keycloak.models.jpa.entities.UserGroupMembershipEntity; +import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.organization.OrganizationProvider; import org.keycloak.representations.idm.MembershipType; import org.keycloak.organization.utils.Organizations; @@ -76,7 +77,7 @@ public class JpaOrganizationProvider implements OrganizationProvider { } @Override - public OrganizationModel create(String name, String alias) { + public OrganizationModel create(String id, String name, String alias) { if (StringUtil.isBlank(name)) { throw new ModelValidationException("Name can not be null"); } @@ -98,8 +99,10 @@ public class JpaOrganizationProvider implements OrganizationProvider { throw new ModelDuplicateException("A organization with the same alias already exists"); } - RealmModel realm = getRealm(); - OrganizationAdapter adapter = new OrganizationAdapter(session, realm, this); + OrganizationEntity entity = new OrganizationEntity(); + entity.setId(id != null ? id : KeycloakModelUtils.generateId()); + entity.setRealmId(getRealm().getId()); + OrganizationAdapter adapter = new OrganizationAdapter(session, getRealm(), entity, this); try { session.getContext().setOrganization(adapter); diff --git a/model/jpa/src/main/java/org/keycloak/organization/jpa/OrganizationAdapter.java b/model/jpa/src/main/java/org/keycloak/organization/jpa/OrganizationAdapter.java index 878b239f90..10168b0b95 100644 --- a/model/jpa/src/main/java/org/keycloak/organization/jpa/OrganizationAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/organization/jpa/OrganizationAdapter.java @@ -53,15 +53,6 @@ public final class OrganizationAdapter implements OrganizationModel, JpaModel> attributes; - public OrganizationAdapter(KeycloakSession session, RealmModel realm, OrganizationProvider provider) { - this.session = session; - entity = new OrganizationEntity(); - entity.setId(KeycloakModelUtils.generateId()); - entity.setRealmId(realm.getId()); - this.realm = realm; - this.provider = provider; - } - public OrganizationAdapter(KeycloakSession session, RealmModel realm, OrganizationEntity entity, OrganizationProvider provider) { this.session = session; this.realm = realm; diff --git a/model/storage-private/src/main/java/org/keycloak/exportimport/util/ExportUtils.java b/model/storage-private/src/main/java/org/keycloak/exportimport/util/ExportUtils.java index df8af409f6..07a6649d9e 100755 --- a/model/storage-private/src/main/java/org/keycloak/exportimport/util/ExportUtils.java +++ b/model/storage-private/src/main/java/org/keycloak/exportimport/util/ExportUtils.java @@ -130,7 +130,7 @@ public class ExportUtils { List currentAppRoleReps = exportRoles(currentAppRoles); clientRolesReps.put(client.getClientId(), currentAppRoleReps); } - if (clientRolesReps.size() > 0) { + if (!clientRolesReps.isEmpty()) { rolesRep.setClient(clientRolesReps); } } @@ -156,11 +156,7 @@ public class ExportUtils { } else { ClientModel app = (ClientModel) scope.getContainer(); String appName = app.getClientId(); - List currentAppScopes = clientScopeReps.get(appName); - if (currentAppScopes == null) { - currentAppScopes = new ArrayList<>(); - clientScopeReps.put(appName, currentAppScopes); - } + List currentAppScopes = clientScopeReps.computeIfAbsent(appName, k -> new ArrayList<>()); ScopeMappingRepresentation currentClientScope = null; for (ScopeMappingRepresentation scopeMapping : currentAppScopes) { @@ -193,11 +189,7 @@ public class ExportUtils { } else { ClientModel app = (ClientModel)scope.getContainer(); String appName = app.getClientId(); - List currentAppScopes = clientScopeReps.get(appName); - if (currentAppScopes == null) { - currentAppScopes = new ArrayList<>(); - clientScopeReps.put(appName, currentAppScopes); - } + List currentAppScopes = clientScopeReps.computeIfAbsent(appName, k -> new ArrayList<>()); ScopeMappingRepresentation currentClientTemplateScope = null; for (ScopeMappingRepresentation scopeMapping : currentAppScopes) { @@ -216,7 +208,7 @@ public class ExportUtils { } }); - if (clientScopeReps.size() > 0) { + if (!clientScopeReps.isEmpty()) { rep.setClientScopeMappings(clientScopeReps); } @@ -226,7 +218,7 @@ public class ExportUtils { .map(user -> exportUser(session, realm, user, options, internal)) .collect(Collectors.toList()); - if (users.size() > 0) { + if (!users.isEmpty()) { rep.setUsers(users); } @@ -234,7 +226,7 @@ public class ExportUtils { if (userFederatedStorageProvider != null) { List federatedUsers = userFederatedStorage(session).getStoredUsersStream(realm, 0, -1) .map(user -> exportFederatedUser(session, realm, user, options)).collect(Collectors.toList()); - if (federatedUsers.size() > 0) { + if (!federatedUsers.isEmpty()) { rep.setFederatedUsers(federatedUsers); } } @@ -251,7 +243,7 @@ public class ExportUtils { } } - if (users.size() > 0) { + if (!users.isEmpty()) { rep.setUsers(users); } } @@ -265,32 +257,19 @@ public class ExportUtils { if (Profile.isFeatureEnabled(Feature.ORGANIZATION) && !options.isPartial()) { OrganizationProvider orgProvider = session.getProvider(OrganizationProvider.class); - orgProvider.getAllStream().map(m -> { - OrganizationRepresentation org = new OrganizationRepresentation(); + orgProvider.getAllStream().map(model -> { + OrganizationRepresentation org = ModelToRepresentation.toRepresentation(model); - org.setName(m.getName()); - org.setAlias(m.getAlias()); - org.setEnabled(m.isEnabled()); - org.setDescription(m.getDescription()); - m.getDomains().map(d -> { - OrganizationDomainRepresentation domain = new OrganizationDomainRepresentation(); - - domain.setName(d.getName()); - domain.setVerified(d.isVerified()); - - return domain; - }).forEach(org::addDomain); - - orgProvider.getMembersStream(m, null, null, null, null) + orgProvider.getMembersStream(model, null, null, null, null) .forEach(user -> { MemberRepresentation member = new MemberRepresentation(); member.setUsername(user.getUsername()); - member.setMembershipType(orgProvider.isManagedMember(m, user) ? MembershipType.MANAGED : MembershipType.UNMANAGED); + member.setMembershipType(orgProvider.isManagedMember(model, user) ? MembershipType.MANAGED : MembershipType.UNMANAGED); org.addMember(member); }); - orgProvider.getIdentityProviders(m) + orgProvider.getIdentityProviders(model) .map(b -> { IdentityProviderRepresentation broker = new IdentityProviderRepresentation(); broker.setAlias(b.getAlias()); diff --git a/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java b/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java index 3ce750759c..01ab451dcb 100644 --- a/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java +++ b/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java @@ -48,7 +48,6 @@ import org.keycloak.models.LDAPConstants; import org.keycloak.models.ModelException; import org.keycloak.models.OAuth2DeviceConfig; import org.keycloak.models.OTPPolicy; -import org.keycloak.models.OrganizationDomainModel; import org.keycloak.models.OrganizationModel; import org.keycloak.models.ParConfig; import org.keycloak.models.PasswordPolicy; @@ -1590,21 +1589,20 @@ public class DefaultExportImportManager implements ExportImportManager { OrganizationProvider provider = session.getProvider(OrganizationProvider.class); for (OrganizationRepresentation orgRep : Optional.ofNullable(rep.getOrganizations()).orElse(Collections.emptyList())) { - OrganizationModel org = provider.create(orgRep.getName(), orgRep.getAlias()); - - org.setDomains(orgRep.getDomains().stream().map(r -> new OrganizationDomainModel(r.getName(), r.isVerified())).collect(Collectors.toSet())); + OrganizationModel orgModel = provider.create(orgRep.getId(), orgRep.getName(), orgRep.getAlias()); + RepresentationToModel.toModel(orgRep, orgModel); for (IdentityProviderRepresentation identityProvider : Optional.ofNullable(orgRep.getIdentityProviders()).orElse(Collections.emptyList())) { IdentityProviderModel idp = session.identityProviders().getByAlias(identityProvider.getAlias()); - provider.addIdentityProvider(org, idp); + provider.addIdentityProvider(orgModel, idp); } for (MemberRepresentation member : Optional.ofNullable(orgRep.getMembers()).orElse(Collections.emptyList())) { UserModel m = session.users().getUserByUsername(newRealm, member.getUsername()); if (MembershipType.MANAGED.equals(member.getMembershipType())) { - provider.addManagedMember(org, m); + provider.addManagedMember(orgModel, m); } else { - provider.addMember(org, m); + provider.addMember(orgModel, m); } } } diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index 9a0497256f..a9f5a994f7 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -1291,4 +1291,35 @@ public class ModelToRepresentation { rep.setConfig(model.getConfig()); return rep; } + + public static OrganizationRepresentation toRepresentation(OrganizationModel model) { + OrganizationRepresentation rep = toBriefRepresentation(model); + if (rep == null) { + return null; + } + rep.setAttributes(model.getAttributes()); + return rep; + } + + public static OrganizationRepresentation toBriefRepresentation(OrganizationModel model) { + if (model == null) { + return null; + } + OrganizationRepresentation rep = new OrganizationRepresentation(); + rep.setId(model.getId()); + rep.setName(model.getName()); + rep.setAlias(model.getAlias()); + rep.setEnabled(model.isEnabled()); + rep.setDescription(model.getDescription()); + model.getDomains().filter(Objects::nonNull).map(ModelToRepresentation::toRepresentation) + .forEach(rep::addDomain); + return rep; + } + + public static OrganizationDomainRepresentation toRepresentation(OrganizationDomainModel model) { + OrganizationDomainRepresentation representation = new OrganizationDomainRepresentation(); + representation.setName(model.getName()); + representation.setVerified(model.isVerified()); + return representation; + } } diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java index 70b51d5d4c..047c7e1bef 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java @@ -108,6 +108,8 @@ import org.keycloak.representations.idm.FederatedIdentityRepresentation; import org.keycloak.representations.idm.GroupRepresentation; import org.keycloak.representations.idm.IdentityProviderMapperRepresentation; import org.keycloak.representations.idm.IdentityProviderRepresentation; +import org.keycloak.representations.idm.OrganizationDomainRepresentation; +import org.keycloak.representations.idm.OrganizationRepresentation; import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RoleRepresentation; @@ -127,6 +129,7 @@ import org.keycloak.storage.DatastoreProvider; import org.keycloak.util.JsonSerialization; import org.keycloak.utils.StringUtil; +import static java.util.Optional.ofNullable; import static org.keycloak.protocol.saml.util.ArtifactBindingUtils.computeArtifactBindingIdentifierString; public class RepresentationToModel { @@ -1674,4 +1677,27 @@ public class RepresentationToModel { representation.setOrganizationId(orgId); } } + + public static OrganizationModel toModel(OrganizationRepresentation rep, OrganizationModel model) { + if (rep == null) { + return null; + } + + model.setName(rep.getName()); + model.setAlias(rep.getAlias()); + model.setEnabled(rep.isEnabled()); + model.setDescription(rep.getDescription()); + model.setAttributes(rep.getAttributes()); + model.setDomains(ofNullable(rep.getDomains()).orElse(Set.of()).stream() + .filter(Objects::nonNull) + .filter(domain -> StringUtil.isNotBlank(domain.getName())) + .map(RepresentationToModel::toModel) + .collect(Collectors.toSet())); + + return model; + } + + public static OrganizationDomainModel toModel(OrganizationDomainRepresentation domainRepresentation) { + return new OrganizationDomainModel(domainRepresentation.getName(), domainRepresentation.isVerified()); + } } diff --git a/server-spi/src/main/java/org/keycloak/organization/OrganizationProvider.java b/server-spi/src/main/java/org/keycloak/organization/OrganizationProvider.java index 9eb98075ec..3f689d61eb 100644 --- a/server-spi/src/main/java/org/keycloak/organization/OrganizationProvider.java +++ b/server-spi/src/main/java/org/keycloak/organization/OrganizationProvider.java @@ -31,14 +31,26 @@ import org.keycloak.provider.Provider; public interface OrganizationProvider extends Provider { /** - * Creates a new organization with given {@code name} to the realm. + * Creates a new organization with given {@code name} and {@code alias} to the realm. * The internal ID of the organization will be created automatically. - * @param name String name of the organization. + * @param name the name of the organization. * @param alias the alias of the organization. If not set, defaults to the value set to {@code name}. Once set, the alias is immutable. * @throws ModelDuplicateException If there is already an organization with the given name or alias * @return Model of the created organization. */ - OrganizationModel create(String name, String alias); + default OrganizationModel create(String name, String alias) { + return create(null, name, alias); + } + + /** + * Creates a new organization with given {@code id}, {@code name}, and {@code alias} to the realm + * @param id the id of the organization. + * @param name the name of the organization. + * @param alias the alias of the organization. If not set, defaults to the value set to {@code name}. Once set, the alias is immutable. + * @throws ModelDuplicateException If there is already an organization with the given name or alias + * @return Model of the created organization. + */ + OrganizationModel create(String id, String name, String alias); /** * Returns a {@link OrganizationModel} by its {@code id}; diff --git a/services/src/main/java/org/keycloak/organization/admin/resource/OrganizationMemberResource.java b/services/src/main/java/org/keycloak/organization/admin/resource/OrganizationMemberResource.java index c0bc07f409..7b01dec09c 100644 --- a/services/src/main/java/org/keycloak/organization/admin/resource/OrganizationMemberResource.java +++ b/services/src/main/java/org/keycloak/organization/admin/resource/OrganizationMemberResource.java @@ -17,7 +17,6 @@ package org.keycloak.organization.admin.resource; -import java.util.List; import java.util.stream.Stream; import jakarta.ws.rs.Consumes; @@ -49,11 +48,9 @@ import org.keycloak.models.UserModel; import org.keycloak.models.utils.ModelToRepresentation; import org.keycloak.organization.OrganizationProvider; -import org.keycloak.organization.utils.Organizations; import org.keycloak.representations.idm.MemberRepresentation; import org.keycloak.representations.idm.MembershipType; import org.keycloak.representations.idm.OrganizationRepresentation; -import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.services.ErrorResponse; import org.keycloak.services.resources.KeycloakOpenAPI; import org.keycloak.services.resources.admin.AdminEventBuilder; @@ -193,7 +190,7 @@ public class OrganizationMemberResource { UserModel member = getUser(id); - return provider.getByMember(member).map(Organizations::toRepresentation); + return provider.getByMember(member).map(ModelToRepresentation::toRepresentation); } @Path("count") diff --git a/services/src/main/java/org/keycloak/organization/admin/resource/OrganizationResource.java b/services/src/main/java/org/keycloak/organization/admin/resource/OrganizationResource.java index 6b77ebc00f..7bb3f4c660 100644 --- a/services/src/main/java/org/keycloak/organization/admin/resource/OrganizationResource.java +++ b/services/src/main/java/org/keycloak/organization/admin/resource/OrganizationResource.java @@ -33,8 +33,9 @@ import org.jboss.resteasy.reactive.NoCache; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelValidationException; import org.keycloak.models.OrganizationModel; +import org.keycloak.models.utils.ModelToRepresentation; +import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.organization.OrganizationProvider; -import org.keycloak.organization.utils.Organizations; import org.keycloak.representations.idm.OrganizationRepresentation; import org.keycloak.services.ErrorResponse; import org.keycloak.services.resources.KeycloakOpenAPI; @@ -67,7 +68,7 @@ public class OrganizationResource { @Tag(name = KeycloakOpenAPI.Admin.Tags.ORGANIZATIONS) @Operation(summary = "Returns the organization representation") public OrganizationRepresentation get() { - return Organizations.toRepresentation(organization); + return ModelToRepresentation.toRepresentation(organization); } @DELETE @@ -84,7 +85,7 @@ public class OrganizationResource { @Operation(summary = "Updates the organization") public Response update(OrganizationRepresentation organizationRep) { try { - Organizations.toModel(organizationRep, organization); + RepresentationToModel.toModel(organizationRep, organization); return Response.noContent().build(); } catch (ModelValidationException mve) { throw ErrorResponse.error(mve.getMessage(), Response.Status.BAD_REQUEST); diff --git a/services/src/main/java/org/keycloak/organization/admin/resource/OrganizationsResource.java b/services/src/main/java/org/keycloak/organization/admin/resource/OrganizationsResource.java index c2b15ebed4..45a5e350e5 100644 --- a/services/src/main/java/org/keycloak/organization/admin/resource/OrganizationsResource.java +++ b/services/src/main/java/org/keycloak/organization/admin/resource/OrganizationsResource.java @@ -42,6 +42,8 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.ModelValidationException; import org.keycloak.models.OrganizationModel; +import org.keycloak.models.utils.ModelToRepresentation; +import org.keycloak.models.utils.RepresentationToModel; import org.keycloak.organization.OrganizationProvider; import org.keycloak.organization.utils.Organizations; import org.keycloak.representations.idm.OrganizationRepresentation; @@ -96,9 +98,7 @@ public class OrganizationsResource { try { OrganizationModel model = provider.create(organization.getName(), organization.getAlias()); - - Organizations.toModel(organization, model); - + RepresentationToModel.toModel(organization, model); return Response.created(session.getContext().getUri().getAbsolutePathBuilder().path(model.getId()).build()).build(); } catch (ModelValidationException mve) { throw ErrorResponse.error(mve.getMessage(), Response.Status.BAD_REQUEST); @@ -137,9 +137,9 @@ public class OrganizationsResource { // check if are searching orgs by attribute. if (StringUtil.isNotBlank(searchQuery)) { Map attributes = SearchQueryUtils.getFields(searchQuery); - return provider.getAllStream(attributes, first, max).map(Organizations::toBriefRepresentation); + return provider.getAllStream(attributes, first, max).map(ModelToRepresentation::toBriefRepresentation); } else { - return provider.getAllStream(search, exact, first, max).map(Organizations::toBriefRepresentation); + return provider.getAllStream(search, exact, first, max).map(ModelToRepresentation::toBriefRepresentation); } } diff --git a/services/src/main/java/org/keycloak/organization/utils/Organizations.java b/services/src/main/java/org/keycloak/organization/utils/Organizations.java index 78a723a242..1ae046142a 100644 --- a/services/src/main/java/org/keycloak/organization/utils/Organizations.java +++ b/services/src/main/java/org/keycloak/organization/utils/Organizations.java @@ -151,66 +151,6 @@ public class Organizations { } } - public static OrganizationRepresentation toRepresentation(OrganizationModel model) { - OrganizationRepresentation rep = toBriefRepresentation(model); - - if (rep == null) { - return null; - } - - rep.setAttributes(model.getAttributes()); - - return rep; - } - - public static OrganizationRepresentation toBriefRepresentation(OrganizationModel model) { - if (model == null) { - return null; - } - - OrganizationRepresentation rep = new OrganizationRepresentation(); - - rep.setId(model.getId()); - rep.setName(model.getName()); - rep.setAlias(model.getAlias()); - rep.setEnabled(model.isEnabled()); - rep.setDescription(model.getDescription()); - model.getDomains().filter(Objects::nonNull).map(Organizations::toRepresentation) - .forEach(rep::addDomain); - - return rep; - } - - public static OrganizationDomainRepresentation toRepresentation(OrganizationDomainModel model) { - OrganizationDomainRepresentation representation = new OrganizationDomainRepresentation(); - representation.setName(model.getName()); - representation.setVerified(model.isVerified()); - return representation; - } - - public static OrganizationModel toModel(OrganizationRepresentation rep, OrganizationModel model) { - if (rep == null) { - return null; - } - - model.setName(rep.getName()); - model.setAlias(rep.getAlias()); - model.setEnabled(rep.isEnabled()); - model.setDescription(rep.getDescription()); - model.setAttributes(rep.getAttributes()); - model.setDomains(ofNullable(rep.getDomains()).orElse(Set.of()).stream() - .filter(Objects::nonNull) - .filter(domain -> StringUtil.isNotBlank(domain.getName())) - .map(Organizations::toModel) - .collect(Collectors.toSet())); - - return model; - } - - public static OrganizationDomainModel toModel(OrganizationDomainRepresentation domainRepresentation) { - return new OrganizationDomainModel(domainRepresentation.getName(), domainRepresentation.isVerified()); - } - public static InviteOrgActionToken parseInvitationToken(HttpRequest request) throws VerificationException { MultivaluedMap queryParameters = request.getUri().getQueryParameters(); String tokenFromQuery = queryParameters.getFirst(Constants.TOKEN); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/AbstractOrganizationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/AbstractOrganizationTest.java index 90bf1728c1..3c23f69927 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/AbstractOrganizationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/AbstractOrganizationTest.java @@ -152,6 +152,7 @@ public abstract class AbstractOrganizationTest extends AbstractAdminTest { OrganizationRepresentation org = new OrganizationRepresentation(); org.setName(name); org.setAlias(name); + org.setDescription(name + " is a test organization!"); for (String orgDomain : orgDomains) { OrganizationDomainRepresentation domainRep = new OrganizationDomainRepresentation(); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/exportimport/OrganizationExportTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/exportimport/OrganizationExportTest.java index eb03751790..2d2e63ba24 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/exportimport/OrganizationExportTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/exportimport/OrganizationExportTest.java @@ -17,8 +17,12 @@ package org.keycloak.testsuite.organization.exportimport; +import static org.hamcrest.CoreMatchers.hasItem; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasSize; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -42,6 +46,7 @@ import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory; import org.keycloak.exportimport.singlefile.SingleFileImportProviderFactory; import org.keycloak.models.OrganizationModel; import org.keycloak.models.utils.DefaultAuthenticationFlows; +import org.keycloak.organization.OrganizationProvider; import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation; import org.keycloak.representations.idm.IdentityProviderRepresentation; import org.keycloak.representations.idm.OrganizationRepresentation; @@ -58,7 +63,7 @@ public class OrganizationExportTest extends AbstractOrganizationTest { @Test public void testExport() { RealmResource providerRealm = realmsResouce().realm(bc.providerRealmName()); - List expectedOrganizations = new ArrayList<>(); + List expectedOrganizations = new ArrayList<>(); Map> expectedManagedMembers = new HashMap<>(); Map> expectedUnmanagedMembers = new HashMap<>(); @@ -70,7 +75,7 @@ public class OrganizationExportTest extends AbstractOrganizationTest { OrganizationRepresentation orgRep = createOrganization(testRealm(), getCleanup(), "org-" + i, broker, domain); OrganizationResource organization = testRealm().organizations().get(orgRep.getId()); - expectedOrganizations.add(orgRep.getName()); + expectedOrganizations.add(orgRep); for (int j = 0; j < 3; j++) { UserRepresentation member = addMember(organization, "realmuser-" + j + "@" + domain); @@ -109,8 +114,27 @@ public class OrganizationExportTest extends AbstractOrganizationTest { List organizations = testRealm().organizations().getAll(); assertEquals(expectedOrganizations.size(), organizations.size()); - assertThat(organizations.stream().map(OrganizationRepresentation::getName).toList(), Matchers.containsInAnyOrder(expectedOrganizations.toArray())); - assertThat(organizations.stream().map(OrganizationRepresentation::getAlias).toList(), Matchers.containsInAnyOrder(expectedOrganizations.toArray())); + // id, name, alias, and description should have all been preserved. + assertThat(organizations.stream().map(OrganizationRepresentation::getId).toList(), + Matchers.containsInAnyOrder(expectedOrganizations.stream().map(OrganizationRepresentation::getId).toArray())); + assertThat(organizations.stream().map(OrganizationRepresentation::getName).toList(), + Matchers.containsInAnyOrder(expectedOrganizations.stream().map(OrganizationRepresentation::getName).toArray())); + assertThat(organizations.stream().map(OrganizationRepresentation::getAlias).toList(), + Matchers.containsInAnyOrder(expectedOrganizations.stream().map(OrganizationRepresentation::getAlias).toArray())); + assertThat(organizations.stream().map(OrganizationRepresentation::getDescription).toList(), + Matchers.containsInAnyOrder(expectedOrganizations.stream().map(OrganizationRepresentation::getDescription).toArray())); + + // the endpoint search method returns brief representations of orgs - to get full rep we need to fetch by id. + for (OrganizationRepresentation organization : organizations) { + OrganizationRepresentation fullRep = testRealm().organizations().get(organization.getId()).toRepresentation(); + // attributes should have been imported. + assertThat(fullRep.getAttributes(), notNullValue()); + assertThat(fullRep.getAttributes().keySet(), hasSize(1)); + assertThat(fullRep.getAttributes().keySet(), hasItem("key")); + List attrValues = fullRep.getAttributes().get("key"); + assertThat(attrValues, notNullValue()); + assertThat(attrValues, containsInAnyOrder("value1", "value2")); + } for (OrganizationRepresentation orgRep : organizations) { OrganizationResource organization = testRealm().organizations().get(orgRep.getId());