package org.exist.storage;
import org.easymock.Capture;
import org.easymock.EasyMock;
import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import org.exist.collections.Collection;
import org.exist.dom.DocumentImpl;
import org.exist.security.Permission;
import org.exist.security.PermissionDeniedException;
import org.exist.security.Subject;
import org.exist.util.LockException;
import org.exist.xmldb.XmldbURI;
import org.junit.Ignore;
import org.junit.Test;
import java.util.*;
import static org.junit.Assert.assertEquals;
public class NativeBrokerTest {
/**
* When copying a Collection (/db/test/source) where
* we have execute+read access and
* which has no descendant documents or collections in it
* to the destination /db/test/dest (which does not already exist)
* and we have execute+write access on /db/test
* we should be allowed to copy the Collection.
*/
@Test
public void copyCollection_noDescendants_toNonExistingDest_canWriteDest() throws LockException, PermissionDeniedException {
final XmldbURI src = XmldbURI.create("/db/test/source");
final XmldbURI dest = XmldbURI.create("/db/test");
final XmldbURI newName = XmldbURI.create("dest");
final Collection srcCollection = EasyMock.createStrictMock(Collection.class);
final Permission srcPermissions = EasyMock.createStrictMock(Permission.class);
final Collection destCollection = EasyMock.createStrictMock(Collection.class);
final Permission destPermissions = EasyMock.createStrictMock(Permission.class);
final Collection newDestCollection = null;
final NativeBroker broker = EasyMock.createMockBuilder(NativeBroker.class)
.addMockedMethod("getCollection")
.addMockedMethod("getSubject")
.createStrictMock();
final Subject subject = EasyMock.createStrictMock(Subject.class);
//grant EXECUTE and READ permissions on the src
expect(srcCollection.getPermissionsNoLock()).andReturn(srcPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcPermissions.validate(subject, Permission.EXECUTE | Permission.READ)).andReturn(true);
//grant EXECUTE and WRITE permission on the dest
expect(broker.getCollection(dest)).andReturn(destCollection);
final Capture<XmldbURI> newDestURICapture = new Capture<XmldbURI>();
expect(broker.getCollection(capture(newDestURICapture))).andReturn(newDestCollection);
expect(destCollection.getPermissionsNoLock()).andReturn(destPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(destPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(true);
//no sub-documents
expect(srcCollection.iterator(broker)).andReturn(new EmptyIterator<DocumentImpl>());
//no sub-collections
expect(srcCollection.collectionIterator(broker)).andReturn(new EmptyIterator<XmldbURI>());
//test below
replay(destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
//run the test
broker.checkPermissionsForCopy(srcCollection, dest, newName);
verify(destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
assertEquals(dest.append(newName), newDestURICapture.getValue());
}
/**
* When copying a Collection (/db/test/source) where
* we have execute+read access and
* which has no descendant documents or collections in it,
*
* to the destination /db/test/dest (which does not already exist)
* and we DO NOT have execute+write access on /db/test
* we should NOT be allowed to copy the Collection.
*/
@Test(expected = PermissionDeniedException.class)
public void copyCollection_noDescendants_toNonExistingDest_cannotWriteDest() throws LockException, PermissionDeniedException {
final XmldbURI src = XmldbURI.create("/db/test/source");
final XmldbURI dest = XmldbURI.create("/db/test");
final XmldbURI newName = XmldbURI.create("dest");
final Collection srcCollection = EasyMock.createStrictMock(Collection.class);
final Permission srcPermissions = EasyMock.createStrictMock(Permission.class);
final Collection destCollection = EasyMock.createStrictMock(Collection.class);
final Permission destPermissions = EasyMock.createStrictMock(Permission.class);
final Collection newDestCollection = null; //EasyMock.createMock(Collection.class);
final NativeBroker broker = EasyMock.createMockBuilder(NativeBroker.class)
.addMockedMethod("getCollection")
.addMockedMethod("getSubject")
.createStrictMock();
final Subject subject = EasyMock.createStrictMock(Subject.class);
//grant EXECUTE and READ permissions on the src
expect(srcCollection.getPermissionsNoLock()).andReturn(srcPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcPermissions.validate(subject, Permission.EXECUTE | Permission.READ)).andReturn(true);
//grant EXECUTE and WRITE permission on the dest
expect(broker.getCollection(dest)).andReturn(destCollection);
final Capture<XmldbURI> newDestURICapture = new Capture<XmldbURI>();
expect(broker.getCollection(capture(newDestURICapture))).andReturn(newDestCollection);
expect(destCollection.getPermissionsNoLock()).andReturn(destPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(destPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(false);
//expectations for exception that should be thrown
expect(srcCollection.getURI()).andReturn(src);
expect(destCollection.getURI()).andReturn(dest);
expect(broker.getSubject()).andReturn(subject);
expect(subject.getName()).andReturn("Fake user");
//test below
replay(subject, destCollection, destPermissions, srcCollection, srcPermissions, broker);
//run the test
broker.checkPermissionsForCopy(srcCollection, dest, newName);
//not actually called, but here for showing intention
verify(subject, destCollection, destPermissions, srcCollection, srcPermissions, broker);
}
/**
* When copying a Collection (/db/test/source) where
* we have execute+read access and
* which has one descendant document (on which we have read access)
* in it,
*
* to the destination /db/test/dest (which does not already exist)
* and we have execute+write access on /db/test
* we should be allowed to copy the Collection.
*/
@Test
public void copyCollection_oneSubDoc_toNonExistingDest_canWriteDest() throws LockException, PermissionDeniedException {
final XmldbURI src = XmldbURI.create("/db/test/source");
final XmldbURI dest = XmldbURI.create("/db/test");
final XmldbURI newName = XmldbURI.create("dest");
final Collection srcCollection = EasyMock.createStrictMock(Collection.class);
final Permission srcPermissions = EasyMock.createStrictMock(Permission.class);
final DocumentImpl srcSubDocument = EasyMock.createStrictMock(DocumentImpl.class);
final Permission srcSubDocumentPermissions = EasyMock.createStrictMock(Permission.class);
final Collection destCollection = EasyMock.createStrictMock(Collection.class);
final Permission destPermissions = EasyMock.createStrictMock(Permission.class);
final Collection newDestCollection = null;
final NativeBroker broker = EasyMock.createMockBuilder(NativeBroker.class)
.addMockedMethod("getCollection")
.addMockedMethod("getSubject")
.createStrictMock();
final Subject subject = EasyMock.createStrictMock(Subject.class);
//grant EXECUTE and READ permissions on the src
expect(srcCollection.getPermissionsNoLock()).andReturn(srcPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcPermissions.validate(subject, Permission.EXECUTE | Permission.READ)).andReturn(true);
//grant EXECUTE and WRITE permission on the dest
expect(broker.getCollection(dest)).andReturn(destCollection);
final Capture<XmldbURI> newDestURICapture = new Capture<XmldbURI>();
expect(broker.getCollection(capture(newDestURICapture))).andReturn(newDestCollection);
expect(destCollection.getPermissionsNoLock()).andReturn(destPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(destPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(true);
//one sub-document with READ permission
expect(srcCollection.iterator(broker)).andReturn(new ArrayIterator<DocumentImpl>(srcSubDocument));
expect(srcSubDocument.getPermissions()).andReturn(srcSubDocumentPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcSubDocumentPermissions.validate(subject, Permission.READ)).andReturn(true);
//no sub-collections
expect(srcCollection.collectionIterator(broker)).andReturn(new EmptyIterator<XmldbURI>());
//test below
replay(srcSubDocumentPermissions, srcSubDocument, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
//run the test
broker.checkPermissionsForCopy(srcCollection, dest, newName);
verify(srcSubDocumentPermissions, srcSubDocument, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
assertEquals(dest.append(newName), newDestURICapture.getValue());
}
/**
* When copying a Collection (/db/test/source) where
* we have execute+read access and
* which has one descendant document (on which we have read access)
* and one descendant collection (on which we have read+execute access) in it,
*
* to the destination /db/test/dest (which does not already exist)
* and we have execute+write access on /db/test
* we should be allowed to copy the Collection.
*/
@Ignore
@Test
public void copyCollection_oneSubDoc_oneSubColl_toNonExistingDest_canWriteDest() throws LockException, PermissionDeniedException {
final XmldbURI src = XmldbURI.create("/db/test/source");
final XmldbURI dest = XmldbURI.create("/db/test");
final XmldbURI newName = XmldbURI.create("dest");
final Collection srcCollection = EasyMock.createStrictMock(Collection.class);
final Permission srcPermissions = EasyMock.createStrictMock(Permission.class);
final DocumentImpl srcSubDocument = EasyMock.createStrictMock(DocumentImpl.class);
final Permission srcSubDocumentPermissions = EasyMock.createStrictMock(Permission.class);
final XmldbURI srcSubCollectionName = XmldbURI.create("sub-collection");
final XmldbURI srcSubCollectionUri = src.append(srcSubCollectionName);
final Collection srcSubCollection = EasyMock.createStrictMock(Collection.class);
final Permission srcSubCollectionPermissions = EasyMock.createStrictMock(Permission.class);
final Collection destCollection = EasyMock.createStrictMock(Collection.class);
final Permission destPermissions = EasyMock.createStrictMock(Permission.class);
final Collection newDestCollection = null;
final NativeBroker broker = EasyMock.createMockBuilder(NativeBroker.class)
.addMockedMethod("getCollection")
.addMockedMethod("getSubject")
.createStrictMock();
final Subject subject = EasyMock.createStrictMock(Subject.class);
//grant EXECUTE and READ permissions on the src
expect(srcCollection.getPermissionsNoLock()).andReturn(srcPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcPermissions.validate(subject, Permission.EXECUTE | Permission.READ)).andReturn(true);
//grant EXECUTE and WRITE permission on the dest
expect(broker.getCollection(dest)).andReturn(destCollection);
final Capture<XmldbURI> newDestURICapture = new Capture<XmldbURI>();
expect(broker.getCollection(capture(newDestURICapture))).andReturn(newDestCollection);
expect(destCollection.getPermissionsNoLock()).andReturn(destPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(destPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(true);
//one sub-document with READ permission
expect(srcCollection.iterator(broker)).andReturn(new ArrayIterator<DocumentImpl>(srcSubDocument));
expect(srcSubDocument.getPermissions()).andReturn(srcSubDocumentPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcSubDocumentPermissions.validate(subject, Permission.READ)).andReturn(true);
//one sub-collection with READ and EXECUTE permission
expect(srcCollection.collectionIterator(broker)).andReturn(new ArrayIterator<XmldbURI>(srcSubCollectionName));
expect(srcCollection.getURI()).andReturn(src); //TODO fix?!? .once() .anyTimes() .times(2)
expect(src.append(srcSubCollectionName)).andReturn(srcSubCollectionUri);
expect(broker.getCollection(srcSubCollectionUri)).andReturn(srcSubCollection);
/* we are now recursing on the sub-collection */
expect(srcSubCollection.getPermissionsNoLock()).andReturn(srcSubCollectionPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcSubCollectionPermissions.validate(subject, Permission.EXECUTE | Permission.READ)).andReturn(true);
expect(broker.getCollection(dest.append(newName))).andReturn(null); //no such dest collection, so return null
expect(broker.getCollection(dest.append(newName).append(srcSubCollectionName))).andReturn(null); //no such dest sub-collection, so return null
expect(srcSubCollection.iterator(broker)).andReturn(new EmptyIterator<DocumentImpl>()); //no sub-sub-docs
expect(srcSubCollection.collectionIterator(broker)).andReturn(new EmptyIterator<XmldbURI>()); //no sub-sub-collections
//test below
replay(srcSubCollectionPermissions, srcSubCollection, srcSubDocumentPermissions, srcSubDocument, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
//run the test
broker.checkPermissionsForCopy(srcCollection, dest, newName);
verify(srcSubCollectionPermissions, srcSubCollection, srcSubDocumentPermissions, srcSubDocument, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
assertEquals(dest.append(newName), newDestURICapture.getValue());
}
/**
* When copying an empty Collection (/db/test/source) where
* we have execute+read access
*
* to the destination /db/test/dest (which already exists)
* and we have execute+write access on /db/test and /db/test/dest
* we should be allowed to copy the content of the Collection.
*/
@Test
public void copyCollection_noDescendants_toExistingDest_canWriteDest() throws LockException, PermissionDeniedException {
final XmldbURI src = XmldbURI.create("/db/test/source");
final XmldbURI dest = XmldbURI.create("/db/test");
final XmldbURI newName = XmldbURI.create("dest");
final Collection srcCollection = EasyMock.createStrictMock(Collection.class);
final Permission srcPermissions = EasyMock.createStrictMock(Permission.class);
final Collection destCollection = EasyMock.createStrictMock(Collection.class);
final Permission destPermissions = EasyMock.createStrictMock(Permission.class);
final Collection newDestCollection = EasyMock.createStrictMock(Collection.class);
final Permission newDestPermissions = EasyMock.createStrictMock(Permission.class);
final NativeBroker broker = EasyMock.createMockBuilder(NativeBroker.class)
.addMockedMethod("getCollection")
.addMockedMethod("getSubject")
.createStrictMock();
final Subject subject = EasyMock.createStrictMock(Subject.class);
//grant EXECUTE and READ permissions on the src
expect(srcCollection.getPermissionsNoLock()).andReturn(srcPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcPermissions.validate(subject, Permission.EXECUTE | Permission.READ)).andReturn(true);
//grant EXECUTE and WRITE permission on the dest
expect(broker.getCollection(dest)).andReturn(destCollection);
final Capture<XmldbURI> newDestURICapture = new Capture<XmldbURI>();
expect(broker.getCollection(capture(newDestURICapture))).andReturn(newDestCollection);
expect(destCollection.getPermissionsNoLock()).andReturn(destPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(destPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(true);
expect(newDestCollection.getPermissionsNoLock()).andReturn(newDestPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(newDestPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(true);
//no sub-documents
expect(srcCollection.iterator(broker)).andReturn(new EmptyIterator<DocumentImpl>());
//no sub-collections
expect(srcCollection.collectionIterator(broker)).andReturn(new EmptyIterator<XmldbURI>());
//test below
replay(newDestPermissions, newDestCollection, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
//run the test
broker.checkPermissionsForCopy(srcCollection, dest, newName);
verify(newDestPermissions, newDestCollection, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
assertEquals(dest.append(newName), newDestURICapture.getValue());
}
/**
* When copying an empty Collection (/db/test/source) where
* we have execute+read access
*
* to the destination /db/test/dest (which already exists)
* and we DO NOT have execute+write access on /db/test
* we should NOT be allowed to copy the content of the Collection.
*/
@Test(expected = PermissionDeniedException.class)
public void copyCollection_noDescendants_toExistingDest_cannotWriteDest() throws LockException, PermissionDeniedException {
final XmldbURI src = XmldbURI.create("/db/test/source");
final XmldbURI dest = XmldbURI.create("/db/test");
final XmldbURI newName = XmldbURI.create("dest");
final Collection srcCollection = EasyMock.createStrictMock(Collection.class);
final Permission srcPermissions = EasyMock.createStrictMock(Permission.class);
final Collection destCollection = EasyMock.createStrictMock(Collection.class);
final Permission destPermissions = EasyMock.createStrictMock(Permission.class);
final Collection newDestCollection = EasyMock.createStrictMock(Collection.class);
final Permission newDestPermissions = EasyMock.createStrictMock(Permission.class);
final NativeBroker broker = EasyMock.createMockBuilder(NativeBroker.class)
.addMockedMethod("getCollection")
.addMockedMethod("getSubject")
.createStrictMock();
final Subject subject = EasyMock.createStrictMock(Subject.class);
//grant EXECUTE and READ permissions on the src
expect(srcCollection.getPermissionsNoLock()).andReturn(srcPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcPermissions.validate(subject, Permission.EXECUTE | Permission.READ)).andReturn(true);
//grant EXECUTE and WRITE permission on the dest
expect(broker.getCollection(dest)).andReturn(destCollection);
final Capture<XmldbURI> newDestURICapture = new Capture<XmldbURI>();
expect(broker.getCollection(capture(newDestURICapture))).andReturn(newDestCollection);
expect(destCollection.getPermissionsNoLock()).andReturn(destPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(destPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(false);
//expectations for exception that should be thrown
expect(srcCollection.getURI()).andReturn(src);
expect(destCollection.getURI()).andReturn(dest);
expect(broker.getSubject()).andReturn(subject);
expect(subject.getName()).andReturn("Fake user");
//no sub-documents
expect(srcCollection.iterator(broker)).andReturn(new EmptyIterator<DocumentImpl>());
//no sub-collections
expect(srcCollection.collectionIterator(broker)).andReturn(new EmptyIterator<XmldbURI>());
//test below
replay(newDestPermissions, newDestCollection, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
//run the test
broker.checkPermissionsForCopy(srcCollection, dest, newName);
verify(newDestPermissions, newDestCollection, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
assertEquals(dest.append(newName), newDestURICapture.getValue());
}
/**
* When copying an empty Collection (/db/test/source) where
* we have execute+read access
*
* to the destination /db/test/dest (which already exists)
* and we have execute+write access on /db/test
* but DO NOT have execute+write access on /db/test/dest
* we should NOT be allowed to copy the content of the Collection.
*/
@Test(expected = PermissionDeniedException.class)
public void copyCollection_noDescendants_toExistingDest_cannotWriteNewDest() throws LockException, PermissionDeniedException {
final XmldbURI src = XmldbURI.create("/db/test/source");
final XmldbURI dest = XmldbURI.create("/db/test");
final XmldbURI newName = XmldbURI.create("dest");
final Collection srcCollection = EasyMock.createStrictMock(Collection.class);
final Permission srcPermissions = EasyMock.createStrictMock(Permission.class);
final Collection destCollection = EasyMock.createStrictMock(Collection.class);
final Permission destPermissions = EasyMock.createStrictMock(Permission.class);
final Collection newDestCollection = EasyMock.createStrictMock(Collection.class);
final Permission newDestPermissions = EasyMock.createStrictMock(Permission.class);
final NativeBroker broker = EasyMock.createMockBuilder(NativeBroker.class)
.addMockedMethod("getCollection")
.addMockedMethod("getSubject")
.createStrictMock();
final Subject subject = EasyMock.createStrictMock(Subject.class);
//grant EXECUTE and READ permissions on the src
expect(srcCollection.getPermissionsNoLock()).andReturn(srcPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcPermissions.validate(subject, Permission.EXECUTE | Permission.READ)).andReturn(true);
//grant EXECUTE and WRITE permission on the dest
expect(broker.getCollection(dest)).andReturn(destCollection);
final Capture<XmldbURI> newDestURICapture = new Capture<XmldbURI>();
expect(broker.getCollection(capture(newDestURICapture))).andReturn(newDestCollection);
expect(destCollection.getPermissionsNoLock()).andReturn(destPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(destPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(true);
expect(newDestCollection.getPermissionsNoLock()).andReturn(newDestPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(newDestPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(false);
//expectations for exception that should be thrown
expect(srcCollection.getURI()).andReturn(src);
expect(newDestCollection.getURI()).andReturn(dest.append(newName));
expect(broker.getSubject()).andReturn(subject);
expect(subject.getName()).andReturn("Fake user");
//no sub-documents
expect(srcCollection.iterator(broker)).andReturn(new EmptyIterator<DocumentImpl>());
//no sub-collections
expect(srcCollection.collectionIterator(broker)).andReturn(new EmptyIterator<XmldbURI>());
//test below
replay(newDestPermissions, newDestCollection, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
//run the test
broker.checkPermissionsForCopy(srcCollection, dest, newName);
verify(newDestPermissions, newDestCollection, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
assertEquals(dest.append(newName), newDestURICapture.getValue());
}
/**
* When copying a Collection (/db/test/source) where
* we have execute+read access and
* which has one descendant document (on which we have read access)
* in it,
*
* to the destination /db/test/dest (which already exists)
* and we have execute+write access on /db/test and /db/test/dest
* we should be allowed to copy the content of the Collection.
*/
@Test
public void copyCollection_oneSubDoc_toExistingDest_canWriteDest() throws LockException, PermissionDeniedException {
final XmldbURI src = XmldbURI.create("/db/test/source");
final XmldbURI dest = XmldbURI.create("/db/test");
final XmldbURI newName = XmldbURI.create("dest");
final Collection srcCollection = EasyMock.createStrictMock(Collection.class);
final Permission srcPermissions = EasyMock.createStrictMock(Permission.class);
final DocumentImpl srcSubDocument = EasyMock.createStrictMock(DocumentImpl.class);
final Permission srcSubDocumentPermissions = EasyMock.createStrictMock(Permission.class);
final Collection destCollection = EasyMock.createStrictMock(Collection.class);
final Permission destPermissions = EasyMock.createStrictMock(Permission.class);
final Collection newDestCollection = EasyMock.createStrictMock(Collection.class);
final Permission newDestPermissions = EasyMock.createStrictMock(Permission.class);
final NativeBroker broker = EasyMock.createMockBuilder(NativeBroker.class)
.addMockedMethod("getCollection")
.addMockedMethod("getSubject")
.createStrictMock();
final Subject subject = EasyMock.createStrictMock(Subject.class);
//grant EXECUTE and READ permissions on the src
expect(srcCollection.getPermissionsNoLock()).andReturn(srcPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcPermissions.validate(subject, Permission.EXECUTE | Permission.READ)).andReturn(true);
//grant EXECUTE and WRITE permission on the dest
expect(broker.getCollection(dest)).andReturn(destCollection);
final Capture<XmldbURI> newDestURICapture = new Capture<XmldbURI>();
expect(broker.getCollection(capture(newDestURICapture))).andReturn(newDestCollection);
expect(destCollection.getPermissionsNoLock()).andReturn(destPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(destPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(true);
expect(newDestCollection.getPermissionsNoLock()).andReturn(newDestPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(newDestPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(true);
//one sub-document with READ permission
expect(srcCollection.iterator(broker)).andReturn(new ArrayIterator<DocumentImpl>(srcSubDocument));
expect(srcSubDocument.getPermissions()).andReturn(srcSubDocumentPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcSubDocumentPermissions.validate(subject, Permission.READ)).andReturn(true);
expect(newDestCollection.isEmpty(broker)).andReturn(true); //no documents in the dest collection
//no sub-collections
expect(srcCollection.collectionIterator(broker)).andReturn(new EmptyIterator<XmldbURI>());
//test below
replay(newDestPermissions, newDestCollection, srcSubDocumentPermissions, srcSubDocument, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
//run the test
broker.checkPermissionsForCopy(srcCollection, dest, newName);
verify(newDestPermissions, newDestCollection, srcSubDocumentPermissions, srcSubDocument, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
assertEquals(dest.append(newName), newDestURICapture.getValue());
}
/**
* When copying a Collection (/db/test/source) where
* we have execute+read access and
* which has one descendant document (on which we DO NOT have read access)
* in it,
*
* to the destination /db/test/dest (which already exists)
* and we have execute+write access on /db/test and /db/test/dest
* we should NOT be allowed to copy the content of the Collection.
*/
@Test(expected=PermissionDeniedException.class)
public void copyCollection_oneSubDoc_toExistingDest_cannotReadSubDoc() throws LockException, PermissionDeniedException {
final XmldbURI src = XmldbURI.create("/db/test/source");
final XmldbURI dest = XmldbURI.create("/db/test");
final XmldbURI newName = XmldbURI.create("dest");
final Collection srcCollection = EasyMock.createStrictMock(Collection.class);
final Permission srcPermissions = EasyMock.createStrictMock(Permission.class);
final DocumentImpl srcSubDocument = EasyMock.createStrictMock(DocumentImpl.class);
final Permission srcSubDocumentPermissions = EasyMock.createStrictMock(Permission.class);
final Collection destCollection = EasyMock.createStrictMock(Collection.class);
final Permission destPermissions = EasyMock.createStrictMock(Permission.class);
final Collection newDestCollection = EasyMock.createStrictMock(Collection.class);
final Permission newDestPermissions = EasyMock.createStrictMock(Permission.class);
final NativeBroker broker = EasyMock.createMockBuilder(NativeBroker.class)
.addMockedMethod("getCollection")
.addMockedMethod("getSubject")
.createStrictMock();
final Subject subject = EasyMock.createStrictMock(Subject.class);
//grant EXECUTE and READ permissions on the src
expect(srcCollection.getPermissionsNoLock()).andReturn(srcPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcPermissions.validate(subject, Permission.EXECUTE | Permission.READ)).andReturn(true);
//grant EXECUTE and WRITE permission on the dest
expect(broker.getCollection(dest)).andReturn(destCollection);
final Capture<XmldbURI> newDestURICapture = new Capture<XmldbURI>();
expect(broker.getCollection(capture(newDestURICapture))).andReturn(newDestCollection);
expect(destCollection.getPermissionsNoLock()).andReturn(destPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(destPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(true);
expect(newDestCollection.getPermissionsNoLock()).andReturn(newDestPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(newDestPermissions.validate(subject, Permission.EXECUTE | Permission.WRITE)).andReturn(true);
//one sub-document with READ permission
expect(srcCollection.iterator(broker)).andReturn(new ArrayIterator<DocumentImpl>(srcSubDocument));
expect(srcSubDocument.getPermissions()).andReturn(srcSubDocumentPermissions);
expect(broker.getSubject()).andReturn(subject);
expect(srcSubDocumentPermissions.validate(subject, Permission.READ)).andReturn(false);
//expectations for exception that should be thrown
expect(srcCollection.getURI()).andReturn(src);
expect(srcSubDocument.getURI()).andReturn(src.append(newName).append("someSubDocument.xml"));
expect(broker.getSubject()).andReturn(subject);
expect(subject.getName()).andReturn("Fake user");
//no sub-collections
expect(srcCollection.collectionIterator(broker)).andReturn(new EmptyIterator<XmldbURI>());
//test below
replay(newDestPermissions, newDestCollection, srcSubDocumentPermissions, srcSubDocument, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
//run the test
broker.checkPermissionsForCopy(srcCollection, dest, newName);
verify(newDestPermissions, newDestCollection, srcSubDocumentPermissions, srcSubDocument, destCollection, destPermissions, srcCollection, srcPermissions, subject, broker);
assertEquals(dest.append(newName), newDestURICapture.getValue());
}
class ArrayIterator<T> implements Iterator<T> {
final Iterator<T> it;
public ArrayIterator(final T... documents) {
this.it = Arrays.asList(documents).iterator();
}
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public T next() {
return it.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException("Remove is not permitted");
}
}
class EmptyIterator<T> implements Iterator<T> {
@Override
public boolean hasNext() {
return false;
}
@Override
public T next() {
throw new NoSuchElementException("Iterator is Empty!");
}
@Override
public void remove() {
throw new UnsupportedOperationException("Remove is not permitted");
}
}
}