use of org.nuxeo.drive.service.FileSystemItemChange in project nuxeo-drive-server by nuxeo.
the class AuditChangeFinderTestSuite method testFolderishCollection.
/**
* <pre>
* /folder1 -> isMemberOf(collectionFolder)
* |-- collectionFolder
* /collectionSyncRoot -> synchronization root
* /testDoc -> isMemberOf(collectionFolder, collectionSyncRoot)
* </pre>
*/
@Test
public void testFolderishCollection() throws Exception {
DocumentModel collectionSyncRoot;
DocumentModel testDoc;
List<FileSystemItemChange> changes;
try {
log.trace("testFolderishCollection():" + "\nCreate a folder with the Collection facet (\"collectionFolder\") inside a folder (\"folder1\");" + "\nAdd \"folder1\" to the \"collectionFolder\" collection;" + "\nCreate a collection \"collectionSyncRoot\" and register it as a synchronization root;" + "\nCreate a document \"testDoc\" and add it to both collections \"collectionFolder\" and \"collectionSyncRoot\".\n");
DocumentModel collectionFolder = session.createDocumentModel("/folder1", "collectionFolder", "FolderishCollection");
collectionFolder = session.createDocument(collectionFolder);
collectionManager.addToCollection(collectionFolder, folder1, session);
collectionSyncRoot = collectionManager.createCollection(session, "collectionSyncRoot", null, "/");
nuxeoDriveManager.registerSynchronizationRoot(session.getPrincipal(), collectionSyncRoot, session);
testDoc = session.createDocumentModel("/", "testDoc", "File");
testDoc.setPropertyValue("file:content", new StringBlob("The content of testDoc."));
testDoc = session.createDocument(testDoc);
collectionManager.addToCollection(collectionFolder, testDoc, session);
collectionManager.addToCollection(collectionSyncRoot, testDoc, session);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
// Expecting 6 (among which 5 distinct) changes:
// - addedToCollection for testDoc
// - documentModified for collectionSyncRoot
// - addedToCollection for testDoc
// - documentCreated for testDoc
// - rootRegistered for collectionSyncRoot
// - documentCreated for collectionSyncRoot
changes = getChanges(session.getPrincipal());
assertEquals(6, changes.size());
Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
expectedChanges.add(new SimpleFileSystemItemChange(testDoc.getId(), "addedToCollection"));
expectedChanges.add(new SimpleFileSystemItemChange(collectionSyncRoot.getId(), "documentModified"));
expectedChanges.add(new SimpleFileSystemItemChange(testDoc.getId(), "documentCreated"));
expectedChanges.add(new SimpleFileSystemItemChange(collectionSyncRoot.getId(), "rootRegistered"));
expectedChanges.add(new SimpleFileSystemItemChange(collectionSyncRoot.getId(), "documentCreated"));
assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
} finally {
commitAndWaitForAsyncCompletion();
}
}
use of org.nuxeo.drive.service.FileSystemItemChange in project nuxeo-drive-server by nuxeo.
the class AuditChangeFinderTestSuite method testFindChanges.
@Test
public void testFindChanges() throws Exception {
List<FileSystemItemChange> changes;
DocumentModel doc1;
DocumentModel doc2;
DocumentModel doc3;
DocumentModel docToCopy;
DocumentModel copiedDoc;
DocumentModel docToVersion;
commitAndWaitForAsyncCompletion();
try {
// No sync roots
changes = getChanges();
assertNotNull(changes);
assertTrue(changes.isEmpty());
log.trace("Sync roots for Administrator");
nuxeoDriveManager.registerSynchronizationRoot(session.getPrincipal(), folder1, session);
nuxeoDriveManager.registerSynchronizationRoot(session.getPrincipal(), folder2, session);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
// Get changes for Administrator
changes = getChanges();
// Root registration events
assertEquals(2, changes.size());
log.trace("Create 3 documents, only 2 in sync roots");
doc1 = session.createDocumentModel("/folder1", "doc1", "File");
doc1.setPropertyValue("file:content", new StringBlob("The content of file 1."));
doc1 = session.createDocument(doc1);
doc2 = session.createDocumentModel("/folder2", "doc2", "File");
doc2.setPropertyValue("file:content", new StringBlob("The content of file 2."));
doc2 = session.createDocument(doc2);
doc3 = session.createDocumentModel("/folder3", "doc3", "File");
doc3.setPropertyValue("file:content", new StringBlob("The content of file 3."));
doc3 = session.createDocument(doc3);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(2, changes.size());
Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
expectedChanges.add(new SimpleFileSystemItemChange(doc2.getId(), "documentCreated", "test"));
expectedChanges.add(new SimpleFileSystemItemChange(doc1.getId(), "documentCreated", "test"));
assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
// No changes since last successful sync
changes = getChanges();
assertTrue(changes.isEmpty());
log.trace("Update both synchronized documents and unsynchronize a root");
doc1.setPropertyValue("file:content", new StringBlob("The content of file 1, updated."));
session.saveDocument(doc1);
doc2.setPropertyValue("file:content", new StringBlob("The content of file 2, updated."));
session.saveDocument(doc2);
nuxeoDriveManager.unregisterSynchronizationRoot(session.getPrincipal(), folder2, session);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(2, changes.size());
// The root unregistration is mapped to a fake deletion from the
// client's point of view
Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
expectedChanges.add(new SimpleFileSystemItemChange(folder2.getId(), "deleted", "test"));
expectedChanges.add(new SimpleFileSystemItemChange(doc1.getId(), "documentModified", "test"));
assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
log.trace("Delete a document with a lifecycle transition (trash)");
session.followTransition(doc1.getRef(), "delete");
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(1, changes.size());
assertEquals(new SimpleFileSystemItemChange(doc1.getId(), "deleted", "test", "test#" + doc1.getId()), toSimpleFileSystemItemChange(changes.get(0)));
log.trace("Restore a deleted document and move a document in a newly synchronized root");
session.followTransition(doc1.getRef(), "undelete");
session.move(doc3.getRef(), folder2.getRef(), null);
nuxeoDriveManager.registerSynchronizationRoot(session.getPrincipal(), folder2, session);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(3, changes.size());
Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
expectedChanges.add(new SimpleFileSystemItemChange(folder2.getId(), "rootRegistered", "test", "defaultSyncRootFolderItemFactory#test#" + folder2.getId()));
expectedChanges.add(new SimpleFileSystemItemChange(doc3.getId(), "documentMoved", "test"));
expectedChanges.add(new SimpleFileSystemItemChange(doc1.getId(), "lifecycle_transition_event", "test"));
assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
log.trace("Physical deletion without triggering the delete transition first");
session.removeDocument(doc3.getRef());
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(1, changes.size());
assertEquals(new SimpleFileSystemItemChange(doc3.getId(), "deleted", "test", "test#" + doc3.getId()), toSimpleFileSystemItemChange(changes.get(0)));
log.trace("Create a doc and copy it from a sync root to another one");
docToCopy = session.createDocumentModel("/folder1", "docToCopy", "File");
docToCopy.setPropertyValue("file:content", new StringBlob("The content of file to copy."));
docToCopy = session.createDocument(docToCopy);
copiedDoc = session.copy(docToCopy.getRef(), folder2.getRef(), null);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(2, changes.size());
Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
expectedChanges.add(new SimpleFileSystemItemChange(copiedDoc.getId(), "documentCreatedByCopy", "test", "defaultFileSystemItemFactory#test#" + copiedDoc.getId(), "docToCopy"));
expectedChanges.add(new SimpleFileSystemItemChange(docToCopy.getId(), "documentCreated", "test", "defaultFileSystemItemFactory#test#" + docToCopy.getId(), "docToCopy"));
assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
log.trace("Remove file from a document, mapped to a fake deletion from the client's point of view");
doc1.setPropertyValue("file:content", null);
session.saveDocument(doc1);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(1, changes.size());
assertEquals(new SimpleFileSystemItemChange(doc1.getId(), "deleted", "test"), toSimpleFileSystemItemChange(changes.get(0)));
log.trace("Move a doc from a sync root to another sync root");
session.move(copiedDoc.getRef(), folder1.getRef(), null);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(1, changes.size());
assertEquals(new SimpleFileSystemItemChange(copiedDoc.getId(), "documentMoved", "test"), toSimpleFileSystemItemChange(changes.get(0)));
log.trace("Move a doc from a sync root to a non synchronized folder");
session.move(copiedDoc.getRef(), folder3.getRef(), null);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
assertEquals(1, changes.size());
assertEquals(new SimpleFileSystemItemChange(copiedDoc.getId(), "deleted", "test"), toSimpleFileSystemItemChange(changes.get(0)));
log.trace("Create a doc, create a version of it, update doc and restore the version");
docToVersion = session.createDocumentModel("/folder1", "docToVersion", "File");
docToVersion.setPropertyValue("file:content", new StringBlob("The content of file to version."));
docToVersion = session.createDocument(docToVersion);
docToVersion.putContextData(VersioningService.VERSIONING_OPTION, VersioningOption.MAJOR);
session.saveDocument(docToVersion);
docToVersion.setPropertyValue("file:content", new StringBlob("Updated content of the versioned file."));
session.saveDocument(docToVersion);
List<DocumentModel> versions = session.getVersions(docToVersion.getRef());
assertEquals(1, versions.size());
DocumentModel version = versions.get(0);
session.restoreToVersion(docToVersion.getRef(), version.getRef());
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges();
// Expecting 4 (among which 3 distinct) changes:
// - documentRestored for docToVersion
// - documentModified for docToVersion (2 occurrences)
// - documentCreated for docToVersion
assertEquals(4, changes.size());
Set<SimpleFileSystemItemChange> expectedChanges = new HashSet<>();
expectedChanges.add(new SimpleFileSystemItemChange(docToVersion.getId(), "documentRestored"));
expectedChanges.add(new SimpleFileSystemItemChange(docToVersion.getId(), "documentModified"));
expectedChanges.add(new SimpleFileSystemItemChange(docToVersion.getId(), "documentCreated"));
assertTrue(CollectionUtils.isEqualCollection(expectedChanges, toSimpleFileSystemItemChanges(changes)));
log.trace("Too many changes");
session.followTransition(doc1.getRef(), "delete");
session.followTransition(doc2.getRef(), "delete");
} finally {
commitAndWaitForAsyncCompletion();
}
Framework.getProperties().put("org.nuxeo.drive.document.change.limit", "1");
FileSystemChangeSummary changeSummary = getChangeSummary(session.getPrincipal());
assertEquals(true, changeSummary.getHasTooManyChanges());
}
use of org.nuxeo.drive.service.FileSystemItemChange in project nuxeo-drive-server by nuxeo.
the class GroupChangesTestSuite method testGroupChangesOnSyncRootParent.
/**
* Tests changes on a group that has access to the parent of a synchronization root.
*/
@Test
public void testGroupChangesOnSyncRootParent() throws Exception {
DocumentModel syncRoot;
try {
DocumentModel parent = session.createDocument(session.createDocumentModel("/", "parent", "Folder"));
syncRoot = session.createDocument(session.createDocumentModel("/parent", "syncRoot", "Folder"));
log.trace("Grant ReadWrite to group1 on parent");
setPermissions(parent, new ACE("group1", SecurityConstants.READ_WRITE));
nuxeoDriveManager.registerSynchronizationRoot(userSession.getPrincipal(), syncRoot, userSession);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
List<FileSystemItemChange> changes = getChanges(userSession.getPrincipal());
// Sync root creation and registration events
assertEquals(2, changes.size());
} finally {
commitAndWaitForAsyncCompletion();
}
testGroupChanges(syncRoot, "defaultSyncRootFolderItemFactory", "group1", false);
}
use of org.nuxeo.drive.service.FileSystemItemChange in project nuxeo-drive-server by nuxeo.
the class GroupChangesTestSuite method testGroupChangesWithAncestorGroups.
/**
* Tests changes on a descendant group of the given group that has access to a synchronization root.
*/
protected void testGroupChangesWithAncestorGroups(String ancestorGroup) throws Exception {
List<FileSystemItemChange> changes;
DocumentModel syncRoot;
try {
syncRoot = session.createDocument(session.createDocumentModel("/", "syncRoot", "Folder"));
log.trace("Grant ReadWrite to " + ancestorGroup + " on syncRoot");
setPermissions(syncRoot, new ACE(ancestorGroup, SecurityConstants.READ_WRITE));
nuxeoDriveManager.registerSynchronizationRoot(userSession.getPrincipal(), syncRoot, userSession);
} finally {
commitAndWaitForAsyncCompletion();
}
try {
changes = getChanges(userSession.getPrincipal());
// Sync root creation and registration events
assertEquals(2, changes.size());
} finally {
commitAndWaitForAsyncCompletion();
}
testGroupChanges(syncRoot, "defaultSyncRootFolderItemFactory", "group1", true);
}
use of org.nuxeo.drive.service.FileSystemItemChange in project nuxeo-drive-server by nuxeo.
the class AuditChangeFinder method getFileSystemChanges.
protected List<FileSystemItemChange> getFileSystemChanges(CoreSession session, Set<IdRef> lastActiveRootRefs, SynchronizationRoots activeRoots, Set<String> collectionSyncRootMemberIds, long lowerBound, long upperBound, boolean integerBounds, int limit) throws TooManyChangesException {
String principalName = session.getPrincipal().getName();
List<FileSystemItemChange> changes = new ArrayList<FileSystemItemChange>();
// Note: lastActiveRootRefs is not used: we could remove it from the
// public API
// and from the client as well but it might be useful to optimize future
// alternative implementations FileSystemChangeFinder component so it
// might
// be better to leave it part of the public API as currently.
// Find changes from the log under active roots or events that are
// linked to the un-registration or deletion of formerly synchronized
// roots
List<LogEntry> entries = queryAuditEntries(session, activeRoots, collectionSyncRootMemberIds, lowerBound, upperBound, integerBounds, limit);
// query with the actual active roots.
for (LogEntry entry : entries) {
if (NuxeoDriveEvents.EVENT_CATEGORY.equals(entry.getCategory())) {
if (log.isDebugEnabled()) {
log.debug(String.format("Detected sync root change for user '%s' in audit log:" + " invalidating the root cache and refetching the changes.", principalName));
}
NuxeoDriveManager driveManager = Framework.getService(NuxeoDriveManager.class);
driveManager.invalidateSynchronizationRootsCache(principalName);
driveManager.invalidateCollectionSyncRootMemberCache(principalName);
Map<String, SynchronizationRoots> synchronizationRoots = driveManager.getSynchronizationRoots(session.getPrincipal());
SynchronizationRoots updatedActiveRoots = synchronizationRoots.get(session.getRepositoryName());
Set<String> updatedCollectionSyncRootMemberIds = driveManager.getCollectionSyncRootMemberIds(session.getPrincipal()).get(session.getRepositoryName());
entries = queryAuditEntries(session, updatedActiveRoots, updatedCollectionSyncRootMemberIds, lowerBound, upperBound, integerBounds, limit);
break;
}
}
if (entries.size() >= limit) {
throw new TooManyChangesException("Too many changes found in the audit logs.");
}
for (LogEntry entry : entries) {
if (log.isDebugEnabled()) {
log.debug(String.format("Handling log entry %s", entry));
}
FileSystemItemChange change = null;
DocumentRef docRef = new IdRef(entry.getDocUUID());
ExtendedInfo fsIdInfo = entry.getExtendedInfos().get("fileSystemItemId");
if (fsIdInfo != null) {
// been updated, we just know the FileSystemItem id and name.
if (log.isDebugEnabled()) {
log.debug(String.format("Found extended info in audit log entry: document has been deleted, moved," + " is an unregistered synchronization root or its security has been updated," + " we just know the FileSystemItem id and name."));
}
boolean isChangeSet = false;
// current user still has access to the document.
if (!"deleted".equals(entry.getEventId()) && session.exists(docRef)) {
change = getFileSystemItemChange(session, docRef, entry, fsIdInfo.getValue(String.class));
if (change != null) {
if (NuxeoDriveEvents.MOVED_EVENT.equals(entry.getEventId())) {
// virtual event.
if (log.isDebugEnabled()) {
log.debug(String.format("Document %s (%s) has been moved to another synchronzation root, not adding entry to the change summary.", entry.getDocPath(), docRef));
}
continue;
}
isChangeSet = true;
}
}
if (!isChangeSet) {
// FileSystemItem id and name to the FileSystemItemChange entry.
if (log.isDebugEnabled()) {
log.debug(String.format("Document %s (%s) doesn't exist or is not adaptable as a FileSystemItem, only providing the FileSystemItem id and name to the FileSystemItemChange entry.", entry.getDocPath(), docRef));
}
String fsId = fsIdInfo.getValue(String.class);
String eventId;
if (NuxeoDriveEvents.MOVED_EVENT.equals(entry.getEventId())) {
// Move to a non synchronization root
eventId = NuxeoDriveEvents.DELETED_EVENT;
} else {
// Deletion, unregistration or security update
eventId = entry.getEventId();
}
change = new FileSystemItemChangeImpl(eventId, entry.getEventDate().getTime(), entry.getRepositoryId(), entry.getDocUUID(), fsId, null);
}
if (log.isDebugEnabled()) {
log.debug(String.format("Adding FileSystemItemChange entry to the change summary: %s", change));
}
changes.add(change);
} else {
// unregistered synchronization root nor a security update denying access to the current user.
if (log.isDebugEnabled()) {
log.debug(String.format("No extended info found in audit log entry %s (%s): this is not a deleted document, a moved document," + " an unregistered synchronization root nor a security update denying access to the current user.", entry.getDocPath(), docRef));
}
if (!session.exists(docRef)) {
if (log.isDebugEnabled()) {
log.debug(String.format("Document %s (%s) doesn't exist, not adding entry to the change summary.", entry.getDocPath(), docRef));
}
// try to propagate this event.
continue;
}
// Let's try to adapt the document as a FileSystemItem to
// provide it to the FileSystemItemChange entry.
change = getFileSystemItemChange(session, docRef, entry, null);
if (change == null) {
// Non-adaptable documents are ignored
if (log.isDebugEnabled()) {
log.debug(String.format("Document %s (%s) is not adaptable as a FileSystemItem, not adding any entry to the change summary.", entry.getDocPath(), docRef));
}
} else {
if (log.isDebugEnabled()) {
log.debug(String.format("Adding FileSystemItemChange entry to the change summary: %s", change));
}
changes.add(change);
}
}
}
return changes;
}
Aggregations