package com.constellio.app.api.cmis.rm;
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.sdk.tests.TestUtils.asMap;
import static com.constellio.sdk.tests.TestUtils.assertThatRecords;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.api.Document;
import org.apache.chemistry.opencmis.client.api.Folder;
import org.apache.chemistry.opencmis.client.api.Session;
import org.apache.chemistry.opencmis.client.runtime.ObjectIdImpl;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.ContentStream;
import org.apache.chemistry.opencmis.commons.data.MutableProperties;
import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.assertj.core.api.ListAssert;
import org.assertj.core.groups.Tuple;
import org.junit.Before;
import org.junit.Test;
import com.constellio.app.api.cmis.accept.CmisAcceptanceTestSetup;
import com.constellio.app.api.cmis.accept.CmisSinglevalueContentManagementAcceptTest;
import com.constellio.app.modules.rm.RMTestRecords;
import com.constellio.app.modules.rm.services.RMSchemasRecordsServices;
import com.constellio.app.modules.rm.wrappers.RMTask;
import com.constellio.app.modules.tasks.services.TasksSchemasRecordsServices;
import com.constellio.model.services.migrations.ConstellioEIMConfigs;
import com.constellio.model.services.records.RecordServices;
import com.constellio.model.services.security.AuthorizationsServices;
import com.constellio.sdk.tests.ConstellioTest;
import com.constellio.sdk.tests.setups.Users;
public class RMNavigationAcceptanceTest extends ConstellioTest {
AuthorizationsServices authorizationsServices;
RecordServices recordServices;
Users users = new Users();
Session session;
RMSchemasRecordsServices rm;
RMTestRecords records = new RMTestRecords(zeCollection);
private final String PDF_MIMETYPE = "application/pdf";
private long pdf1Length = 170039L;
private long pdf2Length = 167347L;
private String pdf1Hash = "KN8RjbrnBgq1EDDV2U71a6/6gd4=";
private String pdf2Hash = "T+4zq4cGP/tXkdJp/qz1WVWYhoQ=";
@Before
public void setUp()
throws Exception {
prepareSystem(withZeCollection().withConstellioRMModule().withAllTest(users)
.withRMTest(records).withFoldersAndContainersOfEveryStatus()
.withDocumentsHavingContent());
recordServices = getModelLayerFactory().newRecordServices();
authorizationsServices = getModelLayerFactory().newAuthorizationsServices();
users.setUp(getModelLayerFactory().newUserServices());
recordServices.update(users.adminIn(zeCollection).setCollectionAllAccess(true));
recordServices.update(users.aliceIn(zeCollection).setCollectionReadAccess(true));
recordServices.update(users.chuckNorrisIn(zeCollection).setCollectionAllAccess(true));
recordServices.update(users.gandalfIn(zeCollection).setCollectionReadAccess(true).setCollectionWriteAccess(true));
givenConfig(ConstellioEIMConfigs.CMIS_NEVER_RETURN_ACL, false);
CmisAcceptanceTestSetup.giveUseCMISPermissionToUsers(getModelLayerFactory());
rm = new RMSchemasRecordsServices(zeCollection, getAppLayerFactory());
}
@Test
public void whenUserDoRequestsOnAFolderThenAllActionsLogged()
throws Exception {
clearLogs();
as(gandalf).session.getObject(records.folder_A02);
as(chuckNorris).session.getObjectByPath("/taxo_plan/categoryId_X/categoryId_X100/" + records.folder_C30);
as(admin).session.getBinding().getObjectService()
.getProperties(session.getRepositoryInfo().getId(), records.folder_A06, null, null);
recordServices.flush();
assertThatRecords(rm.searchEvents(ALL)).extracting("type", "username", "recordId").containsOnly(
tuple("view_folder", "gandalf", "A02"),
tuple("view_folder", "chuck", "C30"),
tuple("view_folder", "admin", "A06")
);
clearLogs();
as(gandalf).session.getObject(records.folder_A02).updateProperties(asMap("title", "newTitle1"))
.updateProperties(asMap("title", "newTitle2"));
MutableProperties properties = new PropertiesImpl();
as(chuckNorris).session.getObject(records.folder_C30).rename("newTitle3");
((Folder) as(admin).session.getObject(records.folder_A05))
.move(new ObjectIdImpl(records.unitId_10a), new ObjectIdImpl(records.unitId_20));
String newFolderId = ((Folder) as(gandalf).session.getObject(records.folder_A07)).createFolder(
asMap("title", "test", PropertyIds.OBJECT_TYPE_ID, "folder_default", "openingDate", Calendar.getInstance()))
.getId();
((Folder) as(chuckNorris).session.getObject(records.folder_A12)).deleteTree(true, UnfileObject.DELETE, true);
recordServices.flush();
List<String> documentsInA05 = getModelLayerFactory().newSearchServices().searchRecordIds(from(rm.document.schemaType())
.where(rm.document.folder()).isEqualTo(records.folder_A05));
assertThatRecords(rm.searchEvents(ALL)).extracting("type", "username", "recordId").contains(
tuple("view_folder", "gandalf", "A02"),
tuple("modify_folder", "gandalf", "A02"),
tuple("modify_folder", "gandalf", "A02"),
tuple("view_folder", "chuck", "C30"),
tuple("modify_folder", "chuck", "C30"),
tuple("view_folder", "admin", "A05"),
tuple("modify_folder", "admin", "A05"),
tuple("view_folder", "gandalf", "A07"),
tuple("view_folder", "chuck", "A12"),
tuple("delete_folder", "chuck", "A12"),
tuple("create_folder", "gandalf", newFolderId),
tuple("view_folder", "gandalf", newFolderId),
tuple("modify_document", "admin", documentsInA05.get(0)),
tuple("modify_document", "admin", documentsInA05.get(1)),
tuple("modify_document", "admin", documentsInA05.get(2))
);
}
@Test
public void whenUserDoRequestsOnADocumentThenAllActionsLogged()
throws Exception {
clearLogs();
String contentId = ((Folder) as(gandalf).session.getObject(records.document_B30)).getChildren().iterator().next().getId();
as(chuckNorris).session
.getObjectByPath("/taxo_plan/categoryId_X/categoryId_X100/" + records.folder_A49 + "/" + records.document_A49);
as(admin).session.getBinding().getObjectService().getProperties(zeCollection, records.document_A79, null, null);
as(aliceWonderland).session.getObject(contentId);
recordServices.flush();
assertThatRecords(rm.searchEvents(ALL)).extracting("type", "username", "recordId").containsOnly(
tuple("view_document", "gandalf", records.document_B30),
tuple("view_document", "chuck", records.document_A49),
tuple("view_document", "admin", records.document_A79),
tuple("view_document", "alice", records.document_B30)
);
clearLogs();
as(gandalf).session.getObject(records.document_B30).updateProperties(asMap("title", "newTitle1"))
.updateProperties(asMap("title", "newTitle2"));
MutableProperties properties = new PropertiesImpl();
((Folder) as(chuckNorris).session.getObject(records.document_B33)).deleteTree(true, UnfileObject.DELETE, true);
as(chuckNorris).session.getObject(records.document_A49).rename("newTitle3");
((Folder) as(admin).session.getObject(records.document_A79))
.move(new ObjectIdImpl(records.folder_A79), new ObjectIdImpl(records.folder_A80));
as(chuckNorris).session.getObject(contentId).delete();
String newDocumentId = ((Folder) as(gandalf).session.getObject(records.folder_A07))
.createFolder(asMap("title", "test", PropertyIds.OBJECT_TYPE_ID, "document_default")).getId();
Document contentA19 = (Document) ((Folder) as(chuckNorris).session.getObject(records.document_A19)).getChildren()
.iterator().next();
contentA19.checkOut();
contentA19.checkIn(false, new HashMap<String, Object>(), null, null);
contentA19 = (Document) ((Folder) as(gandalf).session.getObject(records.document_A19)).getChildren().iterator().next();
contentA19.checkOut();
contentA19.checkIn(false, new HashMap<String, Object>(), pdf2ContentStream(), null);
recordServices.flush();
assertThatRecords(rm.searchEvents(ALL)).extracting("type", "username", "recordId").containsOnly(
tuple("view_document", "gandalf", "docB30"),
tuple("modify_document", "gandalf", "docB30"),
tuple("modify_document", "gandalf", "docB30"),
tuple("modify_document", "chuck", "docB30"),
tuple("view_document", "chuck", "docB33"),
tuple("delete_document", "chuck", "docB33"),
tuple("view_document", "chuck", "docA49"),
tuple("modify_document", "chuck", "docA49"),
tuple("view_document", "admin", "docA79"),
tuple("modify_document", "admin", "docA79"),
tuple("view_folder", "gandalf", "A07"),
tuple("view_document", "chuck", "docB30"),
tuple("view_folder", "admin", "A80"),
tuple("view_document", "chuck", "docA19"),
tuple("borrow_document", "chuck", "docA19"),
tuple("return_document", "chuck", "docA19"),
tuple("modify_document", "chuck", "docA19"),
tuple("view_document", "gandalf", "docA19"),
tuple("borrow_document", "gandalf", "docA19"),
tuple("return_document", "gandalf", "docA19"),
tuple("modify_document", "gandalf", "docA19"),
tuple("create_document", "gandalf", newDocumentId),
tuple("view_document", "gandalf", newDocumentId)
);
}
private void clearLogs() {
SolrClient solrClient = getDataLayerFactory().getRecordsVaultServer().getNestedSolrServer();
try {
solrClient.deleteByQuery("schema_s:event_*");
solrClient.commit();
} catch (SolrServerException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Test
public void whenNavigatingInTaxonomiesThenOK()
throws Exception {
for (String user : asList(admin, aliceWonderland, chuckNorris, gandalf)) {
session = newCMISSessionAsUserInZeCollection(user);
Folder folder = session.getRootFolder();
assertThatChildrensOf(folder).describedAs("seen by " + user).containsOnly(
tuple("taxo_plan", "taxonomy", "Plan de classification"),
tuple("taxo_containers", "taxonomy", "Emplacements"),
tuple("taxo_admUnits", "taxonomy", "Unités administratives")
);
assertThatChildrensOf(folder("/taxo_plan")).describedAs("seen by " + user).containsOnly(
tuple("categoryId_Z", "category_default", "Ze category"),
tuple("categoryId_X", "category_default", "Xe category")
);
assertThatChildrensOf(folder("/taxo_plan/categoryId_X")).describedAs("seen by " + user).containsOnly(
tuple("categoryId_X100", "category_default", "X100"),
tuple("categoryId_X13", "category_default", "Agent Secreet")
);
assertThatChildrensOf(folder("/taxo_plan/categoryId_X/categoryId_X13")).describedAs("seen by " + user).isEmpty();
}
for (String user : asList(admin, aliceWonderland, chuckNorris)) {
as(user).assertThatChildrensOf(folder("/taxo_plan/categoryId_X/categoryId_X100")).containsOnly(
tuple("categoryId_X110", "category_default", "X110"),
tuple("categoryId_X120", "category_default", "X120"),
tuple("B06", "folder_default", "Framboise"),
tuple("C06", "folder_default", "Chou-fleur"),
tuple("A18", "folder_default", "Cheval"),
tuple("A16", "folder_default", "Chat"),
tuple("B32", "folder_default", "Pêche"),
tuple("A17", "folder_default", "Chauve-souris"),
tuple("C32", "folder_default", "Maïs")
);
}
as(gandalf).assertThatChildrensOf(folder("/taxo_plan/categoryId_X/categoryId_X100")).containsOnly(
tuple("categoryId_X110", "category_default", "X110"),
tuple("categoryId_X120", "category_default", "X120"),
tuple("B06", "folder_default", "Framboise"),
tuple("C06", "folder_default", "Chou-fleur"),
tuple("A18", "folder_default", "Cheval"),
tuple("A16", "folder_default", "Chat"),
tuple("B32", "folder_default", "Pêche"),
tuple("A17", "folder_default", "Chauve-souris"),
tuple("C32", "folder_default", "Maïs")
);
as(sasquatch).assertThatChildrensOf(folder("/taxo_plan/categoryId_X/categoryId_X100")).containsOnly(
tuple("categoryId_X110", "category_default", "X110"),
tuple("categoryId_X120", "category_default", "X120")
);
TasksSchemasRecordsServices tasks = new TasksSchemasRecordsServices(zeCollection, getAppLayerFactory());
recordServices.add(tasks.newTask().setTitle("Ze task").set(RMTask.ADMINISTRATIVE_UNIT, records.unitId_11b));
as(admin).assertThatChildrensOf(folder(records.unitId_11b)).containsOnly(
tuple("B31", "folder_default", "Orange"),
tuple("B01", "folder_default", "Abricot"),
tuple("B05", "folder_default", "Fraise"),
tuple("B09", "folder_default", "Melon"),
tuple("B07", "folder_default", "Kiwi"),
tuple("B03", "folder_default", "Citron")
);
}
@Test
public void whenGetObjectByIdThenOnlyWorkWithSupportedTypes()
throws Exception {
// try {
// as(admin).session.getObject(records.containerId_bac06);
// fail("Exception expected");
// } catch (CmisRuntimeException e) {
// assertThat(e.getMessage()).isEqualTo("todo");
// }
try {
as(admin).session.getObject(records.list_04);
fail("Exception expected");
} catch (CmisRuntimeException e) {
assertThat(e.getMessage()).isEqualTo("Unknown type: decommissioningList_default");
}
try {
as(admin).session.getObject(records.documentTypeId_4);
fail("Exception expected");
} catch (CmisRuntimeException e) {
assertThat(e.getMessage()).isEqualTo("Unknown type: ddvDocumentType_default");
}
try {
as(admin).session.getObject(records.ruleId_3);
fail("Exception expected");
} catch (CmisRuntimeException e) {
assertThat(e.getMessage()).isEqualTo("Unknown type: retentionRule_default");
}
try {
as(admin).session.getObject(records.subdivId_1);
fail("Exception expected");
} catch (CmisRuntimeException e) {
assertThat(e.getMessage()).isEqualTo("Unknown type: uniformSubdivision_default");
}
try {
as(admin).session.getObject(records.getAlice().getId());
fail("Exception expected");
} catch (CmisRuntimeException e) {
assertThat(e.getMessage()).isEqualTo("Unknown type: user_default");
}
try {
as(admin).session.getObject(records.getLegends().getId());
fail("Exception expected");
} catch (CmisRuntimeException e) {
assertThat(e.getMessage()).isEqualTo("Unknown type: group_default");
}
}
private Folder folder(String pathOrId) {
if (pathOrId.startsWith("/")) {
return (Folder) session.getObjectByPath(pathOrId);
} else {
return (Folder) session.getObject(pathOrId);
}
}
private RMNavigationAcceptanceTest as(String user) {
session = newCMISSessionAsUserInCollection(user, zeCollection);
return this;
}
private ContentStream pdf2ContentStream()
throws IOException {
String filename = "pdf2.pdf";
BigInteger length = BigInteger.valueOf(pdf2Length);
String mimetype = PDF_MIMETYPE;
InputStream stream = getTestResourceInputStream(CmisSinglevalueContentManagementAcceptTest.class, "pdf2.pdf");
return new ContentStreamImpl(filename, length, mimetype, stream);
}
private ListAssert<Tuple> assertThatChildrensOf(Folder folder) {
List<Tuple> tuples = new ArrayList<>();
for (Iterator<CmisObject> objectIterator = folder.getChildren().iterator(); objectIterator.hasNext(); ) {
CmisObject child = objectIterator.next();
Tuple tuple = new Tuple();
tuples.add(tuple);
tuple.addData(child.getId());
tuple.addData(child.getType().getId());
tuple.addData(child.getName());
}
return assertThat(tuples);
}
}