package com.constellio.model.services.security; import static com.constellio.model.entities.schemas.Schemas.IDENTIFIER; import static com.constellio.model.entities.schemas.Schemas.REMOVED_AUTHORIZATIONS; import static com.constellio.model.entities.security.Role.DELETE; import static com.constellio.model.entities.security.Role.READ; import static com.constellio.model.entities.security.Role.WRITE; import static com.constellio.model.entities.security.global.AuthorizationAddRequest.authorizationInCollection; import static com.constellio.model.entities.security.global.AuthorizationAddRequest.authorizationInCollectionWithId; import static com.constellio.model.entities.security.global.UserCredentialStatus.ACTIVE; import static com.constellio.model.services.search.query.logical.LogicalSearchQuery.query; import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.ALL; import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.from; import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.fromAllSchemasIn; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.assertj.core.api.BooleanAssert; import org.assertj.core.api.Condition; import org.assertj.core.api.ListAssert; import org.joda.time.LocalDate; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import com.constellio.model.entities.Taxonomy; import com.constellio.model.entities.batchprocess.BatchProcess; import com.constellio.model.entities.records.Record; import com.constellio.model.entities.records.wrappers.Event; import com.constellio.model.entities.records.wrappers.Group; import com.constellio.model.entities.records.wrappers.SolrAuthorizationDetails; import com.constellio.model.entities.records.wrappers.User; import com.constellio.model.entities.schemas.MetadataSchema; import com.constellio.model.entities.schemas.MetadataSchemaType; import com.constellio.model.entities.schemas.Schemas; import com.constellio.model.entities.security.Authorization; import com.constellio.model.entities.security.Role; import com.constellio.model.entities.security.global.AuthorizationAddRequest; import com.constellio.model.entities.security.global.AuthorizationDetails; import com.constellio.model.entities.security.global.AuthorizationModificationRequest; import com.constellio.model.entities.security.global.AuthorizationModificationResponse; import com.constellio.model.entities.security.global.UserCredential; import com.constellio.model.services.collections.CollectionsListManager; import com.constellio.model.services.records.RecordServices; import com.constellio.model.services.records.RecordServicesException; import com.constellio.model.services.records.RecordServicesRuntimeException.NoSuchRecordWithId; import com.constellio.model.services.records.RecordUtils; import com.constellio.model.services.records.SchemasRecordsServices; import com.constellio.model.services.records.cache.CacheConfig; import com.constellio.model.services.schemas.MetadataSchemasManager; import com.constellio.model.services.search.SearchServices; import com.constellio.model.services.search.query.logical.LogicalSearchQuery; import com.constellio.model.services.search.query.logical.condition.LogicalSearchCondition; import com.constellio.model.services.security.SecurityAcceptanceTestSetup.Records; import com.constellio.model.services.security.roles.RolesManager; import com.constellio.model.services.taxonomies.TaxonomiesManager; import com.constellio.model.services.users.UserServices; import com.constellio.sdk.tests.ConstellioTest; import com.constellio.sdk.tests.setups.Users; public class BaseAuthorizationsServicesAcceptanceTest extends ConstellioTest { protected String anotherCollection = "anotherCollection"; protected SecurityAcceptanceTestSetup anothercollectionSetup = new SecurityAcceptanceTestSetup(anotherCollection); protected String ZE_ROLE = "zeRoleCode"; protected String ZE_GROUP = "zeGroupCode"; protected String zeUnusedRoleCode = "zeNotUsed"; protected SecurityAcceptanceTestSetup setup = new SecurityAcceptanceTestSetup(zeCollection); protected MetadataSchemasManager schemasManager; protected SearchServices searchServices; protected RecordServices recordServices; protected TaxonomiesManager taxonomiesManager; protected CollectionsListManager collectionsListManager; protected AuthorizationsServices services; protected UserServices userServices; protected SchemasRecordsServices schemas; protected Records records; protected Records otherCollectionRecords; protected Users users = new Users(); protected RolesManager roleManager; protected String ROLE1 = "role1"; protected String ROLE2 = "role2"; protected String ROLE3 = "role3"; protected String PERMISSION_OF_NO_ROLE = "permissionOfNoRole"; protected String PERMISSION_OF_ROLE1 = "permissionOfRole1"; protected String PERMISSION_OF_ROLE2 = "permissionOfRole2"; protected String PERMISSION_OF_ROLE3 = "permissionOfRole3"; protected String PERMISSION_OF_ROLE1_AND_ROLE2 = "permissionOfRole1AndRole2"; protected final String VERSION_HISTORY_READ = "VERSION_HISTORY_READ"; protected final String VERSION_HISTORY = "VERSION_HISTORY"; protected AuthorizationModificationResponse request1, request2, request3; protected List<String> initialFinishedBatchProcesses; protected String auth1, auth2, auth3, auth4, auth5, auth6, auth7; String[] allUsers = new String[] { alice, bob, charles, dakota, edouard, gandalf, chuck, sasquatch, robin }; @Before public void setUp() throws Exception { customSystemPreparation(new CustomSystemPreparation() { @Override public void prepare() { givenCollection(zeCollection).withAllTestUsers(); givenCollection(anotherCollection).withAllTestUsers(); setServices(); defineSchemasManager().using(setup); taxonomiesManager.addTaxonomy(setup.getTaxonomy1(), schemasManager); taxonomiesManager.addTaxonomy(setup.getTaxonomy2(), schemasManager); defineSchemasManager().using(anothercollectionSetup); taxonomiesManager.addTaxonomy(anothercollectionSetup.getTaxonomy1(), schemasManager); taxonomiesManager.addTaxonomy(anothercollectionSetup.getTaxonomy2(), schemasManager); RolesManager rolesManager = getModelLayerFactory().getRolesManager(); rolesManager.addRole( new Role(zeCollection, ROLE1, "Ze role 1", asList(PERMISSION_OF_ROLE1, PERMISSION_OF_ROLE1_AND_ROLE2))); rolesManager.addRole( new Role(zeCollection, ROLE2, "Ze role 2", asList(PERMISSION_OF_ROLE2, PERMISSION_OF_ROLE1_AND_ROLE2))); rolesManager.addRole(new Role(zeCollection, ROLE3, "Ze role 3", asList(PERMISSION_OF_ROLE3))); try { givenChuckNorrisSeesEverything(); givenAliceCanModifyEverythingAndBobCanDeleteEverythingAndDakotaReadEverythingInAnotherCollection(); } catch (Exception e) { throw new RuntimeException(e); } } protected void setServices() { recordServices = getModelLayerFactory().newRecordServices(); taxonomiesManager = getModelLayerFactory().getTaxonomiesManager(); searchServices = getModelLayerFactory().newSearchServices(); services = getModelLayerFactory().newAuthorizationsServices(); schemasManager = getModelLayerFactory().getMetadataSchemasManager(); roleManager = getModelLayerFactory().getRolesManager(); collectionsListManager = getModelLayerFactory().getCollectionsListManager(); userServices = getModelLayerFactory().newUserServices(); schemas = new SchemasRecordsServices(zeCollection, getModelLayerFactory()); users.setUp(getModelLayerFactory().newUserServices()); } @Override public void initializeFromCache() { setServices(); setup.refresh(schemasManager); anothercollectionSetup.refresh(schemasManager); } }); waitForBatchProcess(); initialFinishedBatchProcesses = new ArrayList<>(); for (BatchProcess batchProcess : getModelLayerFactory().getBatchProcessesManager().getFinishedBatchProcesses()) { initialFinishedBatchProcesses.add(batchProcess.getId()); } givenTaxonomy1IsThePrincipalAndSomeRecords(); recordServices.getRecordsCaches().getCache(zeCollection) .configureCache(CacheConfig.permanentCache(schemas.authorizationDetails.schemaType())); recordServices.getRecordsCaches().getCache(anotherCollection) .configureCache(CacheConfig.permanentCache(schemas.authorizationDetails.schemaType())); } protected ListAssert<String> assertThatBatchProcessDuringTest() { try { waitForBatchProcess(); } catch (InterruptedException e) { throw new RuntimeException(e); } List<String> allBatchProcesses = new ArrayList<>(); List<String> batchProcessesUsingTests = new ArrayList<>(); List<BatchProcess> finishedBatchProcesses = getModelLayerFactory().getBatchProcessesManager().getFinishedBatchProcesses(); for (BatchProcess batchProcess : finishedBatchProcesses) { allBatchProcesses.add(batchProcess.getId()); if (!initialFinishedBatchProcesses.contains(batchProcess.getId())) { batchProcessesUsingTests.add(batchProcess.getQuery()); } } initialFinishedBatchProcesses = allBatchProcesses; return assertThat(batchProcessesUsingTests); } protected void givenTaxonomy1IsThePrincipalAndSomeRecords() { Taxonomy taxonomy = taxonomiesManager.getEnabledTaxonomyWithCode(zeCollection, "taxo1"); taxonomiesManager.setPrincipalTaxonomy(taxonomy, schemasManager); records = setup.givenRecords(recordServices); otherCollectionRecords = anothercollectionSetup.givenRecords(recordServices); } static int totalBatchProcessCount = 0; @After public void checkIfNoBatchProcessRequired() { List<String> finishedBatchProcesses = new ArrayList<>(); for (BatchProcess batchProcess : getModelLayerFactory().getBatchProcessesManager().getFinishedBatchProcesses()) { finishedBatchProcesses.add(batchProcess.getId()); } int batchProcessCount = finishedBatchProcesses.size() - initialFinishedBatchProcesses.size(); totalBatchProcessCount += batchProcessCount; } @AfterClass public static void tearDown() throws Exception { System.out.println("Total batch process count : " + totalBatchProcessCount); } protected UserVerifier forUserInAnotherCollection(String username) { return new UserVerifier(username, anotherCollection); } protected UserVerifier forUser(String username) { return new UserVerifier(username, zeCollection); } protected class UserVerifier { String username; String collection; public UserVerifier(String username, String collection) { this.username = username; this.collection = collection; } public User getUser() { return userServices.getUserInCollection(username, collection); } public ListAssert<String> assertThatConceptsForWhichUserHas(String permission) { return assertThat(services.getConceptsForWhichUserHasPermission(permission, getUser())) .describedAs("Concepts for which user '" + username + "' has permission '" + permission + "'"); } public BooleanAssert assertHasDeletePermissionOnPrincipalConceptExcludingRecords( String id) { Record record = recordServices.getDocumentById(id); return assertThat(services.hasDeletePermissionOnPrincipalConceptHierarchy(getUser(), record, false, schemasManager)); } public BooleanAssert assertHasDeletePermissionOnPrincipalConceptIncludingRecords( String id) { Record record = recordServices.getDocumentById(id); return assertThat(services.hasDeletePermissionOnPrincipalConceptHierarchy(getUser(), record, true, schemasManager)); } public BooleanAssert assertHasRestorePermissionOnHierarchyOf( String id) { Record record = recordServices.getDocumentById(id); return assertThat(services.hasRestaurationPermissionOnHierarchy(getUser(), record)); } public BooleanAssert assertHasDeletePermissionOnHierarchyOf( String id) { Record record = recordServices.getDocumentById(id); return assertThat(services.hasDeletePermissionOnHierarchy(getUser(), record)); } public ListAssert<String> assertThatRecordsWithReadAccess() { List<MetadataSchemaType> types = asList(setup.folderSchema.type(), setup.documentFond.type(), setup.administrativeUnit.type(), setup.category.type(), setup.classificationStation.type(), setup.documentSchema.type()); return assertThat(searchServices.searchRecordIds(query(from(types).returnAll()).filteredWithUser(getUser()))); } public ListAssert<String> assertThatAllFoldersAndDocuments() { return assertThat(findAllFoldersAndDocuments(getUser())); } } protected RecordVerifier forRecord(String id) { return new RecordVerifier(id); } protected class RecordVerifier { String recordId; public RecordVerifier(String recordId) { this.recordId = recordId; } public ListAssert<Object> usersWithRole(String role) { return assertThat(services.getUsersWithRoleForRecord(role, get(recordId))) .describedAs("users with role '" + role + "' on record '" + recordId + "'").extracting("username"); } public ListAssert<Object> assertThatUsersWithPermission(String permission) { return assertThat(services.getUsersWithPermissionOnRecord(permission, get(recordId))) .describedAs("users with permission '" + permission + "' on record '" + recordId + "'") .extracting("username"); } public ListAssert<Object> getUsersWithPermissionOnRecordExcludingRecordInheritedAuthorizations(String permission) { return assertThat( services.getUsersWithPermissionOnRecordExcludingRecordInheritedAuthorizations(permission, get(recordId))) .describedAs("users with permission '" + permission + "' on record '" + recordId + "'") .extracting("username"); } public ListAssert<String> usersWithReadAccess() { Record record = get(recordId); List<User> allUsers = userServices.getAllUsersInCollection(zeCollection); List<String> usersWithReadAccess = new ArrayList<>(); for (User user : allUsers) { if (hasReadAccess(user, record)) { usersWithReadAccess.add(user.getUsername()); } } return assertThat(usersWithReadAccess).describedAs("read access on record '" + recordId + "'"); } public ListAssert<String> usersWithWriteAccess() { Record record = get(recordId); List<User> allUsers = userServices.getAllUsersInCollection(zeCollection); List<String> usersWithWriteAccess = new ArrayList<>(); for (User user : allUsers) { if (hasWriteAccess(user, record)) { usersWithWriteAccess.add(user.getUsername()); } } return assertThat(usersWithWriteAccess).describedAs("write access on record '" + recordId + "'"); } public ListAssert<String> usersWithDeleteAccess() { Record record = get(recordId); List<User> allUsers = userServices.getAllUsersInCollection(zeCollection); List<String> usersWithDeleteAccess = new ArrayList<>(); for (User user : allUsers) { if (hasDeleteAccess(user, record)) { usersWithDeleteAccess.add(user.getUsername()); } } return assertThat(usersWithDeleteAccess).describedAs("delete access on record '" + recordId + "'"); } public ListAssert<String> usersWithPermission(String permission) { Record record = get(recordId); List<User> allUsers = userServices.getAllUsersInCollection(zeCollection); List<String> usersWithDeleteAccess = new ArrayList<>(); for (User user : allUsers) { if (hasPermissionOn(user, record, permission)) { usersWithDeleteAccess.add(user.getUsername()); } } return assertThat(usersWithDeleteAccess).describedAs("delete access on record '" + recordId + "'"); } public BooleanAssert detachedAuthorizationFlag() { Record record = get(recordId); return assertThat(Boolean.TRUE == record.get(Schemas.IS_DETACHED_AUTHORIZATIONS)) .describedAs("detach authorization flag on record '" + recordId + "'"); } } protected boolean hasReadAccess(User user, Record record) { boolean hasAccessUsingWrapperMethod = user.hasReadAccess().on(record); boolean hasAccessUsingSearchTokens = searchServices.hasResults(new LogicalSearchQuery().filteredWithUser(user) .setCondition(fromAllSchemasIn(zeCollection).where(IDENTIFIER).isEqualTo(record))); if (hasAccessUsingWrapperMethod && !hasAccessUsingSearchTokens) { fail("User has read access using wrapper method, but not using search"); } if (!hasAccessUsingWrapperMethod && hasAccessUsingSearchTokens) { fail("User has read access using search, but not using wrapper method"); } return hasAccessUsingWrapperMethod; } protected boolean hasWriteAccess(User user, Record record) { boolean hasAccessUsingWrapperMethod = user.hasWriteAccess().on(record); boolean hasAccessUsingSearchTokens = searchServices.hasResults(new LogicalSearchQuery().filteredWithUserWrite(user) .setCondition(fromAllSchemasIn(zeCollection).where(IDENTIFIER).isEqualTo(record))); if (hasAccessUsingWrapperMethod && !hasAccessUsingSearchTokens) { fail("User has read access using wrapper method, but not using search"); } if (!hasAccessUsingWrapperMethod && hasAccessUsingSearchTokens) { fail("User has read access using search, but not using wrapper method"); } return hasAccessUsingWrapperMethod; } protected boolean hasDeleteAccess(User user, Record record) { boolean hasAccessUsingWrapperMethod = user.hasDeleteAccess().on(record); boolean hasAccessUsingSearchTokens = searchServices.hasResults(new LogicalSearchQuery().filteredWithUserDelete(user) .setCondition(fromAllSchemasIn(zeCollection).where(IDENTIFIER).isEqualTo(record))); if (hasAccessUsingWrapperMethod && !hasAccessUsingSearchTokens) { fail("User has read access using wrapper method, but not using search"); } if (!hasAccessUsingWrapperMethod && hasAccessUsingSearchTokens) { fail("User has read access using search, but not using wrapper method"); } return hasAccessUsingWrapperMethod; } protected boolean hasPermissionOn(User user, Record record, String permission) { boolean hasAccessUsingWrapperMethod = user.has(permission).on(record); return hasAccessUsingWrapperMethod; } protected AuthorizationAddRequest authorization() { return authorizationInCollection(zeCollection); } protected AuthorizationAddRequest authorization(String existingAuthorizationId) { return authorizationInCollection(zeCollection); } protected AuthorizationAddRequest authorizationForUsers(String... usernames) { User[] usersArray = new User[usernames.length]; for (int i = 0; i < usernames.length; i++) { usersArray[i] = userServices.getUserInCollection(usernames[i], zeCollection); } return authorizationInCollection(zeCollection).forUsers(usersArray); } protected AuthorizationAddRequest authorizationForGroups(String... groups) { Group[] groupsArray = new Group[groups.length]; for (int i = 0; i < groups.length; i++) { groupsArray[i] = userServices.getGroupInCollection(groups[i], zeCollection); } return authorizationInCollection(zeCollection).forGroups(groupsArray); } protected AuthorizationAddRequest authorizationForUser(String username) { User[] usersArray = new User[] { userServices.getUserInCollection(username, zeCollection) }; return authorizationInCollection(zeCollection).forUsers(usersArray); } protected AuthorizationAddRequest authorizationForPrincipals(String... principals) { List<String> principalIds = new ArrayList<>(); for (String principal : principals) { principalIds.add(toPrincipalId(principal)); } return authorizationInCollection(zeCollection).forPrincipalsIds(principalIds); } protected AuthorizationAddRequest authorizationForGroup(String group) { Group[] groupsArray = new Group[] { userServices.getGroupInCollection(group, zeCollection) }; return authorizationInCollection(zeCollection).forGroups(groupsArray); } protected long fetchEventCount() { LogicalSearchCondition condition = from(schemasManager.getSchemaTypes(zeCollection).getSchemaType(Event.SCHEMA_TYPE)) .returnAll(); return searchServices.getResultsCount(condition); } protected RecordVerifier verifyRecord(String id) { return new RecordVerifier(id); } protected List<RecordVerifier> $(String... ids) { List<RecordVerifier> verifiers = new ArrayList<>(); for (String id : ids) { verifiers.add(new RecordVerifier(id)); } return verifiers; } protected VerifiedAuthorization authOnRecord(String recordId) { return new VerifiedAuthorization(recordId); } protected class VerifiedAuthorization { String recordId; Set<String> principals; Set<String> removedOnRecords = new HashSet<>(); List<String> roles; LocalDate start; LocalDate end; protected VerifiedAuthorization(String recordId) { this.recordId = recordId; } protected VerifiedAuthorization forPrincipals(String... principals) { this.principals = new HashSet<>(asList(principals)); return this; } protected VerifiedAuthorization forPrincipalIds(List<String> principals) { this.principals = new HashSet<>(toPrincipalCodes(principals.toArray(new String[] {}))); return this; } protected VerifiedAuthorization removedOnRecords(String... removedOnRecords) { this.removedOnRecords = new HashSet<>(asList(removedOnRecords)); return this; } protected VerifiedAuthorization givingRoles(String... roles) { this.roles = asList(roles); return this; } protected VerifiedAuthorization givingRead() { this.roles = asList(READ); return this; } protected VerifiedAuthorization givingReadWrite() { this.roles = asList(READ, WRITE); return this; } protected VerifiedAuthorization givingReadWriteDelete() { this.roles = asList(READ, WRITE, DELETE); return this; } protected VerifiedAuthorization startingOn(LocalDate start) { this.start = start; return this; } protected VerifiedAuthorization endingOn(LocalDate end) { this.end = end; return this; } public String getRecordId() { return recordId; } public Set<String> getPrincipals() { return principals; } public Set<String> getRemovedOnRecords() { return removedOnRecords; } public List<String> getRoles() { return roles; } public LocalDate getStart() { return start; } public LocalDate getEnd() { return end; } @Override public String toString() { return "{recordId='" + recordId + '\'' + ", principals=" + principals + ", removedOnRecords=" + removedOnRecords + ", roles=" + roles + ", start=" + start + ", end=" + end + '}'; } } protected ListAssert<String> assertThatAllAuthorizationIds() { List<String> authorizations = new ArrayList<>(); for (AuthorizationDetails details : getModelLayerFactory().getAuthorizationDetailsManager() .getAuthorizationsDetails(zeCollection).values()) { authorizations.add(details.getId()); } return assertThat(authorizations); } protected ListAssert<String> ensureNoRecordsHaveAnInvalidAuthorization() { try { waitForBatchProcess(); } catch (InterruptedException e) { throw new RuntimeException(e); } List<String> authorizations = new ArrayList<>(); for (SolrAuthorizationDetails details : schemas.searchSolrAuthorizationDetailss(ALL)) { authorizations.add(details.getId()); try { recordServices.getDocumentById(details.getTarget()); } catch (NoSuchRecordWithId e) { throw new RuntimeException( "Auth '" + details.getId() + "' is targetting an inexistent record : " + details.getTarget()); } } Iterator<Record> recordIterator = searchServices.recordsIterator(query(fromAllSchemasIn(zeCollection).returnAll())); while (recordIterator.hasNext()) { Record record = recordIterator.next(); for (String auth : record.<String>getList(Schemas.REMOVED_AUTHORIZATIONS)) { if (!authorizations.contains(auth)) { throw new RuntimeException("Record '" + record.getIdTitle() + "' has an invalid authorization : " + auth); } } } return assertThat(authorizations); } protected ListAssert<String> assertThatAllAuthorizationsIds() { List<String> authorizations = new ArrayList<>(); for (AuthorizationDetails details : schemas.searchSolrAuthorizationDetailss(ALL)) { authorizations.add(details.getId()); } return assertThat(authorizations); } protected ListAssert<VerifiedAuthorization> assertThatAllAuthorizations() { List<VerifiedAuthorization> authorizations = new ArrayList<>(); for (AuthorizationDetails details : schemas.searchSolrAuthorizationDetailss(ALL)) { Authorization authorization = services.getAuthorization(zeCollection, details.getId()); List<String> removedOnRecords = searchServices.searchRecordIds(fromAllSchemasIn(zeCollection).where( REMOVED_AUTHORIZATIONS).isEqualTo(authorization.getDetail().getId())); authorizations.add(authOnRecord(authorization.getGrantedOnRecord()) .forPrincipalIds(authorization.getGrantedToPrincipals()) .givingRoles(details.getRoles().toArray(new String[0])) .startingOn(details.getStartDate()).endingOn(details.getEndDate()) .removedOnRecords(removedOnRecords.toArray(new String[0]))); } return assertThat(authorizations).usingFieldByFieldElementComparator(); } protected String toPrincipalId(String principal) { try { return userServices.getUserInCollection(principal, zeCollection).getId(); } catch (Exception e) { return userServices.getGroupInCollection(principal, zeCollection).getId(); } } protected ListAssert<VerifiedAuthorization> assertThatAuthorizationsFor(String principal) { return assertThatAuthorizationsOn(toPrincipalId(principal)); } protected ListAssert<VerifiedAuthorization> assertThatAuthorizationsOn(String recordId) { Record record = recordServices.getDocumentById(recordId); List<VerifiedAuthorization> authorizations = new ArrayList<>(); for (Authorization authorization : services.getRecordAuthorizations(record)) { List<String> removedOnRecords = searchServices.searchRecordIds(fromAllSchemasIn(zeCollection).where( REMOVED_AUTHORIZATIONS).isEqualTo(authorization.getDetail().getId())); authorizations.add(authOnRecord(authorization.getGrantedOnRecord()) .forPrincipalIds(authorization.getGrantedToPrincipals()) .givingRoles(authorization.getDetail().getRoles().toArray(new String[0])) .removedOnRecords(removedOnRecords.toArray(new String[0]))); } return assertThat(authorizations).usingFieldByFieldElementComparator(); } protected class AuthorizationVerifier { String authId; public AuthorizationVerifier(String authId) { this.authId = authId; } public AuthorizationVerifier isDeleted() { assertThat(getModelLayerFactory().getAuthorizationDetailsManager().get(zeCollection, authId)) .describedAs("Authorization supposed to be deleted").isNull(); return this; } public AuthorizationVerifier isTargetting(String recordId) { return this; } public AuthorizationVerifier isOnlyRemovedOn(String... recordIds) { return this; } public AuthorizationVerifier hasPrincipals(String... principals) { List<String> expectedPrincipals = toPrincipalIds(principals); Authorization authorization = services .getAuthorization(zeCollection, authId); assertThat(authorization.getGrantedToPrincipals()).describedAs("principals") .containsOnly(expectedPrincipals.toArray(new String[0])); return this; } } protected List<String> toPrincipalCodes(String... principalIds) { List<String> codes = new ArrayList<>(); for (String principalId : principalIds) { Record record = recordServices.getDocumentById(principalId); if (record.getSchemaCode().startsWith("user")) { codes.add(schemas.wrapUser(record).getUsername()); } else { codes.add(schemas.wrapGroup(record).getCode()); } } return codes; } protected List<String> toPrincipalIds(String... principals) { List<String> ids = new ArrayList<>(); for (String principal : principals) { try { ids.add(userServices.getUserInCollection(principal, zeCollection).getId()); } catch (Exception e) { ids.add(userServices.getGroupInCollection(principal, zeCollection).getId()); } } return ids; } protected AuthorizationVerifier assertThatAuth(String id) { return new AuthorizationVerifier(id); } protected UserAction givenUser(String username) { return new UserAction(username); } protected class UserAction { String username; public UserAction(String username) { this.username = username; } public UserAction isRemovedFromGroup(String group) { userServices.addUpdateUserCredential(userServices.getUser(username).withRemovedGlobalGroup(group)); try { waitForBatchProcess(); } catch (InterruptedException e) { throw new RuntimeException(e); } return this; } public UserAction isAddedInGroup(String group) { userServices.addUpdateUserCredential(userServices.getUser(username).withNewGlobalGroup(group)); try { waitForBatchProcess(); } catch (InterruptedException e) { throw new RuntimeException(e); } return this; } public void logicallyThenPhysicallyDelete(String id) { Record record = record(id); User user = userServices.getUserInCollection(username, record.getCollection()); recordServices.logicallyDelete(record, user); recordServices.physicallyDelete(record, user); } } protected AuthorizationModificationRequest authorizationOnRecord(String authorizationId, String recordId) { return new AuthorizationModificationRequest(authorizationId, zeCollection, recordId); } protected AuthorizationModificationResponse modify(AuthorizationModificationRequest request) { AuthorizationModificationResponse response = services.execute(request); try { waitForBatchProcess(); } catch (InterruptedException e) { throw new RuntimeException(e); } return response; } protected Condition<? super AuthorizationModificationResponse> deleted() { return new Condition<AuthorizationModificationResponse>() { @Override public boolean matches(AuthorizationModificationResponse value) { return value.isAuthorizationDeleted(); } }; } protected Condition<? super AuthorizationModificationResponse> creatingACopy() { return new Condition<AuthorizationModificationResponse>() { @Override public boolean matches(AuthorizationModificationResponse value) { return value.getIdOfAuthorizationCopy() != null; } }; } protected Record get(String recordId) { return recordServices.getDocumentById(recordId); } // --------------------------------------------------------------------------------------------------------- protected Condition<? super User> allowedToWrite(final Record record) { recordServices.refresh(record); return new Condition<User>() { @Override public boolean matches(User user) { assertThat(services.canWrite(user, record)) .describedAs("can write '" + record.getId() + "'") .isTrue(); return true; } }; } protected Condition<? super User> notAllowedToWrite(final Record record) { recordServices.refresh(record); return new Condition<User>() { @Override public boolean matches(User user) { assertThat(services.canWrite(user, record)) .describedAs("can write '" + record.getId() + "'") .isFalse(); return true; } }; } protected List<String> findAllFoldersAndDocumentsWithWritePermission(User user) { MetadataSchema folderSchema, documentSchema; if (user.getCollection().endsWith("zeCollection")) { folderSchema = setup.folderSchema.instance(); documentSchema = setup.documentSchema.instance(); } else { folderSchema = anothercollectionSetup.folderSchema.instance(); documentSchema = anothercollectionSetup.documentSchema.instance(); } LogicalSearchQuery query = new LogicalSearchQuery(); query.setCondition(from(folderSchema).returnAll()); query.filteredWithUserWrite(user); List<String> recordIds = searchServices.searchRecordIds(query); query.setCondition(from(documentSchema).returnAll()); recordIds.addAll(searchServices.searchRecordIds(query)); return recordIds; } protected List<String> findAllFoldersAndDocumentsWithDeletePermission(User user) { MetadataSchema folderSchema, documentSchema; if (user.getCollection().endsWith("zeCollection")) { folderSchema = setup.folderSchema.instance(); documentSchema = setup.documentSchema.instance(); } else { folderSchema = anothercollectionSetup.folderSchema.instance(); documentSchema = anothercollectionSetup.documentSchema.instance(); } LogicalSearchQuery query = new LogicalSearchQuery(); query.setCondition(from(folderSchema).returnAll()); query.filteredWithUserDelete(user); List<String> recordIds = searchServices.searchRecordIds(query); query.setCondition(from(documentSchema).returnAll()); recordIds.addAll(searchServices.searchRecordIds(query)); return recordIds; } protected List<String> findAllFoldersAndDocuments(User user) { List<String> recordIds = new ArrayList<>(); MetadataSchema folderSchema, documentSchema; if (user.getCollection().endsWith("zeCollection")) { folderSchema = setup.folderSchema.instance(); documentSchema = setup.documentSchema.instance(); } else { folderSchema = anothercollectionSetup.folderSchema.instance(); documentSchema = anothercollectionSetup.documentSchema.instance(); } LogicalSearchQuery query = new LogicalSearchQuery(); query.setCondition(from(folderSchema).returnAll()); query.filteredWithUser(user); recordIds.addAll(searchServices.searchRecordIds(query)); query = new LogicalSearchQuery(); query.setCondition(from(documentSchema).returnAll()); query.filteredWithUser(user); recordIds.addAll(searchServices.searchRecordIds(query)); return recordIds; } @Deprecated protected Authorization addAuthorizationWithoutDetaching(List<String> roles, List<String> grantedToPrincipals, String grantedOnRecord) { return addAuthorizationWithoutDetaching(aString(), roles, grantedToPrincipals, grantedOnRecord); } @Deprecated protected Authorization addAuthorizationWithoutDetaching(String id, List<String> roles, List<String> grantedToPrincipals, String grantedOnRecord) { id = services.add(authorizationInCollectionWithId(zeCollection, id).forPrincipalsIds(grantedToPrincipals) .on(grantedOnRecord) .giving(roles).setExecutedBy(users.dakotaLIndienIn(zeCollection))); return services.getAuthorization(zeCollection, id); } protected String add(AuthorizationAddRequest request) { String id = services.add(request, users.dakotaLIndienIn(zeCollection)); try { waitForBatchProcess(); } catch (InterruptedException e) { throw new RuntimeException(e); } return id; } protected String addWithoutUser(AuthorizationAddRequest authorization) { String id = services.add(authorization, null); try { waitForBatchProcess(); } catch (InterruptedException e) { throw new RuntimeException(e); } return id; } protected Map<String, String> detach(String recordId) { Map<String, String> copies = services.detach(get(recordId)); try { waitForBatchProcess(); } catch (InterruptedException e) { throw new RuntimeException(e); } return copies; } protected Group createGroup(String name) { return userServices.createCustomGroupInCollectionWithCodeAndName(zeCollection, ZE_GROUP, name); } protected void givenChuckNorrisSeesEverything() throws Exception { User chuck = users.chuckNorrisIn(zeCollection); chuck.setCollectionReadAccess(true); chuck.setCollectionWriteAccess(true); chuck.setCollectionDeleteAccess(true); recordServices.update(chuck.getWrappedRecord()); } protected void givenAliceCanModifyEverythingAndBobCanDeleteEverythingAndDakotaReadEverythingInAnotherCollection() throws RecordServicesException { User alice = users.aliceIn(anotherCollection); alice.setCollectionWriteAccess(true); recordServices.update(alice.getWrappedRecord()); User bob = users.bobIn(anotherCollection); bob.setCollectionDeleteAccess(true); recordServices.update(bob.getWrappedRecord()); User dakota = users.dakotaIn(anotherCollection); dakota.setCollectionReadAccess(true); recordServices.update(dakota.getWrappedRecord()); } protected Condition<? super User> authorizationsToRead(final Record... records) { final List<String> recordIds = new RecordUtils().toIdList(asList(records)); return new Condition<User>() { @Override public boolean matches(User user) { LogicalSearchQuery query = new LogicalSearchQuery() .setCondition(fromAllSchemasIn(user.getCollection()).returnAll()) .filteredWithUser(user); List<String> results = searchServices.searchRecordIds(query); assertThat(results).containsAll(recordIds); return true; } }; } protected Condition<? super User> noAuthorizationsToRead(final Record... records) { final List<String> recordIds = new RecordUtils().toIdList(asList(records)); return new Condition<User>() { @Override public boolean matches(User user) { LogicalSearchQuery query = new LogicalSearchQuery() .setCondition(fromAllSchemasIn(user.getCollection()).returnAll()) .filteredWithUser(user); List<String> results = searchServices.searchRecordIds(query); assertThat(results).doesNotContainAnyElementsOf(recordIds); return true; } }; } protected ListAssert<Object> assertThatUsersWithGlobalPermissionInCollection(String permission, String collection) { return assertThat(services.getUsersWithGlobalPermissionInCollection(permission, collection)) .extracting("username"); } protected ListAssert<Object> assertThatUsersWithGlobalPermissionInZeCollection(String permission) { return assertThatUsersWithGlobalPermissionInCollection(permission, zeCollection); } protected List<String> createDummyUsersInLegendsGroup(int qty) { List<String> users = new ArrayList<>(); for (int i = 1; i <= qty; i++) { System.out.println("adding user " + i + "/" + qty); String username = "grim.patron." + i; UserCredential userCredential = userServices.createUserCredential(username, "Grim", "Patron", username + "@constellio.com", asList("legends"), asList(zeCollection), ACTIVE); userServices.addUpdateUserCredential(userCredential); users.add(username); } return users; } protected void givenRecordIsLogicallyThenPhysicallyDeleted(String folderId) { Record record = record(folderId); recordServices.logicallyDelete(record, User.GOD); recordServices.physicallyDelete(record, User.GOD); } }