0001: /*
0002: * Copyright 2004 Outerthought bvba and Schaubroeck nv
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.apache.org/licenses/LICENSE-2.0
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */
0016: package org.outerj.daisy.repository.test;
0017:
0018: import org.outerj.daisy.repository.*;
0019: import org.outerj.daisy.repository.comment.CommentVisibility;
0020: import org.outerj.daisy.repository.testsupport.AbstractDaisyTestCase;
0021: import org.outerj.daisy.repository.user.UserManager;
0022: import org.outerj.daisy.repository.user.Role;
0023: import org.outerj.daisy.repository.user.User;
0024: import org.outerj.daisy.repository.acl.*;
0025: import org.outerj.daisy.repository.schema.DocumentType;
0026: import org.outerj.daisy.repository.schema.RepositorySchema;
0027: import org.outerj.daisy.repository.schema.FieldType;
0028: import org.outerj.daisy.repository.schema.PartType;
0029: import org.outerx.daisy.x10.SearchResultDocument;
0030: import org.apache.xmlbeans.QNameSet;
0031:
0032: import java.util.Collections;
0033: import java.util.Locale;
0034:
0035: /**
0036: * Tests for the AccessManager.
0037: */
0038: public abstract class AbstractAclTest extends AbstractDaisyTestCase {
0039: protected boolean resetDataStores() {
0040: return true;
0041: }
0042:
0043: protected abstract RepositoryManager getRepositoryManager()
0044: throws Exception;
0045:
0046: public void testAcl() throws Exception {
0047: RepositoryManager repositoryManager = getRepositoryManager();
0048:
0049: Repository testuserRepository = repositoryManager
0050: .getRepository(new Credentials("testuser", "testuser"));
0051: testuserRepository.switchRole(Role.ADMINISTRATOR);
0052:
0053: // Create a document type
0054: RepositorySchema schema = testuserRepository
0055: .getRepositorySchema();
0056:
0057: FieldType stringField = schema.createFieldType("StringField",
0058: ValueType.STRING);
0059: stringField.setAclAllowed(true);
0060: stringField.save();
0061: FieldType longField = schema.createFieldType("LongField",
0062: ValueType.LONG);
0063: longField.save();
0064:
0065: PartType partType = schema.createPartType("TestPart", "");
0066: partType.setDaisyHtml(true);
0067: partType.save();
0068:
0069: DocumentType documentType = schema
0070: .createDocumentType("acltesttype");
0071: documentType.addFieldType(stringField, false);
0072: documentType.addFieldType(longField, false);
0073: documentType.addPartType(partType, false);
0074: documentType.save();
0075:
0076: // Create users
0077: UserManager userManager = testuserRepository.getUserManager();
0078: Role userRole = userManager.getRole("User", false);
0079:
0080: Role role1 = userManager.createRole("role1");
0081: role1.save();
0082:
0083: Role role2 = userManager.createRole("role2");
0084: role2.save();
0085:
0086: User user1 = userManager.createUser("user1");
0087: user1.setPassword("user1");
0088: user1.addToRole(userRole);
0089: user1.addToRole(role1);
0090: user1.addToRole(role2);
0091: user1.setDefaultRole(userRole);
0092: user1.save();
0093: Repository user1Repository = repositoryManager
0094: .getRepository(new Credentials("user1", "user1"));
0095:
0096: User user2 = userManager.createUser("user2");
0097: user2.setPassword("user2");
0098: user2.addToRole(userRole);
0099: user2.setDefaultRole(userRole);
0100: user2.save();
0101: Repository user2Repository = repositoryManager
0102: .getRepository(new Credentials("user2", "user2"));
0103:
0104: // Create documents
0105: Document document1 = testuserRepository.createDocument(
0106: "Document1", documentType.getId());
0107: document1.setField(stringField.getId(), "hello");
0108: document1.setField(longField.getId(), new Long(55));
0109: document1.setPart(partType.getId(), "text/plain",
0110: "Once upon a time.".getBytes());
0111: document1.save();
0112:
0113: //
0114: // First do some tests regarding ACL manipulation
0115: //
0116:
0117: AccessManager accessManager = testuserRepository
0118: .getAccessManager();
0119: Acl acl = accessManager.getStagingAcl();
0120: AclObject aclObject = acl.createNewObject("true");
0121: acl.add(aclObject);
0122: acl.save();
0123:
0124: Acl aclParallel = accessManager.getStagingAcl();
0125: aclParallel.save();
0126: try {
0127: acl.save();
0128: fail("Saving ACL should have given concurrent modification exception.");
0129: } catch (Exception e) {
0130: }
0131:
0132: accessManager.copyStagingToLive();
0133: Acl liveAcl = accessManager.getLiveAcl();
0134:
0135: try {
0136: liveAcl.save();
0137: fail("Saving the live ACL should not be possible.");
0138: } catch (Exception e) {
0139: }
0140:
0141: assertEquals(1, liveAcl.size());
0142:
0143: acl = accessManager.getStagingAcl();
0144: aclObject = acl.get(0);
0145:
0146: try {
0147: aclObject.createNewEntry(AclSubjectType.EVERYONE, 5);
0148: fail("For subject type EVERYONE, -1 is required as subject value.");
0149: } catch (Exception e) {
0150: }
0151:
0152: try {
0153: aclObject.createNewEntry(AclSubjectType.USER, -1);
0154: fail("For subject type USER, -1 is not allowed as subject value.");
0155: } catch (Exception e) {
0156: }
0157:
0158: try {
0159: aclObject.createNewEntry(AclSubjectType.ROLE, -1);
0160: fail("For subject type USER, -1 is not allowed as subject value.");
0161: } catch (Exception e) {
0162: }
0163:
0164: try {
0165: AclEntry aclEntry = aclObject.createNewEntry(
0166: AclSubjectType.EVERYONE, -1);
0167: aclEntry.setSubjectValue(5);
0168: fail("For subject type EVERYONE, 5 is not allowed as subject value.");
0169: } catch (Exception e) {
0170: }
0171:
0172: AclEntry aclEntry = aclObject.createNewEntry(
0173: AclSubjectType.EVERYONE, -1);
0174: aclEntry.set(AclPermission.READ, AclActionType.GRANT);
0175: assertEquals(AclActionType.DO_NOTHING, aclEntry
0176: .get(AclPermission.WRITE));
0177: assertEquals(AclActionType.DO_NOTHING, aclEntry
0178: .get(AclPermission.PUBLISH));
0179: aclEntry.set(AclPermission.PUBLISH, AclActionType.GRANT);
0180: assertEquals(AclActionType.GRANT, aclEntry
0181: .get(AclPermission.PUBLISH));
0182: aclEntry.set(AclPermission.DELETE, AclActionType.GRANT);
0183: assertEquals(AclActionType.GRANT, aclEntry
0184: .get(AclPermission.DELETE));
0185: aclObject.add(aclEntry);
0186:
0187: acl.save();
0188:
0189: // Check that saving staging ACL didn't influence live ACL
0190: liveAcl = accessManager.getLiveAcl();
0191: assertEquals(0, liveAcl.get(0).size());
0192:
0193: // check that copying live back to staging works
0194: accessManager.copyLiveToStaging();
0195: acl = accessManager.getStagingAcl();
0196: assertEquals(0, acl.get(0).size());
0197:
0198: // Test object expressions don't work on fields that are not ACL allowed
0199: aclObject = acl.createNewObject("$LongField = 55");
0200: acl.add(aclObject);
0201: acl.save();
0202: try {
0203: accessManager.getAclInfoOnStaging(-1, new long[] { -1 },
0204: document1.getId());
0205: fail("Evaluating an ACL containg a check on a non-ACL allowed field should have failed.");
0206: } catch (RepositoryException e) {
0207: }
0208:
0209: // Overview of the ACL created below:
0210: // READ WRITE PUBLISH DELETE
0211: // true
0212: // role=user G G G G
0213: // documentType='acltesttype' and $StringField='ciao'
0214: // user=user1 G D D D
0215: // documentType='acltesttype' and $StringField='hello'
0216: // everyone G D D D
0217: // documentType='acltesttype'
0218: // user=user2 D G G G
0219: // $StringField='ta'
0220: // user=user2 G G D D
0221: // user=user1 G G G G
0222: // $StringField='tata'
0223: // user=user2 D D D D
0224: // user=user1 G G G G
0225:
0226: acl = accessManager.getStagingAcl();
0227: acl.clear();
0228:
0229: AclObject object = acl.createNewObject("true");
0230: acl.add(object);
0231: AclEntry entry = object.createNewEntry(AclSubjectType.ROLE,
0232: userRole.getId());
0233: object.add(entry);
0234: entry.set(AclPermission.READ, AclActionType.GRANT);
0235: entry.set(AclPermission.WRITE, AclActionType.GRANT);
0236: entry.set(AclPermission.PUBLISH, AclActionType.GRANT);
0237: entry.set(AclPermission.DELETE, AclActionType.GRANT);
0238:
0239: object = acl
0240: .createNewObject("documentType = 'acltesttype' and $StringField='ciao'");
0241: acl.add(object);
0242: entry = object.createNewEntry(AclSubjectType.USER, user1
0243: .getId());
0244: object.add(entry);
0245: entry.set(AclPermission.READ, AclActionType.GRANT);
0246: entry.set(AclPermission.WRITE, AclActionType.DENY);
0247: entry.set(AclPermission.PUBLISH, AclActionType.DENY);
0248: entry.set(AclPermission.DELETE, AclActionType.DENY);
0249:
0250: object = acl
0251: .createNewObject("documentType = 'acltesttype' and $StringField='hello'");
0252: acl.add(object);
0253: entry = object.createNewEntry(AclSubjectType.EVERYONE, -1);
0254: object.add(entry);
0255: entry.set(AclPermission.READ, AclActionType.GRANT);
0256: entry.set(AclPermission.WRITE, AclActionType.DENY);
0257: entry.set(AclPermission.PUBLISH, AclActionType.DENY);
0258: entry.set(AclPermission.DELETE, AclActionType.DENY);
0259:
0260: object = acl.createNewObject("documentType = 'acltesttype'");
0261: acl.add(object);
0262: entry = object.createNewEntry(AclSubjectType.USER, user2
0263: .getId());
0264: object.add(entry);
0265: entry.set(AclPermission.READ, AclActionType.DENY);
0266: entry.set(AclPermission.WRITE, AclActionType.GRANT);
0267: entry.set(AclPermission.PUBLISH, AclActionType.DENY);
0268: entry.set(AclPermission.DELETE, AclActionType.DENY);
0269:
0270: object = acl.createNewObject("$StringField = 'ta'");
0271: acl.add(object);
0272: entry = object.createNewEntry(AclSubjectType.USER, user2
0273: .getId());
0274: object.add(entry);
0275: entry.set(AclPermission.READ, AclActionType.GRANT);
0276: entry.set(AclPermission.WRITE, AclActionType.GRANT);
0277: entry.set(AclPermission.PUBLISH, AclActionType.DENY);
0278: entry.set(AclPermission.DELETE, AclActionType.DENY);
0279: entry = object.createNewEntry(AclSubjectType.USER, user1
0280: .getId());
0281: object.add(entry);
0282: entry.set(AclPermission.READ, AclActionType.GRANT);
0283: entry.set(AclPermission.WRITE, AclActionType.GRANT);
0284: entry.set(AclPermission.PUBLISH, AclActionType.GRANT);
0285: entry.set(AclPermission.DELETE, AclActionType.GRANT);
0286:
0287: object = acl.createNewObject("$StringField = 'tata'");
0288: acl.add(object);
0289: entry = object.createNewEntry(AclSubjectType.USER, user2
0290: .getId());
0291: object.add(entry);
0292: AccessDetails accessDetails = entry.createNewDetails();
0293: accessDetails.set(AclDetailPermission.NON_LIVE,
0294: AclActionType.DENY);
0295: entry.set(AclPermission.READ, AclActionType.GRANT,
0296: accessDetails);
0297: entry.set(AclPermission.WRITE, AclActionType.DENY);
0298: entry.set(AclPermission.PUBLISH, AclActionType.DENY);
0299: entry.set(AclPermission.DELETE, AclActionType.DENY);
0300: entry = object.createNewEntry(AclSubjectType.USER, user1
0301: .getId());
0302: object.add(entry);
0303: entry.set(AclPermission.READ, AclActionType.GRANT);
0304: entry.set(AclPermission.WRITE, AclActionType.GRANT);
0305: entry.set(AclPermission.PUBLISH, AclActionType.GRANT);
0306: entry.set(AclPermission.DELETE, AclActionType.GRANT);
0307:
0308: acl.save();
0309: accessManager.copyStagingToLive();
0310:
0311: // owner of the document should have all permissions
0312: AclResultInfo result = accessManager.getAclInfoOnLive(
0313: testuserRepository.getUserId(), new long[] { -1 },
0314: document1.getId());
0315: assertEquals("owner should have read access", result
0316: .isAllowed(AclPermission.READ), true);
0317: assertEquals("owner should have write access", result
0318: .isAllowed(AclPermission.WRITE), true);
0319:
0320: // everyone should have read access on the document, but not write access
0321: result = accessManager.getAclInfoOnLive(-1, new long[] { -1 },
0322: document1.getId());
0323: assertEquals(result.isAllowed(AclPermission.READ), true);
0324: assertEquals(result.isAllowed(AclPermission.WRITE), false);
0325:
0326: // everyone should have read access on the document, but not write access
0327: result = accessManager.getAclInfoOnLive(user2.getId(),
0328: new long[] { userRole.getId() }, document1.getId());
0329: assertEquals(result.isAllowed(AclPermission.READ), false);
0330: assertEquals(result.isAllowed(AclPermission.WRITE), false); // Note that even though write access is granted
0331: // in the ACL, write rights can never be more
0332: // liberal then read rights.
0333:
0334: // Document owner should be able to retrieve the document
0335: testuserRepository.getDocument(document1.getId(), true);
0336:
0337: // Test that user2 should not have read access
0338: try {
0339: user2Repository.getDocument(document1.getId(), true);
0340: fail("user 'user2' should not be able to access Document1");
0341: } catch (RepositoryException e) {
0342: }
0343:
0344: // and verify this is also the case if user2 tries to directly access part data
0345: try {
0346: user2Repository.getPartData(document1.getId(), 1, partType
0347: .getId());
0348: } catch (RepositoryException e) {
0349: }
0350:
0351: Document document2 = user1Repository.createDocument(
0352: "Document2", documentType.getId());
0353: document2.setField(stringField.getId(), "hi");
0354: document2.setField(longField.getId(), new Long(55));
0355: document2.save();
0356:
0357: // User 'user1' should be able to save a document having $StringField='ciao' IF HE IS THE OWNER
0358: document2 = user1Repository
0359: .getDocument(document2.getId(), true);
0360: document2.setField("StringField", "ciao");
0361: document2.save();
0362:
0363: // User 'user1' should not be able to save a document having $StringField='ciao'
0364: Document document3 = testuserRepository.createDocument(
0365: "Document3", documentType.getId());
0366: document3.save();
0367: document3 = user1Repository
0368: .getDocument(document3.getId(), true);
0369: document3.save(); // verifies that saving under normal conditions would work
0370: try {
0371: document3.setField("StringField", "ciao");
0372: document3.save();
0373: fail("Saving document3 by user 'user1' should have failed.");
0374: } catch (RepositoryException e) {
0375: }
0376:
0377: // test that a new document cannot be created if the user himself would not have
0378: // access to it (even if he is the owner, and would thus never be able to loose
0379: // these rights, we don't let him create new documents this way)
0380: Document document4 = user1Repository.createDocument(
0381: "Document4", documentType.getId());
0382: try {
0383: document4.setField("StringField", "ciao");
0384: document4.save();
0385: fail("Saving a new document (document4) to which the user would not have access (if he/she were not owner) should fail.");
0386: } catch (RepositoryException e) {
0387: }
0388:
0389: // Adding comments only works if you have read access
0390: try {
0391: user2Repository.getCommentManager().addComment(
0392: document1.getId(), CommentVisibility.PUBLIC,
0393: "hello");
0394: fail("Adding a comment should have failed because user2 does not have read access.");
0395: } catch (Exception e) {
0396: }
0397:
0398: user1Repository.getCommentManager().addComment(
0399: document1.getId(), CommentVisibility.PUBLIC, "hello");
0400:
0401: // Test private flag
0402: Document document5 = user1Repository.createDocument(
0403: "Document5", documentType.getId());
0404: document5.setPrivate(true);
0405: document5.save();
0406:
0407: // owner should be able to access private document
0408: user1Repository.getDocument(document5.getId(), true);
0409: // admin should be able to access private document
0410: testuserRepository.getDocument(document5.getId(), true);
0411:
0412: Document document6 = testuserRepository.createDocument(
0413: "Document6", documentType.getId());
0414: document6.setPrivate(true);
0415: document6.save();
0416: try {
0417: user1Repository.getDocument(document6.getId(), true);
0418: fail("user1 should not have access to a private document of someone else.");
0419: } catch (Exception e) {
0420: }
0421:
0422: Document document7 = user2Repository.createDocument(
0423: "Document7", documentType.getId());
0424: document7.setOwner(user1.getId()); // otherwise user will always have publish right since he is owner
0425: document7.setField("StringField", "ta");
0426: document7.setNewVersionState(VersionState.PUBLISH);
0427: document7.save();
0428: document7 = user2Repository
0429: .getDocument(document7.getId(), true);
0430: assertTrue("user2 can't put publish document", document7
0431: .getLastVersion().getState() == VersionState.DRAFT);
0432:
0433: AclResultInfo info = testuserRepository.getAccessManager()
0434: .getAclInfoOnLive(user2Repository.getUserId(),
0435: user2Repository.getActiveRoleIds(),
0436: document7.getId());
0437:
0438: try {
0439: Version doc7Last = document7.getLastVersion();
0440: doc7Last.setState(VersionState.PUBLISH);
0441: doc7Last.save();
0442: fail("Setting state to publish should have failed.");
0443: } catch (Exception e) {
0444: }
0445:
0446: Document document7user1 = user1Repository.getDocument(document7
0447: .getId(), true);
0448: try {
0449: Version doc7last = document7user1.getLastVersion();
0450: doc7last.setState(VersionState.PUBLISH);
0451: doc7last.save();
0452: } catch (Exception e) {
0453: }
0454:
0455: assertTrue(user2Repository.getAccessManager().getAclInfoOnLive(
0456: user2.getId(), user2Repository.getActiveRoleIds(),
0457: document7.getId()).getActionType(AclPermission.DELETE) == AclActionType.DENY);
0458: try {
0459: user2Repository.deleteDocument(document7.getId());
0460: fail("user2 shouldn't be able to delete document.");
0461: } catch (AccessException e) {
0462: }
0463:
0464: assertTrue(user1Repository.getAccessManager().getAclInfoOnLive(
0465: user1.getId(), user1Repository.getActiveRoleIds(),
0466: document7.getId()).getActionType(AclPermission.DELETE) == AclActionType.GRANT);
0467: user1Repository.deleteDocument(document7.getId());
0468:
0469: // test read live access
0470: Document document8 = user1Repository.createDocument(
0471: "Document8", documentType.getId());
0472: document8.setField("StringField", "tata");
0473: document8.save();
0474: document8.setName("Document8 - 2");
0475: document8.setNewVersionState(VersionState.DRAFT);
0476: document8.save();
0477:
0478: document8 = user2Repository.getDocument(document8.getId(),
0479: false);
0480: callDisallowedVersionMethods(document8);
0481: document8 = user2Repository
0482: .getDocument(document8.getId(), true);
0483: callDisallowedVersionMethods(document8);
0484:
0485: document8 = user1Repository
0486: .getDocument(document8.getId(), true);
0487: document8.setField("LongField", new Long(5));
0488: document8.setNewVersionState(VersionState.PUBLISH);
0489: document8.save();
0490:
0491: document8 = user2Repository
0492: .getDocument(document8.getId(), true);
0493:
0494: // Getting data from the live version should succeed.
0495: document8.getLiveVersion().getField("StringField");
0496: // Last version is live version, so this should work too
0497: // However, this currently does not work in the remote implementation, since the implemenation depends on loading the full version list
0498: // document8.getLastVersion().getField("StringField");
0499: try {
0500: document8.getVersion(1).getField("StringField");
0501: fail("Getting data from non-live version should fail.");
0502: } catch (RuntimeException e) {
0503: // ok
0504: }
0505:
0506: document8 = user1Repository
0507: .getDocument(document8.getId(), true);
0508: document8.setRetired(true);
0509: document8.save();
0510:
0511: try {
0512: document8 = user2Repository.getDocument(document8.getId(),
0513: false);
0514: fail("Getting live version of retired document should fail if user has only read live permission");
0515: } catch (DocumentReadDeniedException e) {
0516: }
0517:
0518: try {
0519: document8 = user2Repository.getDocument(document8.getId(),
0520: true);
0521: fail("Getting live version of retired document should fail if user has only read live permission");
0522: } catch (DocumentReadDeniedException e) {
0523: }
0524:
0525: //
0526: // Test filtering of document types
0527: //
0528:
0529: // start by creating some document types
0530: DocumentType documentTypeA = schema.createDocumentType("A");
0531: documentTypeA.save();
0532: DocumentType documentTypeB = schema.createDocumentType("B");
0533: documentTypeB.save();
0534: DocumentType documentTypeC = schema.createDocumentType("C");
0535: documentTypeC.save();
0536:
0537: // and collection
0538: DocumentCollection boeCollection = testuserRepository
0539: .getCollectionManager().createCollection("boe");
0540: boeCollection.save();
0541: DocumentCollection baaCollection = testuserRepository
0542: .getCollectionManager().createCollection("baa");
0543: baaCollection.save();
0544:
0545: // Create an acl
0546: acl = accessManager.getStagingAcl();
0547: acl.clear();
0548:
0549: aclObject = acl.createNewObject("documentType = 'A'");
0550: aclEntry = aclObject
0551: .createNewEntry(AclSubjectType.EVERYONE, -1);
0552: aclEntry.set(AclPermission.READ, AclActionType.GRANT);
0553: aclEntry.set(AclPermission.WRITE, AclActionType.GRANT);
0554: aclObject.add(aclEntry);
0555: acl.add(aclObject);
0556:
0557: aclObject = acl
0558: .createNewObject("documentType = 'B' and $StringField = 'hello'");
0559: aclEntry = aclObject
0560: .createNewEntry(AclSubjectType.EVERYONE, -1);
0561: aclEntry.set(AclPermission.READ, AclActionType.GRANT);
0562: aclEntry.set(AclPermission.WRITE, AclActionType.GRANT);
0563: aclObject.add(aclEntry);
0564: aclEntry = aclObject.createNewEntry(AclSubjectType.USER, user1
0565: .getId());
0566: aclEntry.set(AclPermission.READ, AclActionType.DENY);
0567: aclEntry.set(AclPermission.WRITE, AclActionType.DENY);
0568: aclObject.add(aclEntry);
0569: acl.add(aclObject);
0570:
0571: aclObject = acl.createNewObject("documentType = 'C'");
0572: aclEntry = aclObject
0573: .createNewEntry(AclSubjectType.EVERYONE, -1);
0574: aclEntry.set(AclPermission.READ, AclActionType.DENY);
0575: aclEntry.set(AclPermission.WRITE, AclActionType.DENY);
0576: aclObject.add(aclEntry);
0577: acl.add(aclObject);
0578:
0579: acl.save();
0580: accessManager.copyStagingToLive();
0581:
0582: long[] filteredDocTypes = user1Repository.getAccessManager()
0583: .filterDocumentTypes(
0584: new long[] { documentTypeA.getId(),
0585: documentTypeB.getId(),
0586: documentTypeC.getId() }, -1);
0587: assertEquals(2, filteredDocTypes.length);
0588: assertEquals(documentTypeA.getId(), filteredDocTypes[0]);
0589: assertEquals(documentTypeB.getId(), filteredDocTypes[1]);
0590:
0591: // Test filtering with InCollection expressions
0592: // define a new ACL first
0593: acl.clear();
0594:
0595: aclObject = acl.createNewObject("InCollection('boe')");
0596: aclEntry = aclObject
0597: .createNewEntry(AclSubjectType.EVERYONE, -1);
0598: aclEntry.set(AclPermission.READ, AclActionType.DENY);
0599: aclEntry.set(AclPermission.WRITE, AclActionType.DENY);
0600: aclObject.add(aclEntry);
0601: aclEntry = aclObject.createNewEntry(AclSubjectType.ROLE,
0602: userRole.getId());
0603: aclEntry.set(AclPermission.READ, AclActionType.GRANT);
0604: aclEntry.set(AclPermission.WRITE, AclActionType.GRANT);
0605: aclObject.add(aclEntry);
0606: acl.add(aclObject);
0607:
0608: aclObject = acl.createNewObject("InCollection('baa')");
0609: aclEntry = aclObject
0610: .createNewEntry(AclSubjectType.EVERYONE, -1);
0611: aclEntry.set(AclPermission.READ, AclActionType.DENY);
0612: aclEntry.set(AclPermission.WRITE, AclActionType.DENY);
0613: aclObject.add(aclEntry);
0614: acl.add(aclObject);
0615:
0616: acl.save();
0617: accessManager.copyStagingToLive();
0618:
0619: filteredDocTypes = user1Repository.getAccessManager()
0620: .filterDocumentTypes(
0621: new long[] { documentTypeA.getId() },
0622: boeCollection.getId());
0623: assertEquals(1, filteredDocTypes.length);
0624: assertEquals(documentTypeA.getId(), filteredDocTypes[0]);
0625:
0626: filteredDocTypes = user1Repository.getAccessManager()
0627: .filterDocumentTypes(
0628: new long[] { documentTypeA.getId() },
0629: baaCollection.getId());
0630: assertEquals(0, filteredDocTypes.length);
0631:
0632: //
0633: // Test fine-grained read permissions (AccessDetails)
0634: //
0635: acl.clear();
0636: aclObject = acl.createNewObject("true");
0637: aclEntry = aclObject
0638: .createNewEntry(AclSubjectType.EVERYONE, -1);
0639: accessDetails = aclEntry.createNewDetails();
0640: try {
0641: accessDetails.addAccessibleField("foo");
0642: fail("Should not be able to add an accessible field when all fields permission is not denied");
0643: } catch (Exception e) {
0644: }
0645: accessDetails.set(AclDetailPermission.ALL_FIELDS,
0646: AclActionType.DENY);
0647: accessDetails.addAccessibleField("foo");
0648: try {
0649: accessDetails.addAccessiblePart("bar");
0650: fail("Should not be able to add an accessible part when all parts permission is not denied");
0651: } catch (Exception e) {
0652: }
0653: accessDetails.set(AclDetailPermission.ALL_PARTS,
0654: AclActionType.DENY);
0655: accessDetails.addAccessiblePart("bar");
0656: accessDetails.set(AclDetailPermission.NON_LIVE,
0657: AclActionType.DENY);
0658: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
0659: accessDetails);
0660: aclObject.add(aclEntry);
0661: acl.add(aclObject);
0662: acl.save();
0663:
0664: // reload ACL to check everything was saved correctly
0665: acl = accessManager.getStagingAcl();
0666: accessDetails = acl.get(0).get(0)
0667: .getDetails(AclPermission.READ);
0668: assertTrue(accessDetails.getAccessibleFields().equals(
0669: Collections.singleton("foo")));
0670: assertTrue(accessDetails.getAccessibleParts().equals(
0671: Collections.singleton("bar")));
0672: assertTrue(accessDetails.liveOnly());
0673: assertEquals(AclActionType.DENY, accessDetails
0674: .get(AclDetailPermission.NON_LIVE));
0675:
0676: info = user1Repository.getAccessManager().getAclInfoOnStaging(
0677: user1.getId(), user1Repository.getActiveRoleIds(),
0678: document1.getVariantKey());
0679: accessDetails = info.getAccessDetails(AclPermission.READ);
0680: assertTrue(accessDetails.getAccessibleFields().equals(
0681: Collections.singleton("foo")));
0682: assertTrue(accessDetails.getAccessibleParts().equals(
0683: Collections.singleton("bar")));
0684: assertEquals(AclActionType.DENY, accessDetails
0685: .get(AclDetailPermission.NON_LIVE));
0686:
0687: // Test that older AccessDetails are combined/overwritten by newer ones
0688: acl.clear();
0689: aclObject = acl.createNewObject("true");
0690: acl.add(aclObject);
0691:
0692: aclEntry = aclObject
0693: .createNewEntry(AclSubjectType.EVERYONE, -1);
0694: accessDetails = aclEntry.createNewDetails();
0695: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
0696: accessDetails);
0697: accessDetails.set(AclDetailPermission.NON_LIVE,
0698: AclActionType.DENY);
0699: accessDetails.set(AclDetailPermission.ALL_FIELDS,
0700: AclActionType.DENY);
0701: accessDetails.set(AclDetailPermission.ALL_PARTS,
0702: AclActionType.DENY);
0703: accessDetails.addAccessibleField("foo");
0704: accessDetails.addAccessiblePart("bar");
0705: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
0706: accessDetails);
0707: aclObject.add(aclEntry);
0708:
0709: aclEntry = aclObject
0710: .createNewEntry(AclSubjectType.EVERYONE, -1);
0711: accessDetails = aclEntry.createNewDetails();
0712: accessDetails.set(AclDetailPermission.NON_LIVE,
0713: AclActionType.DENY);
0714: accessDetails.set(AclDetailPermission.ALL_FIELDS,
0715: AclActionType.DENY);
0716: accessDetails.set(AclDetailPermission.ALL_PARTS,
0717: AclActionType.DENY);
0718: accessDetails.addAccessibleField("foo2");
0719: accessDetails.addAccessiblePart("bar2");
0720: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
0721: accessDetails);
0722: aclObject.add(aclEntry);
0723:
0724: acl.save();
0725:
0726: info = user1Repository.getAccessManager().getAclInfoOnStaging(
0727: user1.getId(), user1Repository.getActiveRoleIds(),
0728: document1.getVariantKey());
0729: accessDetails = info.getAccessDetails(AclPermission.READ);
0730: assertTrue(accessDetails.getAccessibleFields().contains("foo"));
0731: assertTrue(accessDetails.getAccessibleFields().contains("foo2"));
0732: assertTrue(accessDetails.getAccessibleParts().contains("bar"));
0733: assertTrue(accessDetails.getAccessibleParts().contains("bar2"));
0734: assertEquals(AclActionType.DENY, accessDetails
0735: .get(AclDetailPermission.NON_LIVE));
0736:
0737: // Test giving back full access
0738: acl.clear();
0739: aclObject = acl.createNewObject("true");
0740: acl.add(aclObject);
0741:
0742: aclEntry = aclObject
0743: .createNewEntry(AclSubjectType.EVERYONE, -1);
0744: accessDetails = aclEntry.createNewDetails();
0745: accessDetails.set(AclDetailPermission.ALL_FIELDS,
0746: AclActionType.DENY);
0747: accessDetails.set(AclDetailPermission.ALL_PARTS,
0748: AclActionType.DENY);
0749: accessDetails.addAccessibleField("foo");
0750: accessDetails.addAccessiblePart("bar");
0751: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
0752: accessDetails);
0753: aclObject.add(aclEntry);
0754:
0755: aclEntry = aclObject
0756: .createNewEntry(AclSubjectType.EVERYONE, -1);
0757: aclEntry.set(AclPermission.READ, AclActionType.GRANT); // granting without details == all details granted
0758: aclObject.add(aclEntry);
0759:
0760: acl.save();
0761:
0762: info = user1Repository.getAccessManager().getAclInfoOnStaging(
0763: user1.getId(), user1Repository.getActiveRoleIds(),
0764: document1.getVariantKey());
0765: accessDetails = info.getAccessDetails(AclPermission.READ);
0766: assertTrue(accessDetails.isFullAccess());
0767:
0768: // test combining (merging) AccessDetails granted by different roles
0769: acl.clear();
0770: aclObject = acl.createNewObject("true");
0771: acl.add(aclObject);
0772:
0773: aclEntry = aclObject.createNewEntry(AclSubjectType.ROLE, role1
0774: .getId());
0775: accessDetails = aclEntry.createNewDetails();
0776: accessDetails.set(AclDetailPermission.ALL_FIELDS,
0777: AclActionType.DENY);
0778: accessDetails.addAccessibleField("foo");
0779: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
0780: accessDetails);
0781: aclObject.add(aclEntry);
0782:
0783: aclEntry = aclObject.createNewEntry(AclSubjectType.ROLE, role2
0784: .getId());
0785: accessDetails = aclEntry.createNewDetails();
0786: accessDetails.set(AclDetailPermission.ALL_FIELDS,
0787: AclActionType.DENY);
0788: accessDetails.addAccessibleField("bar");
0789: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
0790: accessDetails);
0791: aclObject.add(aclEntry);
0792:
0793: acl.save();
0794:
0795: info = user1Repository.getAccessManager().getAclInfoOnStaging(
0796: user1.getId(), new long[] { role1.getId() },
0797: document1.getVariantKey());
0798: assertTrue(info.getAccessDetails(AclPermission.READ)
0799: .canAccessField("foo"));
0800: assertFalse(info.getAccessDetails(AclPermission.READ)
0801: .canAccessField("bar"));
0802:
0803: info = user1Repository.getAccessManager().getAclInfoOnStaging(
0804: user1.getId(), new long[] { role2.getId() },
0805: document1.getVariantKey());
0806: assertNotNull(info.getAccessDetails(AclPermission.READ));
0807: assertFalse(info.getAccessDetails(AclPermission.READ)
0808: .canAccessField("foo"));
0809: assertTrue(info.getAccessDetails(AclPermission.READ)
0810: .canAccessField("bar"));
0811:
0812: info = user1Repository.getAccessManager().getAclInfoOnStaging(
0813: user1.getId(),
0814: new long[] { role1.getId(), role2.getId() },
0815: document1.getVariantKey());
0816: assertTrue(info.getAccessDetails(AclPermission.READ)
0817: .canAccessField("foo"));
0818: assertTrue(info.getAccessDetails(AclPermission.READ)
0819: .canAccessField("bar"));
0820:
0821: // Verify that 'grant' is taken as default (= initial situation) for the detail permissions.
0822: acl.clear();
0823: aclObject = acl.createNewObject("true");
0824: acl.add(aclObject);
0825:
0826: aclEntry = aclObject
0827: .createNewEntry(AclSubjectType.EVERYONE, -1);
0828: aclEntry.set(AclPermission.READ, AclActionType.GRANT);
0829: aclObject.add(aclEntry);
0830:
0831: aclEntry = aclObject
0832: .createNewEntry(AclSubjectType.EVERYONE, -1);
0833: accessDetails = aclEntry.createNewDetails();
0834: accessDetails.set(AclDetailPermission.ALL_PARTS,
0835: AclActionType.DENY);
0836: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
0837: accessDetails);
0838: aclObject.add(aclEntry);
0839:
0840: acl.save();
0841: accessManager.copyStagingToLive();
0842:
0843: result = accessManager
0844: .getAclInfoOnLive(user1.getId(), new long[] { role1
0845: .getId() }, document1.getVariantKey());
0846: // since we didn't say anything about the non-live, it should be granted.
0847: assertEquals(AclActionType.GRANT, result.getAccessDetails(
0848: AclPermission.READ).get(AclDetailPermission.NON_LIVE));
0849: assertEquals(AclActionType.DENY, result.getAccessDetails(
0850: AclPermission.READ).get(AclDetailPermission.ALL_PARTS));
0851:
0852: // Test actual protection
0853: acl.clear();
0854: aclObject = acl.createNewObject("true");
0855: acl.add(aclObject);
0856:
0857: aclEntry = aclObject.createNewEntry(AclSubjectType.ROLE,
0858: userRole.getId());
0859: accessDetails = aclEntry.createNewDetails();
0860: accessDetails.set(AclDetailPermission.ALL_FIELDS,
0861: AclActionType.DENY);
0862: accessDetails.set(AclDetailPermission.ALL_PARTS,
0863: AclActionType.DENY);
0864: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
0865: accessDetails);
0866: aclEntry.set(AclPermission.WRITE, AclActionType.GRANT);
0867: aclObject.add(aclEntry);
0868:
0869: acl.save();
0870:
0871: accessManager.copyStagingToLive();
0872:
0873: Document document9 = testuserRepository.createDocument(
0874: "Document9", documentType.getId());
0875: document9.setField("StringField", "foo");
0876: document9.setPart(partType.getId(), "text/xml",
0877: "<html><body>foo</body></html>".getBytes("UTF-8"));
0878: document9.save();
0879:
0880: assertTrue(document9.hasField("StringField"));
0881: assertTrue(document9.getLastVersion().hasField("StringField"));
0882: assertEquals(1, document9.getXml().getDocument().getFields()
0883: .getFieldList().size());
0884:
0885: info = user2Repository.getAccessManager().getAclInfoOnLive(
0886: user2.getId(), user2Repository.getActiveRoleIds(),
0887: document9.getVariantKey());
0888: assertEquals(AclActionType.GRANT, info
0889: .getActionType(AclPermission.READ));
0890: assertNotNull(info.getAccessDetails(AclPermission.READ));
0891: document9 = user2Repository.getDocument(document9
0892: .getVariantKey(), true);
0893: assertFalse(document9.hasField("StringField"));
0894: assertFalse(document9.getLastVersion().hasField("StringField"));
0895: assertEquals(0, document9.getXml().getDocument().getFields()
0896: .getFieldList().size());
0897:
0898: // Even though ACL grants write access, write access is not allowed when one only has partial read access
0899: try {
0900: if (repositoryManager.getClass().getName().endsWith(
0901: "RemoteRepositoryManager")) {
0902: // remote impl needs document to be modified
0903: document9.setCustomField("foo", "foo");
0904: }
0905: document9.save();
0906: fail("Expected an exception trying to save a document to which we have only partial read access");
0907: } catch (Exception e) {
0908: }
0909:
0910: // Test values are missing in query results too
0911: SearchResultDocument searchResult = user2Repository
0912: .getQueryManager().performQuery(
0913: "select name, $StringField where id = '"
0914: + document9.getId() + "'", Locale.US);
0915: assertEquals("", searchResult.getSearchResult().getRows()
0916: .getRowList().get(0).getValueArray(1));
0917: assertTrue(searchResult.getSearchResult().getRows()
0918: .getRowList().get(0).getAccess().contains(
0919: "restrictedRead"));
0920:
0921: searchResult = testuserRepository.getQueryManager()
0922: .performQuery(
0923: "select name, $StringField where id = '"
0924: + document9.getId() + "'", Locale.US);
0925: assertEquals("foo", searchResult.getSearchResult().getRows()
0926: .getRowList().get(0).getValueArray(1));
0927:
0928: searchResult = user2Repository
0929: .getQueryManager()
0930: .performQuery(
0931: "select name, %TestPart.mimeType, %TestPart.size, %TestPart.content where id = '"
0932: + document9.getId() + "'", Locale.US);
0933: assertEquals("", searchResult.getSearchResult().getRows()
0934: .getRowList().get(0).getValueArray(1));
0935: assertEquals("", searchResult.getSearchResult().getRows()
0936: .getRowList().get(0).getValueArray(2));
0937: assertEquals(0, searchResult.getSearchResult().getRows()
0938: .getRowList().get(0).getXmlValueArray(0)
0939: .selectChildren(QNameSet.ALL).length);
0940:
0941: // When the where clause includes a test on a non-readable field, the result row should be excluded
0942: searchResult = user2Repository.getQueryManager().performQuery(
0943: "select name, $StringField where id = '"
0944: + document9.getId()
0945: + "' and $StringField = 'foo'", Locale.US);
0946: assertEquals(0, searchResult.getSearchResult().getRows()
0947: .getRowList().size());
0948:
0949: searchResult = user2Repository.getQueryManager().performQuery(
0950: "select name, $StringField where id = '"
0951: + document9.getId()
0952: + "' and %TestPart.size > 0", Locale.US);
0953: assertEquals(0, searchResult.getSearchResult().getRows()
0954: .getRowList().size());
0955:
0956: searchResult = user2Repository.getQueryManager().performQuery(
0957: "select name, $StringField where id = '"
0958: + document9.getId()
0959: + "' and %TestPart.mimeType = 'text/xml'",
0960: Locale.US);
0961: assertEquals(0, searchResult.getSearchResult().getRows()
0962: .getRowList().size());
0963:
0964: // Same when the field is part of a dereference
0965: searchResult = user2Repository.getQueryManager().performQuery(
0966: "select name, $StringField where id = '"
0967: + document9.getId()
0968: + "' and link=>link=>$StringField = 'foo'",
0969: Locale.US);
0970: assertEquals(0, searchResult.getSearchResult().getRows()
0971: .getRowList().size());
0972:
0973: // test deny summary and fulltext access
0974:
0975: System.err
0976: .println("Sleeping a little while to give fulltextinder time to do its job.");
0977: Thread.sleep(10000);
0978:
0979: // first test they are accessible right now
0980: searchResult = user2Repository.getQueryManager().performQuery(
0981: "select name where FullText('foo') and id= '"
0982: + document9.getId() + "'", Locale.US);
0983: assertEquals(1, searchResult.getSearchResult().getRows()
0984: .getRowList().size());
0985:
0986: searchResult = user2Repository.getQueryManager().performQuery(
0987: "select name, summary where id = '" + document9.getId()
0988: + "'", Locale.US);
0989: assertTrue(searchResult.getSearchResult().getRows()
0990: .getRowList().get(0).getValueArray(1).length() > 0);
0991:
0992: // update ACL to disallow fulltext and summary access
0993: acl.clear();
0994: aclObject = acl.createNewObject("true");
0995: acl.add(aclObject);
0996:
0997: aclEntry = aclObject.createNewEntry(AclSubjectType.ROLE,
0998: userRole.getId());
0999: accessDetails = aclEntry.createNewDetails();
1000: accessDetails.set(AclDetailPermission.ALL_FIELDS,
1001: AclActionType.DENY);
1002: accessDetails.set(AclDetailPermission.ALL_PARTS,
1003: AclActionType.DENY);
1004: accessDetails.set(AclDetailPermission.FULLTEXT_INDEX,
1005: AclActionType.DENY);
1006: accessDetails.set(AclDetailPermission.SUMMARY,
1007: AclActionType.DENY);
1008: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
1009: accessDetails);
1010: aclEntry.set(AclPermission.WRITE, AclActionType.GRANT);
1011: aclObject.add(aclEntry);
1012:
1013: acl.save();
1014:
1015: accessManager.copyStagingToLive();
1016:
1017: // now the summary should be empty
1018: searchResult = user2Repository.getQueryManager().performQuery(
1019: "select name, summary where id = '" + document9.getId()
1020: + "'", Locale.US);
1021: assertEquals("", searchResult.getSearchResult().getRows()
1022: .getRowList().get(0).getValueArray(1));
1023:
1024: // and the fulltext should not return a result
1025: searchResult = user2Repository.getQueryManager().performQuery(
1026: "select name where FullText('foo') and id= '"
1027: + document9.getId() + "'", Locale.US);
1028: assertEquals(0, searchResult.getSearchResult().getRows()
1029: .getRowList().size());
1030:
1031: //
1032: // Test that the same object/entry/details object can only be used once in the ACL object model
1033: //
1034: acl.clear();
1035: aclObject = acl.createNewObject("true");
1036: acl.add(aclObject);
1037:
1038: aclEntry = aclObject.createNewEntry(AclSubjectType.ROLE,
1039: userRole.getId());
1040: aclEntry.set(AclPermission.READ, AclActionType.GRANT);
1041: aclObject.add(aclEntry);
1042:
1043: try {
1044: aclObject.add(aclEntry);
1045: fail("Adding the same entry twice should give an error.");
1046: } catch (RuntimeException e) {
1047: }
1048:
1049: // removing and re-adding should work
1050: aclObject.remove(0);
1051: aclObject.add(aclEntry);
1052:
1053: try {
1054: acl.add(aclObject);
1055: fail("Adding the same object twice should give an error.");
1056: } catch (RuntimeException e) {
1057: }
1058:
1059: accessDetails = aclEntry.createNewDetails();
1060: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
1061: accessDetails);
1062: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
1063: accessDetails); // should work
1064:
1065: aclEntry = aclObject
1066: .createNewEntry(AclSubjectType.EVERYONE, -1);
1067: try {
1068: aclEntry.set(AclPermission.READ, AclActionType.GRANT,
1069: accessDetails);
1070: fail("Adding the same details twice should give an error.");
1071: } catch (RuntimeException e) {
1072: }
1073:
1074: acl.save();
1075:
1076: // Note: the QueryTest implicitely also contains some ACL testing due
1077: // to the ACL-based filtering of resultsets, which is tested over there.
1078: }
1079:
1080: private void callDisallowedVersionMethods(Document document)
1081: throws Exception {
1082: document.getLiveVersion();
1083:
1084: try {
1085: document.getVersions();
1086: fail("Getting non-live version data should fail.");
1087: } catch (RuntimeException e) {
1088: }
1089:
1090: try {
1091: document.getLastVersion();
1092: fail("Getting non-live version data should fail.");
1093: } catch (RuntimeException e) {
1094: }
1095:
1096: try {
1097: document.getXml();
1098: fail("Getting non-live version data should fail.");
1099: } catch (RuntimeException e) {
1100: }
1101:
1102: try {
1103: document.getXml(2);
1104: fail("Getting non-live version data should fail.");
1105: } catch (RuntimeException e) {
1106: }
1107:
1108: try {
1109: document.getName();
1110: fail("Getting non-live version data should fail.");
1111: } catch (RuntimeException e) {
1112: }
1113:
1114: try {
1115: document.getField("whatever");
1116: fail("Getting non-live version data should fail.");
1117: } catch (RuntimeException e) {
1118: }
1119: }
1120: }
|