diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index e7fa2ec5ae..9f9dcfdf64 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -75,6 +75,12 @@ + + + + + + diff --git a/source/java/org/alfresco/repo/avm/AVMNode.java b/source/java/org/alfresco/repo/avm/AVMNode.java index e456aeb87d..4247664e2d 100644 --- a/source/java/org/alfresco/repo/avm/AVMNode.java +++ b/source/java/org/alfresco/repo/avm/AVMNode.java @@ -41,7 +41,7 @@ public interface AVMNode * @param ancestor The ancestor to set. */ public void setAncestor(AVMNode ancestor); - + /** * Change the ancestor of a node. * @param ancestor The ancestor node that should be set. @@ -114,26 +114,26 @@ public interface AVMNode * @return The descriptor for this node. */ public AVMNodeDescriptor getDescriptor(String parentPath, String name, String parentIndirection, int parentIndirectionVersion); - + /** * Get the object id. * @return The object id. */ public long getId(); - + /** * Get the newnews. * @return Whether the node is new. */ public boolean getIsNew(); - + /** * Get a string representation for debugging. * @param lPath The Lookup. * @return A String representation. */ public String toString(Lookup lPath); - + /** * Set whether this node to be a root of a AVMStore * @param isRoot @@ -145,91 +145,91 @@ public interface AVMNode * @return Whether this node is a root. */ public boolean getIsRoot(); - + /** * Update the modification time of this node. */ public void updateModTime(); - + /** * Set a property. * @param name The name of the property. * @param value The value to set. */ public void setProperty(QName name, PropertyValue value); - + /** * Set a collection of properties on this node. * @param properties The Map of QNames to PropertyValues. */ public void setProperties(Map properties); - + /** * Get a property by name. * @param name The name of the property to get. * @return A PropertyValue */ public PropertyValue getProperty(QName name); - + /** * Get all the properties associated with this node. * @return A Map of QNames to PropertyValues. */ public Map getProperties(); - + /** * Delete a property from this node. * @param name The name of the property. */ public void deleteProperty(QName name); - + /** * Delete all properties from this node. */ public void deleteProperties(); - + /** * Set an ACL on this node. * @param acl The ACL to set. */ public void setAcl(DbAccessControlList acl); - + /** * Get the ACL on this node. * @return The ACL on this node. */ public DbAccessControlList getAcl(); - + /** * Set the store that we are new in. * @param store The store we are new in. */ public void setStoreNew(AVMStore store); - + /** * Get the possibly null store that we're new in. * @return The store that we're new in. */ public AVMStore getStoreNew(); - + /** * Copy metadata from another node. * @param other The other node. */ public void copyMetaDataFrom(AVMNode other); - + /** * Get the GUID associated with this version. * @return The GUID. */ public String getGuid(); - + /** * Set the GUID associated with this version. * @param guid */ public void setGuid(String guid); - + /** * Get the Aspects that this node has. * @return A Set of Aspects names. @@ -241,4 +241,10 @@ public interface AVMNode * @param properties The properties to add. */ public void addProperties(Map properties); + + /** + * Get the Basic Attributes on this node. + * @return + */ + public BasicAttributes getBasicAttributes(); } diff --git a/source/java/org/alfresco/repo/avm/AVMRepository.java b/source/java/org/alfresco/repo/avm/AVMRepository.java index e205897ab0..a71cb37902 100644 --- a/source/java/org/alfresco/repo/avm/AVMRepository.java +++ b/source/java/org/alfresco/repo/avm/AVMRepository.java @@ -26,6 +26,7 @@ package org.alfresco.repo.avm; import java.io.File; import java.io.InputStream; import java.io.OutputStream; +import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -37,6 +38,7 @@ import java.util.SortedMap; import org.alfresco.repo.content.ContentStore; import org.alfresco.repo.domain.DbAccessControlList; import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.service.cmr.avm.AVMBadArgumentException; import org.alfresco.service.cmr.avm.AVMCycleException; @@ -51,10 +53,15 @@ import org.alfresco.service.cmr.avm.VersionDescriptor; import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; import org.alfresco.util.Pair; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; /** * This or AVMStore are @@ -108,6 +115,10 @@ public class AVMRepository private ChildEntryDAO fChildEntryDAO; + private PermissionService fPermissionService; + + private ApplicationContext fContext; + // A bunch of TransactionListeners that do work for this. /** @@ -224,6 +235,11 @@ public class AVMRepository fChildEntryDAO = dao; } + public void setPermissionService(PermissionService service) + { + fPermissionService = service; + } + /** * Create a file. * @param path The path to the containing directory. @@ -318,6 +334,10 @@ public class AVMRepository { throw new AVMWrongTypeException("Not a directory."); } + if (!can(node, PermissionService.CREATE_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to write in: " + parent); + } // We need the store to do anything so... String [] pathParts = SplitPath(parent.getPath()); AVMStore store = getAVMStoreByName(pathParts[0]); @@ -338,6 +358,8 @@ public class AVMRepository child = new PlainDirectoryNodeImpl(store); } dir.putChild(name, child); + DbAccessControlList acl = dir.getAcl(); + child.setAcl(acl != null ? acl.getCopy() : null); fLookupCache.onWrite(pathParts[0]); AVMNodeDescriptor desc = child.getDescriptor(parent.getPath(), name, parent.getIndirection(), parent.getIndirectionVersion()); return desc; @@ -480,6 +502,10 @@ public class AVMRepository throw new AVMNotFoundException("Path not found."); } DirectoryNode dirNode = (DirectoryNode)dPath.getCurrentNode(); + if (!can(dirNode, PermissionService.ADD_CHILDREN)) + { + throw new AccessDeniedException("Not permitted to add children: " + dstPath); + } AVMNode srcNode = sPath.getCurrentNode(); AVMNode dstNode = null; // We do different things depending on what kind of thing we're @@ -507,6 +533,8 @@ public class AVMRepository dstNode.setAncestor(srcNode); dirNode.putChild(name, dstNode); dirNode.updateModTime(); + DbAccessControlList acl = srcNode.getAcl(); + dstNode.setAcl(acl != null ? acl.getCopy() : null); String beginingPath = AVMNodeConverter.NormalizePath(srcPath); String finalPath = AVMNodeConverter.ExtendAVMPath(dstPath, name); finalPath = AVMNodeConverter.NormalizePath(finalPath); @@ -641,6 +669,10 @@ public class AVMRepository throw new AVMNotFoundException("Path not found."); } srcDir = (DirectoryNode)sPath.getCurrentNode(); + if (!can(srcDir, PermissionService.DELETE_CHILDREN) || !can(srcDir, PermissionService.ADD_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to read or write: " + srcPath); + } Pair temp = srcDir.lookupChild(sPath, srcName, false); srcNode = (temp == null) ? null : temp.getFirst(); if (srcNode == null) @@ -668,6 +700,10 @@ public class AVMRepository throw new AVMNotFoundException("Path not found."); } DirectoryNode dstDir = (DirectoryNode)dPath.getCurrentNode(); + if (!can(dstDir, PermissionService.ADD_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to write: " + dstPath); + } Pair temp = dstDir.lookupChild(dPath, dstName, true); AVMNode child = (temp == null) ? null : temp.getFirst(); if (child != null && child.getType() != AVMNodeType.DELETED_NODE) @@ -864,6 +900,11 @@ public class AVMRepository } fLookupCache.onDelete(name); AVMNode root = store.getRoot(); + // TODO Probably a special PermissionService.PURGE is needed. + if (!can(root, PermissionService.DELETE_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to purge: " + name); + } root.setIsRoot(false); List vRoots = fVersionRootDAO.getAllInAVMStore(store); for (VersionRoot vr : vRoots) @@ -934,6 +975,10 @@ public class AVMRepository { throw new AVMWrongTypeException(desc + " is not a File."); } + if (!can(node, PermissionService.READ_CONTENT)) + { + throw new AccessDeniedException("Not allowed to read content: " + desc); + } FileNode file = (FileNode)node; ContentData data = file.getContentData(null); if (data == null) @@ -1011,6 +1056,10 @@ public class AVMRepository { throw new AVMBadArgumentException("Invalid Node."); } + if (!can(node, PermissionService.READ_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to read children: " + dir); + } if (node.getType() == AVMNodeType.PLAIN_DIRECTORY) { return getListing(dir, includeDeleted); @@ -1043,6 +1092,10 @@ public class AVMRepository { throw new AVMWrongTypeException("Not a directory."); } + if (!can(node, PermissionService.READ_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to read children: " + dir); + } DirectoryNode dirNode = (DirectoryNode)node; SortedMap listing = dirNode.getListing(dir, includeDeleted); return listing; @@ -1305,6 +1358,10 @@ public class AVMRepository throw new AVMWrongTypeException("Not a directory."); } DirectoryNode dirNode = (DirectoryNode)node; + if (!can(dirNode, PermissionService.READ_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to read children: " + dir); + } return dirNode.lookupChild(dir, name, includeDeleted); } finally @@ -1323,7 +1380,7 @@ public class AVMRepository AVMNode node = fAVMNodeDAO.getByID(desc.getId()); if (node == null) { - throw new AVMNotFoundException("Not found: " + desc.getPath()); + throw new AVMNotFoundException("Not found: " + desc); } List> paths = new ArrayList>(); List components = new ArrayList(); @@ -1389,6 +1446,10 @@ public class AVMRepository */ private void recursiveGetVersionPaths(AVMNode node, List components, List paths, DirectoryNode root, String storeName) { + if (!can(node, PermissionService.READ_CHILDREN)) + { + return; + } if (node.equals(root)) { paths.add(this.makePath(components, storeName)); @@ -1422,7 +1483,7 @@ public class AVMRepository AVMNode node = fAVMNodeDAO.getByID(desc.getId()); if (node == null) { - throw new AVMNotFoundException("Not found: " + desc.getPath()); + throw new AVMNotFoundException("Not found: " + desc); } List> paths = new ArrayList>(); List components = new ArrayList(); @@ -1439,6 +1500,10 @@ public class AVMRepository private void recursiveGetPaths(AVMNode node, List components, List> paths) { + if (!can(node, PermissionService.READ_CHILDREN)) + { + return; + } if (node.getIsRoot()) { AVMStore store = fAVMStoreDAO.getByRoot(node); @@ -1472,6 +1537,10 @@ public class AVMRepository */ private Pair recursiveGetAPath(AVMNode node, List components) { + if (!can(node, PermissionService.READ_CHILDREN)) + { + return null; + } if (node.getIsRoot()) { AVMStore store = fAVMStoreDAO.getByRoot(node); @@ -1510,6 +1579,10 @@ public class AVMRepository private void recursiveGetHeadPaths(AVMNode node, List components, List> paths) { + if (!can(node, PermissionService.READ_CHILDREN)) + { + return; + } if (node.getIsRoot()) { AVMStore store = fAVMStoreDAO.getByRoot(node); @@ -1541,6 +1614,10 @@ public class AVMRepository List> paths, DirectoryNode root, String storeName) { + if (!can(node, PermissionService.READ_CHILDREN)) + { + return; + } if (node.equals(root)) { addPath(components, -1, storeName, paths); @@ -1628,6 +1705,10 @@ public class AVMRepository { throw new AVMNotFoundException("Path not found."); } + if (!can(lookup.getCurrentNode(), PermissionService.READ_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to read properties: " + path); + } return new LayeringDescriptor(!lookup.getDirectlyContained(), lookup.getAVMStore().getDescriptor(), lookup.getFinalStore().getDescriptor()); @@ -1752,6 +1833,10 @@ public class AVMRepository { throw new AVMNotFoundException("Not found."); } + if (!can(node, PermissionService.READ_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to read properties: " + desc); + } if (count < 0) { count = Integer.MAX_VALUE; @@ -1764,6 +1849,10 @@ public class AVMRepository { break; } + if (!can(node, PermissionService.READ_PROPERTIES)) + { + break; + } history.add(node.getDescriptor("UNKNOWN", "UNKNOWN", "UNKNOWN", -1)); } return history; @@ -2022,7 +2111,7 @@ public class AVMRepository } /** - * Queries all AVM stores for properties with keys that matcha given pattern. + * Queries all AVM stores for properties with keys that match a given pattern. * @param keyPattern The sql 'like' pattern, inserted into a QName. * @return A List of Pairs of Store name, Map.Entry. */ @@ -2102,6 +2191,16 @@ public class AVMRepository { throw new AVMNotFoundException("Node not found."); } + if (!can(lNode, PermissionService.READ_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to read properties: " + left); + } + if (!can(rNode, PermissionService.READ_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to read properties: " + right); + } + // TODO Short changing the permissions checking here. I'm not sure + // if that's OK. List leftHistory = new ArrayList(); List rightHistory = new ArrayList(); while (lNode != null || rNode != null) @@ -2429,6 +2528,7 @@ public class AVMRepository } } + /** * This is the danger version of link. It must be called on * a copied and unsnapshotted directory. It blithely inserts @@ -2449,6 +2549,10 @@ public class AVMRepository { throw new AVMException("Directory has not already been copied."); } + if (!can(dir, PermissionService.ADD_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to write: " + parent); + } dir.link(name, child); } @@ -2480,6 +2584,10 @@ public class AVMRepository { throw new AVMWrongTypeException("Not a Layered Directory."); } + if (!can(node, PermissionService.DELETE_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to write in: " + path); + } LayeredDirectoryNode dir = (LayeredDirectoryNode)node; dir.flatten(name); } @@ -2661,7 +2769,7 @@ public class AVMRepository AVMNode node = fAVMNodeDAO.getByID(desc.getId()); if (node == null) { - throw new AVMNotFoundException("Not found: " + desc.getPath()); + throw new AVMNotFoundException("Not found: " + desc); } List paths = new ArrayList(); List components = new ArrayList(); @@ -2678,6 +2786,10 @@ public class AVMRepository private void recursiveGetStoreVersionPaths(String storeName, AVMNode node, int version, List components, List paths) { + if (!can(node, PermissionService.READ)) + { + return; + } if (node.getIsRoot()) { VersionRoot versionRoot = fVersionRootDAO.getByRoot(node); @@ -2707,6 +2819,10 @@ public class AVMRepository { throw new AVMNotFoundException("Node not found: " + desc); } + if (!can(node, PermissionService.READ_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to read properties: " + desc); + } return node.getProperties(); } @@ -2717,6 +2833,10 @@ public class AVMRepository { throw new AVMNotFoundException("Node not found: " + desc); } + if (!can(node, PermissionService.READ_CONTENT)) + { + throw new AccessDeniedException("Not allowed to read: " + desc); + } if (node.getType() == AVMNodeType.PLAIN_FILE) { PlainFileNode file = (PlainFileNode)node; @@ -2732,7 +2852,40 @@ public class AVMRepository { throw new AVMNotFoundException("Node not found: " + desc); } + if (!can(node, PermissionService.READ_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to read properties: " + desc); + } Set aspects = node.getAspects(); return aspects; } + + /** + * Evaluate permission on a node. + * I've got a bad feeling about this... + * @param node + * @param permission + * @return + */ + public boolean can(AVMNode node, String permission) + { + DbAccessControlList acl = node.getAcl(); + if (acl == null) + { + return true; + } + Map context = new HashMap(4); + context.put(PermissionService.OWNER_AUTHORITY, node.getBasicAttributes().getOwner()); + context.put(PermissionService.ASPECTS, node.getAspects()); + Map props = node.getProperties(); + Map properties = new HashMap(5); + for (Map.Entry entry : props.entrySet()) + { + properties.put(entry.getKey(), entry.getValue().getValue(entry.getKey())); + } + context.put(PermissionService.PROPERTIES, properties); + // TODO put node type in there to. + return fPermissionService.hasPermission(acl.getId(), context, permission) + == AccessStatus.ALLOWED; + } } diff --git a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java index ee793166b9..84b6826b64 100644 --- a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java @@ -42,6 +42,7 @@ import org.alfresco.repo.avm.util.RawServices; import org.alfresco.repo.avm.util.SimplePath; import org.alfresco.repo.domain.DbAccessControlList; import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.service.cmr.avm.AVMBadArgumentException; import org.alfresco.service.cmr.avm.AVMException; import org.alfresco.service.cmr.avm.AVMExistsException; @@ -57,6 +58,7 @@ import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; import org.alfresco.util.GUID; import org.alfresco.util.Pair; @@ -327,6 +329,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); + if (!fAVMRepository.can(dir, PermissionService.ADD_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to write: " + path); + } Pair temp = dir.lookupChild(lPath, name, true); AVMNode child = (temp == null) ? null : temp.getFirst(); if (child != null && child.getType() != AVMNodeType.DELETED_NODE) @@ -361,6 +367,8 @@ public class AVMStoreImpl implements AVMStore, Serializable { newDir.getProperties().putAll(properties); } + DbAccessControlList acl = dir.getAcl(); + newDir.setAcl(acl != null ? acl.getCopy() : null); } /** @@ -422,6 +430,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); + if (!fAVMRepository.can(dir, PermissionService.ADD_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to write: " + path); + } Pair temp = dir.lookupChild(lPath, name, true); AVMNode child = (temp == null) ? null : temp.getFirst(); if (child != null && child.getType() != AVMNodeType.DELETED_NODE) @@ -440,6 +452,8 @@ public class AVMStoreImpl implements AVMStore, Serializable RawServices.Instance().getMimetypeService().guessMimetype(name), -1, "UTF-8")); + DbAccessControlList acl = dir.getAcl(); + file.setAcl(acl != null ? acl.getCopy() : null); ContentWriter writer = createContentWriter(AVMNodeConverter.ExtendAVMPath(path, name)); return writer.getContentOutputStream(); } @@ -458,6 +472,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); + if (!fAVMRepository.can(dir, PermissionService.ADD_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to write: " + path); + } Pair temp = dir.lookupChild(lPath, name, true); AVMNode child = (temp == null) ? null : temp.getFirst(); if (child != null && child.getType() != AVMNodeType.DELETED_NODE) @@ -484,6 +502,8 @@ public class AVMStoreImpl implements AVMStore, Serializable { file.getProperties().putAll(properties); } + DbAccessControlList acl = dir.getAcl(); + file.setAcl(acl != null ? acl.getCopy() : null); // Yet another flush. AVMDAOs.Instance().fAVMNodeDAO.flush(); ContentWriter writer = createContentWriter(AVMNodeConverter.ExtendAVMPath(path, name)); @@ -504,6 +524,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + dstPath + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); + if (!fAVMRepository.can(dir, PermissionService.ADD_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to write: " + dstPath); + } Pair temp = dir.lookupChild(lPath, name, true); AVMNode child = (temp == null) ? null : temp.getFirst(); if (child != null && child.getType() != AVMNodeType.DELETED_NODE) @@ -519,6 +543,8 @@ public class AVMStoreImpl implements AVMStore, Serializable } dir.updateModTime(); dir.putChild(name, newFile); + DbAccessControlList acl = dir.getAcl(); + newFile.setAcl(acl != null ? acl.getCopy() : null); // newFile.setVersionID(getNextVersionID()); } @@ -580,6 +606,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); + if (!fAVMRepository.can(dir, PermissionService.READ_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to read: " + path); + } Map listing = dir.getListing(lPath, includeDeleted); return translateListing(listing, lPath); } @@ -599,6 +629,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); + if (!fAVMRepository.can(dir, PermissionService.READ_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to read: " + path); + } if (lPath.isLayered() && dir.getType() != AVMNodeType.LAYERED_DIRECTORY) { return new TreeMap(); @@ -642,6 +676,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); + if (!fAVMRepository.can(dir, PermissionService.READ_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to read: " + path); + } List deleted = dir.getDeletedNames(); return deleted; } @@ -670,14 +708,16 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); + if (!fAVMRepository.can(dir, PermissionService.DELETE_CHILDREN)) + { + throw new AVMNotFoundException("Not allowed to write: " + path); + } if (dir.lookupChild(lPath, name, false) == null) { throw new AVMNotFoundException("Does not exist: " + name); } dir.removeChild(lPath, name); dir.updateModTime(); - // AVMDAOs.Instance().fAVMNodeDAO.flush(); - // AVMDAOs.Instance().fAVMNodeDAO.evict(dir); } /** @@ -697,6 +737,10 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMWrongTypeException("Not a layered directory: " + dirPath); } + if (!fAVMRepository.can(node, PermissionService.DELETE_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to write: " + dirPath); + } ((LayeredDirectoryNode)node).uncover(lPath, name); node.updateModTime(); } @@ -792,6 +836,10 @@ public class AVMStoreImpl implements AVMStore, Serializable { root = AVMDAOs.Instance().fAVMNodeDAO.getAVMStoreRoot(this, version); } + if (!fAVMRepository.can(root, PermissionService.READ_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to read: " + fName + "@" + version); + } return root.getDescriptor(fName + ":", "", null, -1); } @@ -837,6 +885,10 @@ public class AVMStoreImpl implements AVMStore, Serializable return null; } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.READ_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to read: " + path); + } if (node.getType() == AVMNodeType.LAYERED_DIRECTORY) { LayeredDirectoryNode dir = (LayeredDirectoryNode)node; @@ -866,6 +918,10 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMException("Not in a layered context: " + path); } + if (!fAVMRepository.can(dir, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write: " + path); + } dir.turnPrimary(lPath); dir.updateModTime(); } @@ -887,6 +943,10 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMException("Not in a layered context: " + path); } + if (!fAVMRepository.can(dir, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write: " + path); + } dir.retarget(lPath, target); dir.updateModTime(); } @@ -1018,6 +1078,10 @@ public class AVMStoreImpl implements AVMStore, Serializable } AVMDAOs.Instance().fVersionLayeredNodeEntryDAO.delete(vRoot); AVMNode root = vRoot.getRoot(); + if (!fAVMRepository.can(root, PermissionService.DELETE_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to purge: " + fName + "@" + version); + } root.setIsRoot(false); AVMDAOs.Instance().fAVMNodeDAO.update(root); AVMDAOs.Instance().fVersionRootDAO.delete(vRoot); @@ -1031,6 +1095,7 @@ public class AVMStoreImpl implements AVMStore, Serializable } } + // TODO permissions? /** * Get the descriptor for this. * @return An AVMStoreDescriptor @@ -1060,6 +1125,10 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMWrongTypeException("Not a LayeredDirectoryNode."); } + if (!fAVMRepository.can(node, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write: " + path); + } ((LayeredDirectoryNode)node).setOpacity(opacity); node.updateModTime(); } @@ -1079,6 +1148,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write: " + path); + } node.setProperty(name, value); node.setGuid(GUID.generate()); } @@ -1096,6 +1169,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write: " + path); + } node.addProperties(properties); node.setGuid(GUID.generate()); } @@ -1115,6 +1192,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.READ_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to read: " + path); + } PropertyValue prop = node.getProperty(name); return prop; } @@ -1133,6 +1214,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.READ_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to read: " + path); + } Map props = node.getProperties(); return props; } @@ -1150,6 +1235,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write: " + path); + } node.setGuid(GUID.generate()); node.deleteProperty(name); } @@ -1166,6 +1255,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write: " + path); + } node.setGuid(GUID.generate()); node.deleteProperties(); } @@ -1254,6 +1347,10 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMWrongTypeException("File Expected."); } + if (!fAVMRepository.can(node, PermissionService.READ_CONTENT)) + { + throw new AccessDeniedException("Not allowed to read: " + path); + } ContentData content = ((FileNode)node).getContentData(lPath); // AVMDAOs.Instance().fAVMNodeDAO.flush(); // AVMDAOs.Instance().fAVMNodeDAO.evict(node); @@ -1277,6 +1374,11 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMWrongTypeException("File Expected."); } + if (!fAVMRepository.can(node, PermissionService.WRITE_CONTENT)) + { + throw new AccessDeniedException("Not allowed to write content: " + path); + } + // TODO Set modifier. node.updateModTime(); node.setGuid(GUID.generate()); ContentData content = ((FileNode)node).getContentData(lPath); @@ -1285,6 +1387,8 @@ public class AVMStoreImpl implements AVMStore, Serializable return content; } + // Not doing permission checking because it will already have been done + // at the getContentDataForWrite point. /** * Set the ContentData for a file. * @param path The path to the file. @@ -1318,6 +1422,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path not found: " + path); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write properties: " + path); + } node.copyMetaDataFrom(from); node.setGuid(GUID.generate()); } @@ -1335,6 +1443,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write: " + path); + } node.getAspects().add(aspectName); node.setGuid(GUID.generate()); } @@ -1353,6 +1465,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.READ_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to read properties: " + path); + } Set aspects = node.getAspects(); return aspects; } @@ -1370,6 +1486,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write properties: " + path); + } node.getAspects().remove(aspectName); AspectDefinition def = RawServices.Instance().getDictionaryService().getAspect(aspectName); Map properties = @@ -1396,6 +1516,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.READ_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to read properties: " + path); + } boolean has = node.getAspects().contains(aspectName); return has; } @@ -1413,6 +1537,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.CHANGE_PERMISSIONS)) + { + throw new AccessDeniedException("Not allowed to change permissions: " + path); + } node.setAcl(acl); node.setGuid(GUID.generate()); } @@ -1430,6 +1558,10 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMNotFoundException("Path " + path + " not found."); } + if (!fAVMRepository.can(lPath.getCurrentNode(), PermissionService.READ_PERMISSIONS)) + { + throw new AccessDeniedException("Not allowed to read permissions: " + path); + } return lPath.getCurrentNode().getAcl(); } @@ -1447,9 +1579,11 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + parentPath + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); + if (!fAVMRepository.can(dir, PermissionService.ADD_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to add children: " + parentPath); + } dir.link(lPath, name, toLink); - //AVMDAOs.Instance().fAVMNodeDAO.flush(); - //AVMDAOs.Instance().fAVMNodeDAO.evict(dir); } /** @@ -1468,6 +1602,11 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); + if (!fAVMRepository.can(dir, PermissionService.DELETE_CHILDREN) || + !fAVMRepository.can(dir, PermissionService.ADD_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to revert: " + path); + } Pair temp = dir.lookupChild(lPath, name, true); AVMNode child = (temp == null) ? null : temp.getFirst(); if (child == null) @@ -1500,6 +1639,10 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path not found: " + path); } AVMNode node = lPath.getCurrentNode(); + if (!fAVMRepository.can(node, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write properties: " + path); + } node.setGuid(guid); } @@ -1518,6 +1661,10 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMWrongTypeException("Not a File: " + path); } + if (!fAVMRepository.can(node, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write properties: " + path); + } PlainFileNode file = (PlainFileNode)node; file.setEncoding(encoding); } @@ -1537,6 +1684,10 @@ public class AVMStoreImpl implements AVMStore, Serializable { throw new AVMWrongTypeException("Not a File: " + path); } + if (!fAVMRepository.can(node, PermissionService.WRITE_PROPERTIES)) + { + throw new AccessDeniedException("Not allowed to write properties: " + path); + } PlainFileNode file = (PlainFileNode)node; file.setMimeType(mimeType); } diff --git a/source/java/org/alfresco/repo/avm/AvmBootstrap.java b/source/java/org/alfresco/repo/avm/AvmBootstrap.java index 0782a1dae1..415668073b 100644 --- a/source/java/org/alfresco/repo/avm/AvmBootstrap.java +++ b/source/java/org/alfresco/repo/avm/AvmBootstrap.java @@ -15,11 +15,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ package org.alfresco.repo.avm; @@ -27,6 +27,7 @@ package org.alfresco.repo.avm; import java.util.ArrayList; import java.util.List; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.util.AbstractLifecycleBean; import org.springframework.context.ApplicationEvent; @@ -34,31 +35,45 @@ import org.springframework.context.ApplicationEvent; * This component ensures that the AVM system is properly bootstrapped * and that this is done in the correct order relative to other * bootstrap components. - * + * * @see #setIssuers(List) * @see org.alfresco.repo.avm.Issuer - * + * * @author Derek Hulley */ public class AvmBootstrap extends AbstractLifecycleBean { private List issuers; - + private AVMLockingAwareService avmLockingAwareService; - + + private AVMRepository avmRepository; + + private PermissionService permissionService; + public AvmBootstrap() { issuers = new ArrayList(0); } - + public void setAvmLockingAwareService(AVMLockingAwareService service) { avmLockingAwareService = service; } + public void setAvmRepository(AVMRepository repository) + { + avmRepository = repository; + } + + public void setPermissionService(PermissionService service) + { + permissionService = service; + } + /** * Provide a list of {@link Issuer issuers} to bootstrap on context initialization. - * + * * @see #onBootstrap(ApplicationEvent) */ public void setIssuers(List issuers) @@ -77,6 +92,7 @@ public class AvmBootstrap extends AbstractLifecycleBean issuer.initialize(); } avmLockingAwareService.init(); + avmRepository.setPermissionService(permissionService); } /** NO-OP */ diff --git a/source/java/org/alfresco/repo/avm/LookupCache.java b/source/java/org/alfresco/repo/avm/LookupCache.java index 542014316f..e4cab06e38 100644 --- a/source/java/org/alfresco/repo/avm/LookupCache.java +++ b/source/java/org/alfresco/repo/avm/LookupCache.java @@ -8,6 +8,8 @@ import java.util.List; import org.alfresco.repo.avm.util.SimplePath; import org.alfresco.repo.cache.SimpleCache; +import org.alfresco.repo.security.permissions.AccessDeniedException; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.util.Pair; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -107,7 +109,10 @@ public class LookupCache else { VersionRoot vRoot = AVMDAOs.Instance().fVersionRootDAO.getByVersionID(store, version); - dir = vRoot.getRoot(); + if (vRoot != null) + { + dir = vRoot.getRoot(); + } // dir = fAVMNodeDAO.getAVMStoreRoot(store, version); } if (dir == null) @@ -127,6 +132,10 @@ public class LookupCache // before the end. for (int i = 0; i < path.size() - 1; i++) { + if (!AVMRepository.GetInstance().can(dir, PermissionService.READ_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to read children: " + path.get(i)); + } Pair child = dir.lookupChild(result, path.get(i), includeDeleted); if (child == null) { @@ -142,6 +151,10 @@ public class LookupCache dir = (DirectoryNode)result.getCurrentNode(); } // Now look up the last element. + if (!AVMRepository.GetInstance().can(dir, PermissionService.READ_CHILDREN)) + { + throw new AccessDeniedException("Not allowed to read children: " + path.get(path.size() - 1)); + } Pair child = dir.lookupChild(result, path.get(path.size() - 1), includeDeleted); if (child == null) diff --git a/source/java/org/alfresco/repo/clt/CltBase.java b/source/java/org/alfresco/repo/clt/CltBase.java index c7dee7138e..769de0a0c1 100644 --- a/source/java/org/alfresco/repo/clt/CltBase.java +++ b/source/java/org/alfresco/repo/clt/CltBase.java @@ -1,5 +1,5 @@ /** - * + * */ package org.alfresco.repo.clt; @@ -12,7 +12,6 @@ import java.util.List; import java.util.Map; import org.alfresco.repo.remote.ClientTicketHolder; -import org.alfresco.repo.remote.ClientTicketHolderGlobal; import org.alfresco.service.cmr.avmsync.AVMSyncService; import org.alfresco.service.cmr.remote.AVMRemote; import org.alfresco.service.cmr.remote.RepoRemote; @@ -25,13 +24,13 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; * This is the base class for AVM clts. * @author britt */ -public abstract class CltBase +public abstract class CltBase { /** * The instance of the remote interface. */ protected AVMRemote fAVMRemote; - + /** * The instance of the remote sync service interface. */ @@ -41,31 +40,31 @@ public abstract class CltBase * The instance of the remote repo interface. */ protected RepoRemote fRepoRemote; - + /** * The ApplicationContext. */ protected ConfigurableApplicationContext fContext; - + /** * The Authentication Service. */ protected AuthenticationService fAuthenticationService; - + /** * The usage string. */ private String fUsage; - + /** * Construct a new one. This takes care of instantiating * the application context and grabs references to the - * services. + * services. * @param args The program arguments. */ protected CltBase() { - fContext = new ClassPathXmlApplicationContext("alfresco/clt-context.xml"); + fContext = new ClassPathXmlApplicationContext("clt-context.xml"); fAVMRemote = (AVMRemote)fContext.getBean("avmRemote"); fAVMSyncService = (AVMSyncService)fContext.getBean("avmSyncService"); fRepoRemote = (RepoRemote)fContext.getBean("repoRemote"); @@ -74,19 +73,19 @@ public abstract class CltBase String ticket = fAuthenticationService.getCurrentTicket(); ((ClientTicketHolder)fContext.getBean("clientTicketHolder")).setTicket(ticket); } - + /** - * All clts go through this call. This parses the arguments, exits if + * All clts go through this call. This parses the arguments, exits if * there are any errors and then passes the broken flags and arguments * to the run method of the derived clt. * @param args The raw command line arguments. * @param flagDefs The definition of what flags to accept and their * arities. * @param minArgs The minimum number of actual arguments expected. - * @param usageMessage The message that should be printed if there is a + * @param usageMessage The message that should be printed if there is a * syntax error. */ - public void exec(String [] args, + public void exec(String [] args, Object [] flagDefs, int minArgs, String usageMessage) @@ -144,7 +143,7 @@ public abstract class CltBase // Cleanup. fContext.close(); } - + /** * Handle syntax error by exiting. */ @@ -154,7 +153,7 @@ public abstract class CltBase fContext.close(); System.exit(1); } - + /** * Utility to split an AVM path into a parent path and a * base name. @@ -189,7 +188,7 @@ public abstract class CltBase String [] ret = { parent, name }; return ret; } - + protected void copyStream(InputStream in, OutputStream out) { try @@ -210,7 +209,7 @@ public abstract class CltBase System.exit(1); } } - + protected Pair splitPathVersion(String pathVersion) { int index = pathVersion.lastIndexOf('@'); @@ -222,6 +221,6 @@ public abstract class CltBase int version = Integer.parseInt(pathVersion.substring(index + 1)); return new Pair(path, version); } - + protected abstract void run(Map> flags, List args); } diff --git a/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceImpl.java b/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceImpl.java index eb453f31e5..3c6a1d2ee0 100644 --- a/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceImpl.java +++ b/source/java/org/alfresco/repo/security/permissions/impl/PermissionServiceImpl.java @@ -15,11 +15,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing */ package org.alfresco.repo.security.permissions.impl; @@ -64,7 +64,7 @@ import org.springframework.beans.factory.InitializingBean; /** * The Alfresco implementation of a permissions service against our APIs for the permissions model and permissions * persistence. - * + * * @author andyh */ public class PermissionServiceImpl implements PermissionServiceSPI, InitializingBean @@ -174,7 +174,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing /** * Set the permissions access cache. - * + * * @param accessCache * a transactionally safe cache */ @@ -396,6 +396,16 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing return status; } + /* (non-Javadoc) + * @see org.alfresco.service.cmr.security.PermissionService#hasPermission(java.lang.Long, java.lang.String, java.lang.String) + */ + public AccessStatus hasPermission(Long aclID, Map context, + String permission) + { + // TODO Implement. + return AccessStatus.ALLOWED; + } + enum CacheType { HAS_PERMISSION, SINGLE_PERMISSION, SINGLE_PERMISSION_GLOBAL; @@ -417,7 +427,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing /** * Get the authorisations for the currently authenticated user - * + * * @param auth * @return */ @@ -602,7 +612,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing /** * Support class to test the permission on a node. - * + * * @author Andy Hind */ private class NodeTest @@ -675,7 +685,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing /** * External hook point - * + * * @param authorisations * @param nodeRef * @return @@ -688,7 +698,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing /** * Internal hook point for recursion - * + * * @param authorisations * @param nodeRef * @param denied @@ -716,7 +726,6 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing if (checkGlobalPermissions(authorisations) || checkRequired(authorisations, nodeRef, locallyDenied)) { // No need to do the recursive test as it has been found - recursiveOut = null; if (recursiveIn != null) { recursiveIn.setValue(true); @@ -934,7 +943,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing /** * Check if we have a global permission - * + * * @param authorisations * @return */ @@ -952,7 +961,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing /** * Get the list of permissions denied for this node. - * + * * @param nodeRef * @return */ @@ -1002,7 +1011,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing /** * Check that a given authentication is available on a node - * + * * @param authorisations * @param nodeRef * @param denied @@ -1032,7 +1041,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing /** * Is a permission granted - * + * * @param pe - * the permissions entry to consider * @param granters - @@ -1106,7 +1115,7 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing /** * Helper class to store a pair of objects which may be null - * + * * @author Andy Hind */ private static class Pair diff --git a/source/java/org/alfresco/repo/security/permissions/noop/PermissionServiceNOOPImpl.java b/source/java/org/alfresco/repo/security/permissions/noop/PermissionServiceNOOPImpl.java index 62dcf33843..f70e1e5cb3 100644 --- a/source/java/org/alfresco/repo/security/permissions/noop/PermissionServiceNOOPImpl.java +++ b/source/java/org/alfresco/repo/security/permissions/noop/PermissionServiceNOOPImpl.java @@ -15,11 +15,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ package org.alfresco.repo.security.permissions.noop; @@ -41,12 +41,12 @@ import org.alfresco.service.namespace.QName; /** * Dummy implementation of Permissions Service - * + * */ public class PermissionServiceNOOPImpl implements PermissionServiceSPI { - + /* (non-Javadoc) * @see org.alfresco.repo.security.permissions.PermissionService#getOwnerAuthority() */ @@ -69,8 +69,8 @@ public class PermissionServiceNOOPImpl public String getAllPermission() { return ALL_PERMISSIONS; - } - + } + /* (non-Javadoc) * @see org.alfresco.repo.security.permissions.PermissionService#getPermissions(org.alfresco.service.cmr.repository.NodeRef) */ @@ -140,7 +140,7 @@ public class PermissionServiceNOOPImpl public void setInheritParentPermissions(NodeRef nodeRef, boolean inheritParentPermissions) { } - + /* (non-Javadoc) * @see org.alfresco.service.cmr.security.PermissionService#getInheritParentPermissions(org.alfresco.service.cmr.repository.NodeRef) */ @@ -152,24 +152,24 @@ public class PermissionServiceNOOPImpl public void clearPermission(NodeRef nodeRef, String authority) { - + } // SPI - + public void deletePermission(PermissionEntry permissionEntry) { - + } public void deletePermissions(NodePermissionEntry nodePermissionEntry) { - + } public void deletePermissions(String recipient) { - + } public NodePermissionEntry explainPermission(NodeRef nodeRef, PermissionReference perm) @@ -217,6 +217,15 @@ public class PermissionServiceNOOPImpl throw new UnsupportedOperationException(); } + /* (non-Javadoc) + * @see org.alfresco.service.cmr.security.PermissionService#hasPermission(java.lang.Long, java.lang.String, java.lang.String) + */ + public AccessStatus hasPermission(Long aclID, Map context, + String permission) + { + return AccessStatus.ALLOWED; + } + public void setPermission(NodePermissionEntry nodePermissionEntry) { throw new UnsupportedOperationException(); diff --git a/source/java/org/alfresco/service/cmr/security/PermissionService.java b/source/java/org/alfresco/service/cmr/security/PermissionService.java index 5d7a218a9e..55b428b95b 100644 --- a/source/java/org/alfresco/service/cmr/security/PermissionService.java +++ b/source/java/org/alfresco/service/cmr/security/PermissionService.java @@ -15,11 +15,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ package org.alfresco.service.cmr.security; @@ -35,7 +35,7 @@ import org.apache.axis.wsdl.symbolTable.Parameters; /** * The public API for a permission service The implementation may be changed in the application configuration - * + * * @author Andy Hind */ @PublicService @@ -149,9 +149,13 @@ public interface PermissionService public static final String CANCEL_CHECK_OUT = "CancelCheckOut"; + public static final String ASPECTS = "Aspects"; + + public static final String PROPERTIES = "Properties"; + /** * Get the Owner Authority - * + * * @return the owner authority */ @Auditable @@ -159,7 +163,7 @@ public interface PermissionService /** * Get the All Authorities - * + * * @return the All authorities */ @Auditable @@ -167,7 +171,7 @@ public interface PermissionService /** * Get the All Permission - * + * * @return the All permission */ @Auditable @@ -175,7 +179,7 @@ public interface PermissionService /** * Get all the AccessPermissions that are granted/denied to the current authentication for the given node - * + * * @param nodeRef - * the reference to the node * @return the set of allowed permissions @@ -185,7 +189,7 @@ public interface PermissionService /** * Get all the AccessPermissions that are set for anyone for the given node - * + * * @param nodeRef - * the reference to the node * @return the set of allowed permissions @@ -195,7 +199,7 @@ public interface PermissionService /** * Get the permissions that can be set for a given node - * + * * @param nodeRef * @return */ @@ -204,7 +208,7 @@ public interface PermissionService /** * Get the permissions that can be set for a given type - * + * * @param type * @return - set of permissions */ @@ -214,7 +218,7 @@ public interface PermissionService /** * Check that the given authentication has a particular permission for the given node. (The default behaviour is to * inherit permissions) - * + * * @param nodeRef * @param permission * @return - access status @@ -222,9 +226,19 @@ public interface PermissionService @Auditable(key = Auditable.Key.ARG_0, parameters = { "nodeRef", "permission" }) public AccessStatus hasPermission(NodeRef nodeRef, String permission); + /** + * Check if a permission is allowed on an acl. + * @param aclID + * @param owner + * @param permission + * @return + */ + @Auditable(parameters = { "aclID", "context", "permission" }) + public AccessStatus hasPermission(Long aclID, Map context, String permission); + /** * Delete all the permission assigned to the node - * + * * @param nodeRef */ @Auditable(key = Auditable.Key.ARG_0, parameters = { "nodeRef" }) @@ -232,7 +246,7 @@ public interface PermissionService /** * Delete all permission for the given authority. - * + * * @param nodeRef * @param authority * (if null then this will match all authorities) @@ -248,7 +262,7 @@ public interface PermissionService *
  • entries for all authorities that have a specific permission (if the authority is null); and *
  • all permissions set for the node (if both the permission and authority are null). * - * + * * @param nodeRef * the node that the entry applies to * @param authority @@ -261,7 +275,7 @@ public interface PermissionService /** * Set a specific permission on a node. - * + * * @param nodeRef * @param authority * @param permission @@ -272,7 +286,7 @@ public interface PermissionService /** * Set the global inheritance behaviour for permissions on a node. - * + * * @param nodeRef * @param inheritParentPermissions */ @@ -281,7 +295,7 @@ public interface PermissionService /** * Return the global inheritance behaviour for permissions on a node. - * + * * @param nodeRef * @return inheritParentPermissions */ @@ -290,7 +304,7 @@ public interface PermissionService /** * Get all permissions set for the current user. - * + * * @return - A map of noderefs to permissions set */ @Auditable @@ -298,7 +312,7 @@ public interface PermissionService /** * Get all the permissions set for the given authority - * + * * @param authority * @return - A map of noderefs to permissions set */ @@ -307,7 +321,7 @@ public interface PermissionService /** * Find all the nodes where the current user has explicitly been assigned the specified permission. - * + * * @param permission - * the permission to find * @param allow @@ -324,7 +338,7 @@ public interface PermissionService /** * Find all the nodes where the current user has explicitly been assigned the specified permission. - * + * * @param permission - * the permission to find * @param allow