RM-523: Installation: Impossible to install RM module without -force option

* overriden file removed from both AMPs
 * alternative solution found for hard coded "read" permission checks
 * build scripts updated to remove --force parameter
 * MMT dependancies updated (need to grab these from Maven at some point if possible)



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/BRANCHES/V2.0@42779 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2012-10-18 07:08:22 +00:00
parent 74fdad1905
commit d016261614
13 changed files with 30 additions and 714 deletions

View File

@@ -301,7 +301,7 @@ subprojects {
mmt = new org.alfresco.repo.module.tool.ModuleManagementTool() mmt = new org.alfresco.repo.module.tool.ModuleManagementTool()
mmt.setVerbose(true) mmt.setVerbose(true)
mmt.installModule(ampFileLocation.getPath(), warFileLocation.getPath(), false, true, false) mmt.installModule(ampFileLocation.getPath(), warFileLocation.getPath(), false, false, false)
} }
task cleanDeploy(type: Delete) { task cleanDeploy(type: Delete) {

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
mmt/truezip-file-7.5.5.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
mmt/truezip-swing-7.5.5.jar Normal file

Binary file not shown.

BIN
mmt/xz-1.0.jar Normal file

Binary file not shown.

View File

@@ -1,264 +0,0 @@
const REQUEST_MAX = 1000;
/**
* Main entry point: Create collection of documents and folders in the given space
*
* @method doclist_main
*/
function doclist_main()
{
// Use helper function to get the arguments
var parsedArgs = ParseArgs.getParsedArgs();
if (parsedArgs === null)
{
return;
}
var filter = args.filter,
items = [];
// Try to find a filter query based on the passed-in arguments
var allNodes = [],
totalRecords = 0,
requestTotalCountMax = 0,
paged = false,
favourites = Common.getFavourites(),
filterParams = Filters.getFilterParams(filter, parsedArgs,
{
favourites: favourites
}),
query = filterParams.query;
if ((filter || "path") == "path")
{
// TODO also add DB filter by "node" (in addition to "path")
var parentNode = parsedArgs.pathNode;
if (parentNode !== null)
{
var skip = -1,
max = -1;
if (args.size != null)
{
max = args.size;
if (args.pos > 0)
{
skip = (args.pos - 1) * max;
}
}
var sortField = (args.sortField == null ? "cm:name" : args.sortField),
sortAsc = (((args.sortAsc == null) || (args.sortAsc == "true")) ? true : false);
// Get paged set
requestTotalCountMax = skip + REQUEST_MAX;
var pagedResult = parentNode.childFileFolders(true, true, filterParams.ignoreTypes, skip, max, requestTotalCountMax, sortField, sortAsc, "TODO");
allNodes = pagedResult.page;
totalRecords = pagedResult.totalResultCountUpper;
paged = true;
}
}
else
{
// Query the nodes - passing in sort and result limit parameters
if (query !== "")
{
allNodes = search.query(
{
query: query,
language: filterParams.language,
page:
{
maxItems: (filterParams.limitResults ? parseInt(filterParams.limitResults, 10) : 0)
},
sort: filterParams.sort,
templates: filterParams.templates,
namespace: (filterParams.namespace ? filterParams.namespace : null)
});
totalRecords = allNodes.length;
}
}
// Ensure folders and folderlinks appear at the top of the list
var folderNodes = [],
documentNodes = [];
for each (node in allNodes)
{
try
{
if (node.isContainer || node.isLinkToContainer)
{
folderNodes.push(node);
}
else
{
documentNodes.push(node);
}
}
catch (e)
{
// Possibly an old indexed node - ignore it
}
}
// Node type counts
var folderNodesCount = folderNodes.length,
documentNodesCount = documentNodes.length,
nodes;
if (parsedArgs.type === "documents")
{
nodes = documentNodes;
totalRecords -= folderNodesCount;
}
else
{
// TODO: Sorting with folders at end -- swap order of concat()
nodes = folderNodes.concat(documentNodes);
}
// Pagination
var pageSize = args.size || nodes.length,
pagePos = args.pos || "1",
startIndex = (pagePos - 1) * pageSize;
if (!paged)
{
// Trim the nodes array down to the page size
nodes = nodes.slice(startIndex, pagePos * pageSize);
}
// Common or variable parent container?
var parent = null;
if (!filterParams.variablePath)
{
// Parent node permissions (and Site role if applicable)
parent = Evaluator.run(parsedArgs.pathNode, true);
}
var isThumbnailNameRegistered = thumbnailService.isThumbnailNameRegistered(THUMBNAIL_NAME),
thumbnail = null,
locationNode,
item;
// Loop through and evaluate each node in this result set
for each (node in nodes)
{
// Get evaluated properties.
item = Evaluator.run(node);
if (item !== null)
{
item.isFavourite = (favourites[item.node.nodeRef] === true);
item.likes = Common.getLikes(node);
// Does this collection of nodes have potentially differering paths?
if (filterParams.variablePath || item.isLink)
{
locationNode = item.isLink ? item.linkedNode : item.node;
location = Common.getLocation(locationNode, parsedArgs.libraryRoot);
// Parent node
if (node.parent != null &&
(node.parent.hasPermission("Read") || node.parent.hasPermission("ReadRecords")))
{
item.parent = Evaluator.run(node.parent, true);
}
}
else
{
location =
{
site: parsedArgs.location.site,
siteTitle: parsedArgs.location.siteTitle,
sitePreset: parsedArgs.location.sitePreset,
container: parsedArgs.location.container,
containerType: parsedArgs.location.containerType,
path: parsedArgs.location.path,
file: node.name
};
}
// Resolved location
item.location = location;
// Check: thumbnail type is registered && node is a cm:content subtype && valid inputStream for content property
if (isThumbnailNameRegistered && item.node.isSubType("cm:content") && item.node.properties.content.inputStream != null)
{
// Make sure we have a thumbnail.
thumbnail = item.node.getThumbnail(THUMBNAIL_NAME);
if (thumbnail === null)
{
// No thumbnail, so queue creation
item.node.createThumbnail(THUMBNAIL_NAME, true);
}
}
items.push(item);
}
else
{
--totalRecords;
}
}
// Array Remove - By John Resig (MIT Licensed)
var fnArrayRemove = function fnArrayRemove(array, from, to)
{
var rest = array.slice((to || from) + 1 || array.length);
array.length = from < 0 ? array.length + from : from;
return array.push.apply(array, rest);
};
/**
* De-duplicate orignals for any existing working copies.
* This can't be done in evaluator.lib.js as it has no knowledge of the current filter or UI operation.
* Note: This may result in pages containing less than the configured amount of items (50 by default).
*/
for each (item in items)
{
if (item.workingCopy.isWorkingCopy)
{
var workingCopySource = String(item.workingCopy.sourceNodeRef);
for (var i = 0, ii = items.length; i < ii; i++)
{
if (String(items[i].node.nodeRef) == workingCopySource)
{
fnArrayRemove(items, i);
--totalRecords;
break;
}
}
}
}
var paging =
{
totalRecords: totalRecords,
startIndex: startIndex
};
if (paged && (totalRecords == requestTotalCountMax))
{
paging.totalRecordsUpper = requestTotalCountMax;
}
return (
{
luceneQuery: query,
paging: paging,
container: parsedArgs.rootNode,
parent: parent,
onlineEditing: utils.moduleInstalled("org.alfresco.module.vti"),
itemCount:
{
folders: folderNodesCount,
documents: documentNodesCount
},
items: items,
customJSON: slingshotDocLib.getJSON()
});
}

View File

@@ -1,77 +0,0 @@
<import resource="classpath:/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary-v2/evaluator.lib.js">
<import resource="classpath:/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary-v2/parse-args.lib.js">
/**
* Main entry point: Return single document or folder given it's nodeRef
*
* @method getDoclist
*/
function getDoclist()
{
// Use helper function to get the arguments
var parsedArgs = ParseArgs.getParsedArgs();
if (parsedArgs === null)
{
return;
}
parsedArgs.pathNode = ParseArgs.resolveNode(parsedArgs.nodeRef);
parsedArgs.location = Common.getLocation(parsedArgs.pathNode, parsedArgs.libraryRoot);
var favourites = Common.getFavourites(),
node = parsedArgs.pathNode;
var isThumbnailNameRegistered = thumbnailService.isThumbnailNameRegistered(THUMBNAIL_NAME),
thumbnail = null,
item = Evaluator.run(node);
item.isFavourite = (favourites[node.nodeRef] === true);
item.likes = Common.getLikes(node);
item.location =
{
site: parsedArgs.location.site,
siteTitle: parsedArgs.location.siteTitle,
container: parsedArgs.location.container,
containerType: parsedArgs.location.containerType,
path: parsedArgs.location.path,
file: node.name
};
item.parent = {};
if (node.parent != null && (node.parent.hasPermission("Read") || node.parent.hasPermission("ReadRecords")))
{
item.parent = Evaluator.run(node.parent, true);
}
// Special case for container and libraryRoot nodes
if ((parsedArgs.location.containerNode && String(parsedArgs.location.containerNode.nodeRef) == String(node.nodeRef)) ||
(parsedArgs.libraryRoot && String(parsedArgs.libraryRoot.nodeRef) == String(node.nodeRef)))
{
item.location.file = "";
}
// Check: thumbnail type is registered && node is a cm:content subtype && valid inputStream for content property
if (isThumbnailNameRegistered && item.node.isSubType("cm:content") && item.node.properties.content.inputStream != null)
{
// Make sure we have a thumbnail.
thumbnail = item.node.getThumbnail(THUMBNAIL_NAME);
if (thumbnail === null)
{
// No thumbnail, so queue creation
item.node.createThumbnail(THUMBNAIL_NAME, true);
}
}
return (
{
container: parsedArgs.rootNode,
onlineEditing: utils.moduleInstalled("org.alfresco.module.vti"),
item: item,
customJSON: slingshotDocLib.getJSON()
});
}
/**
* Document List Component: doclist
*/
model.doclist = getDoclist();

View File

@@ -1,370 +0,0 @@
package org.alfresco.module.org_alfresco_module_rm.permission;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.domain.permissions.AclDAO;
import org.alfresco.repo.security.permissions.AccessControlEntry;
import org.alfresco.repo.security.permissions.AccessControlList;
import org.alfresco.repo.security.permissions.PermissionEntry;
import org.alfresco.repo.security.permissions.PermissionReference;
import org.alfresco.repo.security.permissions.impl.ModelDAO;
import org.alfresco.repo.security.permissions.impl.PermissionServiceImpl;
import org.alfresco.repo.security.permissions.impl.RequiredPermission;
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
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;
public class OtherImpl extends PermissionServiceImpl
{
static SimplePermissionReference RM_OLD_ALL_PERMISSIONS_REFERENCE = SimplePermissionReference.getPermissionReference(
QName.createQName("", PermissionService.ALL_PERMISSIONS),
PermissionService.ALL_PERMISSIONS);
private SimpleCache<Serializable, Set<String>> rmReadersCache;
private AclDAO rmAclDaoComponent;
private ModelDAO rmModelDao;
public void setRmReadersCache(SimpleCache<Serializable, Set<String>> rmReadersCache)
{
this.rmReadersCache = rmReadersCache;
}
public void setRmAclDAO(AclDAO rmAclDaoComponent)
{
this.rmAclDaoComponent = rmAclDaoComponent;
}
public void setRmModelDAO(ModelDAO rmModelDao)
{
this.rmModelDao = rmModelDao;
}
@Override
public void setAnyDenyDenies(boolean anyDenyDenies)
{
super.setAnyDenyDenies(anyDenyDenies);
rmReadersCache.clear();
}
@Override
public Set<String> getReaders(Long aclId)
{
Set<String> dmReaders = super.getReaders(aclId);
Set<String> rmReaders = rmReadersCache.get(aclId);
if (rmReaders == null)
{
rmReaders = buildRMReaders(aclId);
rmReadersCache.put(aclId, rmReaders);
}
Set<String> result = new HashSet<String>();
result.addAll(dmReaders);
result.addAll(rmReaders);
return result;
}
private Set<String> buildRMReaders(Long aclId)
{
AccessControlList acl = rmAclDaoComponent.getAccessControlList(aclId);
if (acl == null)
{
return Collections.emptySet();
}
HashSet<String> assigned = new HashSet<String>();
HashSet<String> readers = new HashSet<String>();
for (AccessControlEntry ace : acl.getEntries())
{
assigned.add(ace.getAuthority());
}
PermissionReference permissionRef = getPermissionReference(RMPermissionModel.READ_RECORDS);
for (String authority : assigned)
{
RMUnconditionalAclTest rmTest = new RMUnconditionalAclTest(permissionRef);
if (rmTest.evaluate(authority, aclId))
{
readers.add(authority);
}
}
return Collections.unmodifiableSet(readers);
}
/**
* Ignores type and aspect requirements on the node
*
*/
private class RMUnconditionalAclTest
{
/*
* The required permission.
*/
PermissionReference required;
/*
* Granters of the permission
*/
Set<PermissionReference> granters;
/*
* The additional permissions required at the node level.
*/
Set<PermissionReference> nodeRequirements = new HashSet<PermissionReference>();
/*
* Constructor just gets the additional requirements
*/
RMUnconditionalAclTest(PermissionReference required)
{
this.required = required;
// Set the required node permissions
if (required.equals(getPermissionReference(ALL_PERMISSIONS)))
{
nodeRequirements = rmModelDao.getUnconditionalRequiredPermissions(getPermissionReference(PermissionService.FULL_CONTROL), RequiredPermission.On.NODE);
}
else
{
nodeRequirements = rmModelDao.getUnconditionalRequiredPermissions(required, RequiredPermission.On.NODE);
}
if (rmModelDao.getUnconditionalRequiredPermissions(required, RequiredPermission.On.PARENT).size() > 0)
{
throw new IllegalStateException("Parent permissions can not be checked for an acl");
}
if (rmModelDao.getUnconditionalRequiredPermissions(required, RequiredPermission.On.CHILDREN).size() > 0)
{
throw new IllegalStateException("Child permissions can not be checked for an acl");
}
// Find all the permissions that grant the allowed permission
// All permissions are treated specially.
granters = new LinkedHashSet<PermissionReference>(128, 1.0f);
granters.addAll(rmModelDao.getGrantingPermissions(required));
granters.add(getAllPermissionReference());
granters.add(RM_OLD_ALL_PERMISSIONS_REFERENCE);
}
/**
* Internal hook point for recursion
*
* @param authorisations
* @param nodeRef
* @param denied
* @param recursiveIn
* @return true if granted
*/
boolean evaluate(String authority, Long aclId)
{
// Start out true and "and" all other results
boolean success = true;
// Check the required permissions but not for sets they rely on
// their underlying permissions
//if (modelDAO.checkPermission(required))
//{
// We have to do the test as no parent will help us out
success &= hasSinglePermission(authority, aclId);
if (!success)
{
return false;
}
//}
// Check the other permissions required on the node
for (PermissionReference pr : nodeRequirements)
{
// Build a new test
RMUnconditionalAclTest nt = new RMUnconditionalAclTest(pr);
success &= nt.evaluate(authority, aclId);
if (!success)
{
return false;
}
}
return success;
}
boolean hasSinglePermission(String authority, Long aclId)
{
// Check global permission
if (checkGlobalPermissions(authority))
{
return true;
}
if(aclId == null)
{
return false;
}
else
{
return checkRequired(authority, aclId);
}
}
/**
* Check if we have a global permission
*
* @param authorisations
* @return true if granted
*/
private boolean checkGlobalPermissions(String authority)
{
for (PermissionEntry pe : rmModelDao.getGlobalPermissionEntries())
{
if (isGranted(pe, authority))
{
return true;
}
}
return false;
}
/**
* Check that a given authentication is available on a node
*
* @param authorisations
* @param nodeRef
* @param denied
* @return true if a check is required
*/
boolean checkRequired(String authority, Long aclId)
{
AccessControlList acl = rmAclDaoComponent.getAccessControlList(aclId);
if (acl == null)
{
return false;
}
Set<Pair<String, PermissionReference>> denied = new HashSet<Pair<String, PermissionReference>>();
// Check if each permission allows - the first wins.
// We could have other voting style mechanisms here
for (AccessControlEntry ace : acl.getEntries())
{
if (isGranted(ace, authority, denied))
{
return true;
}
}
return false;
}
/**
* Is a permission granted
*
* @param pe -
* the permissions entry to consider
* @param granters -
* the set of granters
* @param authorisations -
* the set of authorities
* @param denied -
* the set of denied permissions/authority pais
* @return true if granted
*/
private boolean isGranted(AccessControlEntry ace, String authority, Set<Pair<String, PermissionReference>> denied)
{
// If the permission entry denies then we just deny
if (ace.getAccessStatus() == AccessStatus.DENIED)
{
denied.add(new Pair<String, PermissionReference>(ace.getAuthority(), ace.getPermission()));
Set<PermissionReference> granters = rmModelDao.getGrantingPermissions(ace.getPermission());
for (PermissionReference granter : granters)
{
denied.add(new Pair<String, PermissionReference>(ace.getAuthority(), granter));
}
// All the things granted by this permission must be
// denied
Set<PermissionReference> grantees = rmModelDao.getGranteePermissions(ace.getPermission());
for (PermissionReference grantee : grantees)
{
denied.add(new Pair<String, PermissionReference>(ace.getAuthority(), grantee));
}
// All permission excludes all permissions available for
// the node.
if (ace.getPermission().equals(getAllPermissionReference()) || ace.getPermission().equals(RM_OLD_ALL_PERMISSIONS_REFERENCE))
{
for (PermissionReference deny : rmModelDao.getAllPermissions())
{
denied.add(new Pair<String, PermissionReference>(ace.getAuthority(), deny));
}
}
return false;
}
// The permission is allowed but we deny it as it is in the denied
// set
if (denied != null)
{
Pair<String, PermissionReference> specific = new Pair<String, PermissionReference>(ace.getAuthority(), required);
if (denied.contains(specific))
{
return false;
}
}
// If the permission has a match in both the authorities and
// granters list it is allowed
// It applies to the current user and it is granted
if (authority.equals(ace.getAuthority()) && granters.contains(ace.getPermission()))
{
{
return true;
}
}
// Default deny
return false;
}
private boolean isGranted(PermissionEntry pe, String authority)
{
// If the permission entry denies then we just deny
if (pe.isDenied())
{
return false;
}
// If the permission has a match in both the authorities and
// granters list it is allowed
// It applies to the current user and it is granted
if (granters.contains(pe.getPermissionReference()) && authority.equals(pe.getAuthority()))
{
{
return true;
}
}
// Default deny
return false;
}
}
}

View File

@@ -32,6 +32,7 @@ import net.sf.acegisecurity.providers.dao.User;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.avm.AVMRepository; import org.alfresco.repo.avm.AVMRepository;
import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.cache.SimpleCache;
@@ -82,6 +83,10 @@ import org.springframework.context.ApplicationEvent;
import org.springframework.extensions.surf.util.AbstractLifecycleBean; import org.springframework.extensions.surf.util.AbstractLifecycleBean;
/** /**
* Currently required to re-implement the permission service.
*
* As of V4.2 this will no longer be required.
*
* @author Roy Wetherall * @author Roy Wetherall
*/ */
public class PermissionServiceImpl extends AbstractLifecycleBean implements PermissionServiceSPI public class PermissionServiceImpl extends AbstractLifecycleBean implements PermissionServiceSPI
@@ -1037,9 +1042,31 @@ public class PermissionServiceImpl extends AbstractLifecycleBean implements Perm
deletePermission(nodeRef, authority, getPermissionReference(perm)); deletePermission(nodeRef, authority, getPermissionReference(perm));
} }
public AccessStatus hasPermission(NodeRef nodeRef, String perm) public AccessStatus hasPermission(final NodeRef nodeRef, final String perm)
{ {
return hasPermission(nodeRef, getPermissionReference(perm)); // NOTE: this is a work around fix for the specific case when we are asking if a filePlan node has
// READ permission, but in fact this makes no sense and we mean ReadRecord
//
// For now we will restrict this change to only this form of the method to limit the
// potential effects. When this is refactored to extend the updated PermissionService post 4.2
// it can be readdressed and determined if there is a better place for this.
String updatedPerm = AuthenticationUtil.runAsSystem(new RunAsWork<String>()
{
@Override
public String doWork() throws Exception
{
String result = perm;
if ("Read".equals(perm) == true &&
nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT) == true)
{
result = "ReadRecords";
}
return result;
}
});
return hasPermission(nodeRef, getPermissionReference(updatedPerm));
} }
public void setPermission(NodeRef nodeRef, String authority, String perm, boolean allow) public void setPermission(NodeRef nodeRef, String authority, String perm, boolean allow)