-
Notifications
You must be signed in to change notification settings - Fork 827
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ScimUserAliasHandlerEnsureConsistencyTest
- Loading branch information
1 parent
463202f
commit 9ed1580
Showing
1 changed file
with
247 additions
and
0 deletions.
There are no files selected for viewing
247 changes: 247 additions & 0 deletions
247
...st/java/org/cloudfoundry/identity/uaa/scim/ScimUserAliasHandlerEnsureConsistencyTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,247 @@ | ||
package org.cloudfoundry.identity.uaa.scim; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.cloudfoundry.identity.uaa.constants.OriginKeys.UAA; | ||
import static org.mockito.ArgumentMatchers.any; | ||
import static org.mockito.ArgumentMatchers.anyString; | ||
import static org.mockito.ArgumentMatchers.argThat; | ||
import static org.mockito.ArgumentMatchers.eq; | ||
import static org.mockito.Mockito.verify; | ||
import static org.mockito.Mockito.when; | ||
|
||
import java.util.Collections; | ||
import java.util.Objects; | ||
import java.util.UUID; | ||
|
||
import org.cloudfoundry.identity.uaa.alias.EntityAliasHandler; | ||
import org.cloudfoundry.identity.uaa.alias.EntityAliasHandlerEnsureConsistencyTest; | ||
import org.cloudfoundry.identity.uaa.provider.IdentityProviderProvisioning; | ||
import org.cloudfoundry.identity.uaa.scim.exception.ScimResourceNotFoundException; | ||
import org.cloudfoundry.identity.uaa.util.UaaStringUtils; | ||
import org.cloudfoundry.identity.uaa.zone.IdentityZoneProvisioning; | ||
import org.cloudfoundry.identity.uaa.zone.ZoneDoesNotExistsException; | ||
import org.cloudfoundry.identity.uaa.zone.beans.IdentityZoneManager; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.ArgumentCaptor; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
class ScimUserAliasHandlerEnsureConsistencyTest extends EntityAliasHandlerEnsureConsistencyTest<ScimUser> { | ||
@Mock | ||
private ScimUserProvisioning scimUserProvisioning; | ||
@Mock | ||
private IdentityProviderProvisioning identityProviderProvisioning; | ||
@Mock | ||
private IdentityZoneManager identityZoneManager; | ||
@Mock | ||
private IdentityZoneProvisioning identityZoneProvisioning; | ||
|
||
@Override | ||
protected EntityAliasHandler<ScimUser> buildAliasHandler(final boolean aliasEntitiesEnabled) { | ||
return new ScimUserAliasHandler( | ||
identityZoneProvisioning, | ||
scimUserProvisioning, | ||
identityProviderProvisioning, | ||
identityZoneManager, | ||
aliasEntitiesEnabled | ||
); | ||
} | ||
|
||
@Override | ||
protected ScimUser shallowCloneEntity(final ScimUser entity) { | ||
final ScimUser clonedScimUser = new ScimUser(); | ||
clonedScimUser.setId(entity.getId()); | ||
clonedScimUser.setUserName(entity.getUserName()); | ||
clonedScimUser.setPrimaryEmail(entity.getPrimaryEmail()); | ||
clonedScimUser.setName(entity.getName()); | ||
clonedScimUser.setActive(entity.isActive()); | ||
clonedScimUser.setPhoneNumbers(entity.getPhoneNumbers()); | ||
clonedScimUser.setOrigin(entity.getOrigin()); | ||
clonedScimUser.setAliasId(entity.getAliasId()); | ||
clonedScimUser.setAliasZid(entity.getAliasZid()); | ||
clonedScimUser.setZoneId(entity.getZoneId()); | ||
clonedScimUser.setPassword(entity.getPassword()); | ||
clonedScimUser.setSalt(entity.getSalt()); | ||
return clonedScimUser; | ||
} | ||
|
||
@Override | ||
protected ScimUser buildEntityWithAliasProperties(String aliasId, String aliasZid) { | ||
final ScimUser scimUser = new ScimUser(); | ||
scimUser.setId(UUID.randomUUID().toString()); | ||
scimUser.setUserName("john.doe"); | ||
scimUser.setPrimaryEmail("john.doe@example.com"); | ||
scimUser.setName(new ScimUser.Name("John", "Doe")); | ||
scimUser.setActive(true); | ||
scimUser.setPhoneNumbers(Collections.singletonList(new ScimUser.PhoneNumber("12345"))); | ||
scimUser.setOrigin("some-origin"); | ||
scimUser.setAliasId(aliasId); | ||
scimUser.setAliasZid(aliasZid); | ||
scimUser.setZoneId(UAA); | ||
scimUser.setPassword(""); | ||
scimUser.setSalt(null); | ||
return scimUser; | ||
} | ||
|
||
@Override | ||
protected boolean entitiesAreEqual(final ScimUser entity1, final ScimUser entity2) { | ||
return Objects.equals(entity1.getId(), entity2.getId()) | ||
&& Objects.equals(entity1.getUserName(), entity2.getUserName()) | ||
&& Objects.equals(entity1.getPrimaryEmail(), entity2.getPrimaryEmail()) | ||
&& Objects.equals(entity1.getGivenName(), entity2.getGivenName()) | ||
&& Objects.equals(entity1.getFamilyName(), entity2.getFamilyName()) | ||
&& Objects.equals(entity1.isActive(), entity2.isActive()) | ||
&& Objects.equals(entity1.getPhoneNumbers(), entity2.getPhoneNumbers()) | ||
&& Objects.equals(entity1.getOrigin(), entity2.getOrigin()) | ||
&& Objects.equals(entity1.getAliasId(), entity2.getAliasId()) | ||
&& Objects.equals(entity1.getAliasZid(), entity2.getAliasZid()) | ||
&& Objects.equals(entity1.getZoneId(), entity2.getZoneId()) | ||
&& Objects.equals(entity1.getPassword(), entity2.getPassword()) | ||
&& Objects.equals(entity1.getSalt(), entity2.getSalt()); | ||
} | ||
|
||
@Override | ||
protected void changeNonAliasProperties(final ScimUser entity) { | ||
entity.getName().setGivenName("some-new-given-name"); | ||
} | ||
|
||
@Override | ||
protected void arrangeZoneDoesNotExist(final String zoneId) { | ||
when(identityZoneProvisioning.retrieve(zoneId)) | ||
.thenThrow(new ZoneDoesNotExistsException("zone does not exist")); | ||
} | ||
|
||
@Override | ||
protected void mockUpdateEntity(final String zoneId) { | ||
when(scimUserProvisioning.update(any(), any(), eq(zoneId))) | ||
.then(invocationOnMock -> invocationOnMock.getArgument(1)); | ||
} | ||
|
||
@Override | ||
protected void mockCreateEntity(final String newId, final String zoneId) { | ||
when(scimUserProvisioning.createUser(any(), anyString(), eq(zoneId))).then(invocationOnMock -> { | ||
final ScimUser scimUser = invocationOnMock.getArgument(0); | ||
scimUser.setId(newId); | ||
return scimUser; | ||
}); | ||
} | ||
|
||
@Override | ||
protected void arrangeEntityExists(final String id, final String zoneId, final ScimUser entity) { | ||
when(scimUserProvisioning.retrieve(id, zoneId)).thenReturn(entity); | ||
} | ||
|
||
@Override | ||
protected void arrangeEntityDoesNotExist(final String id, final String zoneId) { | ||
when(scimUserProvisioning.retrieve(id, zoneId)).thenThrow(new ScimResourceNotFoundException("user not found")); | ||
} | ||
|
||
@Nested | ||
class ExistingAlias { | ||
@Nested | ||
class AliasFeatureEnabled extends ExistingAlias_AliasFeatureEnabled { | ||
@Test | ||
void shouldPropagateChangesToExistingAlias() { | ||
final String aliasId = UUID.randomUUID().toString(); | ||
final ScimUser existingUser = buildEntityWithAliasProperties(aliasId, customZoneId); | ||
|
||
final ScimUser originalUser = shallowCloneEntity(existingUser); | ||
final String newGivenName = "some-new-name"; | ||
originalUser.setName(new ScimUser.Name(newGivenName, originalUser.getFamilyName())); | ||
|
||
// arrange alias user is present | ||
final ScimUser aliasUser = shallowCloneEntity(existingUser); | ||
aliasUser.setId(existingUser.getAliasId()); | ||
aliasUser.setZoneId(existingUser.getAliasZid()); | ||
aliasUser.setAliasId(existingUser.getId()); | ||
aliasUser.setAliasZid(existingUser.getZoneId()); | ||
arrangeEntityExists(aliasUser.getId(), aliasUser.getZoneId(), aliasUser); | ||
|
||
final ScimUser result = aliasHandler.ensureConsistencyOfAliasEntity( | ||
originalUser, | ||
existingUser | ||
); | ||
assertThat(entitiesAreEqual(result, originalUser)).isTrue(); | ||
|
||
// check if the change was propagated to the alias user | ||
final ArgumentCaptor<ScimUser> userArgCaptor = ArgumentCaptor.forClass(ScimUser.class); | ||
verify(scimUserProvisioning).update(eq(aliasId), userArgCaptor.capture(), eq(customZoneId)); | ||
final ScimUser capturedUser = userArgCaptor.getValue(); | ||
assertThat(capturedUser.getAliasId()).isEqualTo(existingUser.getId()); | ||
assertThat(capturedUser.getAliasZid()).isEqualTo(UAA); | ||
assertThat(capturedUser.getId()).isEqualTo(aliasId); | ||
assertThat(capturedUser.getZoneId()).isEqualTo(customZoneId); | ||
assertThat(capturedUser.getGivenName()).isEqualTo(newGivenName); | ||
} | ||
|
||
@Test | ||
void shouldFixDanglingReferenceByCreatingNewAliasEntity() { | ||
final String initialAliasId = UUID.randomUUID().toString(); | ||
final ScimUser existingUser = buildEntityWithAliasProperties(initialAliasId, customZoneId); | ||
final String originalUserId = existingUser.getId(); | ||
|
||
final ScimUser requestBody = shallowCloneEntity(existingUser); | ||
final String newGivenName = "some-new-given-name"; | ||
requestBody.setName(new ScimUser.Name(newGivenName, requestBody.getFamilyName())); | ||
|
||
// dangling reference -> referenced alias user not present | ||
arrangeEntityDoesNotExist(initialAliasId, customZoneId); | ||
|
||
// mock creation of new alias user | ||
final ScimUser createdAliasUser = shallowCloneEntity(requestBody); | ||
final String newAliasUserId = UUID.randomUUID().toString(); | ||
createdAliasUser.setId(newAliasUserId); | ||
createdAliasUser.setZoneId(customZoneId); | ||
createdAliasUser.setAliasId(originalUserId); | ||
createdAliasUser.setAliasZid(UAA); | ||
when(scimUserProvisioning.createUser( | ||
argThat(new EntityWithAliasMatcher<>(customZoneId, null, originalUserId, UAA)), | ||
eq(UaaStringUtils.EMPTY_STRING), | ||
eq(customZoneId) | ||
)).thenReturn(createdAliasUser); | ||
|
||
// mock update of original user | ||
when(scimUserProvisioning.update( | ||
eq(originalUserId), | ||
argThat(new EntityWithAliasMatcher<>(UAA, originalUserId, newAliasUserId, customZoneId)), | ||
eq(UAA) | ||
)).then(invocationOnMock -> invocationOnMock.getArgument(1)); | ||
|
||
// check if the original user now references the new alias | ||
final ScimUser result = aliasHandler.ensureConsistencyOfAliasEntity( | ||
requestBody, | ||
existingUser | ||
); | ||
assertThat(result.getAliasId()).isEqualTo(newAliasUserId); | ||
assertThat(result.getAliasZid()).isEqualTo(customZoneId); | ||
|
||
// should update original user with new aliasId | ||
final ArgumentCaptor<ScimUser> originalUserCaptor = ArgumentCaptor.forClass(ScimUser.class); | ||
verify(scimUserProvisioning).update(eq(originalUserId), originalUserCaptor.capture(), eq(UAA)); | ||
final ScimUser capturedOriginalUser = originalUserCaptor.getValue(); | ||
assertThat(capturedOriginalUser.getAliasId()).isEqualTo(newAliasUserId); | ||
} | ||
} | ||
|
||
@Nested | ||
class AliasFeatureDisabled extends ExistingAlias_AliasFeatureDisabled { | ||
// all tests defined in superclass | ||
} | ||
} | ||
|
||
@Nested | ||
class NoExistingAlias { | ||
@Nested | ||
class AliasFeatureEnabled extends NoExistingAlias_AliasFeatureEnabled { | ||
// all tests defined in superclass | ||
} | ||
|
||
@Nested | ||
class AliasFeatureDisabled extends NoExistingAlias_AliasFeatureDisabled { | ||
// all tests defined in superclass | ||
} | ||
} | ||
} |