Search in sources :

Example 6 with FileSystemItemChange

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();
    }
}
Also used : StringBlob(org.nuxeo.ecm.core.api.impl.blob.StringBlob) FileSystemItemChange(org.nuxeo.drive.service.FileSystemItemChange) DocumentModel(org.nuxeo.ecm.core.api.DocumentModel) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 7 with FileSystemItemChange

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());
}
Also used : FileSystemChangeSummary(org.nuxeo.drive.service.FileSystemChangeSummary) StringBlob(org.nuxeo.ecm.core.api.impl.blob.StringBlob) FileSystemItemChange(org.nuxeo.drive.service.FileSystemItemChange) DocumentModel(org.nuxeo.ecm.core.api.DocumentModel) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 8 with FileSystemItemChange

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);
}
Also used : ACE(org.nuxeo.ecm.core.api.security.ACE) FileSystemItemChange(org.nuxeo.drive.service.FileSystemItemChange) DocumentModel(org.nuxeo.ecm.core.api.DocumentModel) Test(org.junit.Test)

Example 9 with FileSystemItemChange

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);
}
Also used : ACE(org.nuxeo.ecm.core.api.security.ACE) FileSystemItemChange(org.nuxeo.drive.service.FileSystemItemChange) DocumentModel(org.nuxeo.ecm.core.api.DocumentModel)

Example 10 with FileSystemItemChange

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;
}
Also used : DocumentRef(org.nuxeo.ecm.core.api.DocumentRef) ArrayList(java.util.ArrayList) SynchronizationRoots(org.nuxeo.drive.service.SynchronizationRoots) IdRef(org.nuxeo.ecm.core.api.IdRef) ExtendedInfo(org.nuxeo.ecm.platform.audit.api.ExtendedInfo) FileSystemItemChange(org.nuxeo.drive.service.FileSystemItemChange) TooManyChangesException(org.nuxeo.drive.service.TooManyChangesException) LogEntry(org.nuxeo.ecm.platform.audit.api.LogEntry) NuxeoDriveManager(org.nuxeo.drive.service.NuxeoDriveManager)

Aggregations

FileSystemItemChange (org.nuxeo.drive.service.FileSystemItemChange)30 Test (org.junit.Test)26 DocumentModel (org.nuxeo.ecm.core.api.DocumentModel)24 HashSet (java.util.HashSet)17 StringBlob (org.nuxeo.ecm.core.api.impl.blob.StringBlob)13 IdRef (org.nuxeo.ecm.core.api.IdRef)7 ACE (org.nuxeo.ecm.core.api.security.ACE)7 FileSystemChangeSummary (org.nuxeo.drive.service.FileSystemChangeSummary)6 Principal (java.security.Principal)5 ArrayList (java.util.ArrayList)3 SimpleFileSystemItemChange (org.nuxeo.drive.fixtures.SimpleFileSystemItemChange)2 SynchronizationRoots (org.nuxeo.drive.service.SynchronizationRoots)2 TooManyChangesException (org.nuxeo.drive.service.TooManyChangesException)2 DocumentRef (org.nuxeo.ecm.core.api.DocumentRef)2 NuxeoPrincipalImpl (org.nuxeo.ecm.platform.usermanager.NuxeoPrincipalImpl)2 HashMap (java.util.HashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 Map (java.util.Map)1 Set (java.util.Set)1 TreeSet (java.util.TreeSet)1