mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
RM-582: A user can edit record meta-data if they have write permissions.
* all users that had 'write' permissions on a document when it becomes a record continue to have 'file' on that record. * these users also have EditMetadata capability * this include the owner of the document at the time it was made a record * extended 'read' permissions for created records continues to work in the same way * added an extended permission service with additional method to get the writers of a node .. configured and implemented as an extension to the core and held in the RM AMP (could be moved down at a later stage if appropriate) * patches updated * unit tests updated (and fixed) * content model updated to more generic 'ExtendedSecurity' aspect with writers property * service generalised as an ExtendedSecurityService with appropriate method changes * mandatory parameter no longer mandatory in create-record action .. fixes issues seen in unit tests and UI NOTE: due to the nature of this change any db's created on an earlier 2.1 dev build will need to be reset .. going from 2.0.1 onwards will, however, be fine. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@46270 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -239,9 +239,10 @@ public class RecordsManagementServiceImpl extends ServiceBaseImpl
|
||||
ExtendedSecurityService extendedSecurityService = serviceRegistry.getExtendedSecurityService();
|
||||
NodeRef parent = childAssocRef.getParentRef();
|
||||
Set<String> readers = extendedSecurityService.getExtendedReaders(parent);
|
||||
Set<String> writers = extendedSecurityService.getExtendedWriters(parent);
|
||||
if (readers != null && readers.size() != 0)
|
||||
{
|
||||
extendedSecurityService.setExtendedReaders(thumbnail, readers, false);
|
||||
extendedSecurityService.addExtendedSecurity(thumbnail, readers, writers, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -143,8 +143,13 @@ public class CreateRecordAction extends ActionExecuterAbstractBase
|
||||
}
|
||||
}
|
||||
|
||||
// indicate whether the record should be hidden or not
|
||||
boolean hideRecord = ((Boolean)action.getParameterValue(PARAM_HIDE_RECORD)).booleanValue();
|
||||
// indicate whether the record should be hidden or not (default not)
|
||||
boolean hideRecord = false;
|
||||
Boolean hideRecordValue = ((Boolean)action.getParameterValue(PARAM_HIDE_RECORD));
|
||||
if (hideRecordValue != null)
|
||||
{
|
||||
hideRecord = hideRecordValue.booleanValue();
|
||||
}
|
||||
|
||||
// create record from existing document
|
||||
recordService.createRecord(filePlan, actionedUponNodeRef, !hideRecord);
|
||||
@@ -159,7 +164,7 @@ public class CreateRecordAction extends ActionExecuterAbstractBase
|
||||
{
|
||||
// NOTE: commented out for now so that it doesn't appear in the UI ... enable later when multi-file plan support is added
|
||||
//params.add(new ParameterDefinitionImpl(PARAM_FILE_PLAN, DataTypeDefinition.NODE_REF, false, getParamDisplayLabel(PARAM_FILE_PLAN)));
|
||||
params.add(new ParameterDefinitionImpl(PARAM_HIDE_RECORD, DataTypeDefinition.BOOLEAN, true, getParamDisplayLabel(PARAM_HIDE_RECORD)));
|
||||
params.add(new ParameterDefinitionImpl(PARAM_HIDE_RECORD, DataTypeDefinition.BOOLEAN, false, getParamDisplayLabel(PARAM_HIDE_RECORD)));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -93,17 +93,6 @@ public abstract class AbstractCapability extends RMSecurityCommon
|
||||
capabilityService.registerCapability(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an action
|
||||
*
|
||||
* @param action
|
||||
*/
|
||||
// public void registerAction(RecordsManagementAction action)
|
||||
// {
|
||||
// this.actions.add(action);
|
||||
// this.actionNames.add(action.getName());
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param name capability name
|
||||
*/
|
||||
@@ -205,37 +194,6 @@ public abstract class AbstractCapability extends RMSecurityCommon
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param nodeRef
|
||||
* @return
|
||||
*/
|
||||
// public int checkActionConditionsIfPresent(NodeRef nodeRef)
|
||||
// {
|
||||
// String prefix = "checkActionConditionsIfPresent" + getName();
|
||||
// int result = getTransactionCache(prefix, nodeRef);
|
||||
// if (result != NOSET_VALUE)
|
||||
// {
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// if (actions.size() > 0)
|
||||
// {
|
||||
// for (RecordsManagementAction action : actions)
|
||||
// {
|
||||
// if (action.isExecutable(nodeRef, null))
|
||||
// {
|
||||
// return setTransactionCache(prefix, nodeRef, AccessDecisionVoter.ACCESS_GRANTED);
|
||||
// }
|
||||
// }
|
||||
// return setTransactionCache(prefix, nodeRef, AccessDecisionVoter.ACCESS_DENIED);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return setTransactionCache(prefix, nodeRef, AccessDecisionVoter.ACCESS_GRANTED);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.capability.Capability#hasPermission(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@@ -265,10 +223,6 @@ public abstract class AbstractCapability extends RMSecurityCommon
|
||||
{
|
||||
result = AccessDecisionVoter.ACCESS_DENIED;
|
||||
}
|
||||
// else if (checkActionConditionsIfPresent(nodeRef) == AccessDecisionVoter.ACCESS_DENIED)
|
||||
// {
|
||||
// result = AccessDecisionVoter.ACCESS_DENIED;
|
||||
// }
|
||||
else
|
||||
{
|
||||
result = hasPermissionImpl(nodeRef);
|
||||
@@ -296,22 +250,6 @@ public abstract class AbstractCapability extends RMSecurityCommon
|
||||
return AccessDecisionVoter.ACCESS_ABSTAIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.capability.Capability#getActionNames()
|
||||
*/
|
||||
// public List<String> getActionNames()
|
||||
// {
|
||||
// return actionNames;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.capability.Capability#getActions()
|
||||
*/
|
||||
// public List<RecordsManagementAction> getActions()
|
||||
// {
|
||||
// return actions;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.capability.Capability#getGroup()
|
||||
*/
|
||||
|
@@ -169,7 +169,7 @@ public class DeclarativeCapability extends AbstractCapability
|
||||
|
||||
for (String permission : permissions)
|
||||
{
|
||||
if (permissionService.hasPermission(filePlan, permission) != AccessStatus.ALLOWED)
|
||||
if (permissionService.hasPermission(filePlan, permission) != AccessStatus.ALLOWED)
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
|
@@ -29,6 +29,7 @@ import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
|
||||
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -159,6 +160,7 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
|
||||
permissionService.setInheritParentPermissions(container, false);
|
||||
permissionService.setPermission(container, allRoles, RMPermissionModel.READ_RECORDS, true);
|
||||
permissionService.setPermission(container, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true);
|
||||
permissionService.setPermission(container, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true);
|
||||
|
||||
// TODO set the admin users to have filing permissions on the unfiled container!!!
|
||||
// TODO we will need to be able to get a list of the admin roles from the service
|
||||
|
@@ -227,9 +227,10 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel
|
||||
public static final QName ASPECT_LOADED_DATA_SET_ID = QName.createQName(RM_URI, "loadedDataSetId");
|
||||
public static final QName PROP_LOADED_DATA_SET_IDS = QName.createQName(RM_URI, "loadedDataSetIds");
|
||||
|
||||
// Extended readers aspect
|
||||
public static final QName ASPECT_EXTENDED_READERS = QName.createQName(RM_URI, "extendedReaders");
|
||||
// Extended security aspect
|
||||
public static final QName ASPECT_EXTENDED_SECURITY = QName.createQName(RM_URI, "extendedSecurity");
|
||||
public static final QName PROP_READERS = QName.createQName(RM_URI, "readers");
|
||||
public static final QName PROP_WRITERS = QName.createQName(RM_URI, "writers");
|
||||
|
||||
// Originating details of a record
|
||||
public static final QName ASPECT_RECORD_ORIGINATING_DETAILS = QName.createQName(RM_URI, "recordOriginatingDetails");
|
||||
|
@@ -26,6 +26,7 @@ import org.alfresco.module.org_alfresco_module_rm.dod5015.DOD5015Model;
|
||||
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionService;
|
||||
import org.alfresco.repo.module.AbstractModuleComponent;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -117,7 +118,11 @@ public class RMv21InPlacePatch extends AbstractModuleComponent
|
||||
|
||||
// set permissions
|
||||
filePlanPermissionService.setPermission(filePlan, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS);
|
||||
filePlanPermissionService.setPermission(filePlan, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING);
|
||||
|
||||
// set capabilities
|
||||
permissionService.setPermission(filePlan, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.VIEW_RECORDS, true);
|
||||
permissionService.setPermission(filePlan, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.EDIT_RECORD_METADATA, true);
|
||||
|
||||
// create unfiled container
|
||||
filePlanService.createUnfiledContainer(filePlan);
|
||||
|
@@ -21,6 +21,7 @@ package org.alfresco.module.org_alfresco_module_rm.record;
|
||||
import java.io.Serializable;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -46,12 +47,14 @@ import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.repo.security.permissions.impl.ExtendedPermissionService;
|
||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.OwnableService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
@@ -83,7 +86,7 @@ public class RecordServiceImpl implements RecordService,
|
||||
private DictionaryService dictionaryService;
|
||||
|
||||
/** Permission service */
|
||||
private PermissionService permissionService;
|
||||
private ExtendedPermissionService permissionService;
|
||||
|
||||
/** Extended security service */
|
||||
private ExtendedSecurityService extendedSecurityService;
|
||||
@@ -102,6 +105,9 @@ public class RecordServiceImpl implements RecordService,
|
||||
|
||||
/** Policy component */
|
||||
private PolicyComponent policyComponent;
|
||||
|
||||
/** Ownable service */
|
||||
private OwnableService ownableService;
|
||||
|
||||
/** List of available record meta-data aspects */
|
||||
private Set<QName> recordMetaDataAspects;
|
||||
@@ -145,7 +151,7 @@ public class RecordServiceImpl implements RecordService,
|
||||
/**
|
||||
* @param permissionService permission service
|
||||
*/
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
public void setPermissionService(ExtendedPermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
@@ -198,6 +204,14 @@ public class RecordServiceImpl implements RecordService,
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ownableService ownable service
|
||||
*/
|
||||
public void setOwnableService(OwnableService ownableService)
|
||||
{
|
||||
this.ownableService = ownableService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init method
|
||||
*/
|
||||
@@ -323,6 +337,13 @@ public class RecordServiceImpl implements RecordService,
|
||||
// get the documents readers
|
||||
Long aclId = nodeService.getNodeAclId(nodeRef);
|
||||
Set<String> readers = permissionService.getReaders(aclId);
|
||||
Set<String> writers = permissionService.getWriters(aclId);
|
||||
|
||||
// add the current owner to the list of extended writers
|
||||
String owner = ownableService.getOwner(nodeRef);
|
||||
|
||||
// remove the owner
|
||||
ownableService.setOwner(nodeRef, OwnableService.NO_OWNER);
|
||||
|
||||
// get the documents primary parent assoc
|
||||
ChildAssociationRef parentAssoc = nodeService.getPrimaryParent(nodeRef);
|
||||
@@ -345,8 +366,9 @@ public class RecordServiceImpl implements RecordService,
|
||||
// maintain the original primary location
|
||||
nodeService.addChild(parentAssoc.getParentRef(), nodeRef, parentAssoc.getTypeQName(), parentAssoc.getQName());
|
||||
|
||||
// set the readers
|
||||
extendedSecurityService.setExtendedReaders(nodeRef, readers);
|
||||
// set the extended security
|
||||
extendedSecurityService.addExtendedSecurity(nodeRef, readers, writers);
|
||||
extendedSecurityService.addExtendedSecurity(nodeRef, null, Collections.singleton(owner));
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -417,7 +439,7 @@ public class RecordServiceImpl implements RecordService,
|
||||
// check whether this item is already an item or not
|
||||
if (isRecord(record) == false)
|
||||
{
|
||||
// make the item a record
|
||||
// make the item a recor
|
||||
makeRecord(record);
|
||||
}
|
||||
|
||||
@@ -483,7 +505,7 @@ public class RecordServiceImpl implements RecordService,
|
||||
|
||||
// remove the extended security from the node
|
||||
// this prevents the users from continuing to see the record in searchs and other linked locations
|
||||
extendedSecurityService.removeAllExtendedReaders(nodeRef);
|
||||
extendedSecurityService.removeAllExtendedSecurity(nodeRef);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -534,7 +556,7 @@ public class RecordServiceImpl implements RecordService,
|
||||
nodeService.moveNode(nodeRef, originatingLocation, ContentModel.ASSOC_CONTAINS, parentAssoc.getQName());
|
||||
|
||||
// remove all extended readers
|
||||
extendedSecurityService.removeAllExtendedReaders(nodeRef);
|
||||
extendedSecurityService.removeAllExtendedSecurity(nodeRef);
|
||||
|
||||
// save the information about the rejection details
|
||||
Map<QName, Serializable> aspectProperties = new HashMap<QName, Serializable>(3);
|
||||
|
@@ -32,6 +32,7 @@ import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
|
||||
import org.alfresco.repo.node.NodeServicePolicies;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
@@ -176,8 +177,12 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService,
|
||||
permissionService.setInheritParentPermissions(rmRootNode, false);
|
||||
permissionService.setPermission(rmRootNode, allRoles, RMPermissionModel.READ_RECORDS, true);
|
||||
permissionService.setPermission(rmRootNode, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true);
|
||||
permissionService.setPermission(rmRootNode, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.VIEW_RECORDS, true);
|
||||
permissionService.setPermission(rmRootNode, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true);
|
||||
|
||||
// set the capabilities
|
||||
permissionService.setPermission(rmRootNode, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.VIEW_RECORDS, true);
|
||||
permissionService.setPermission(rmRootNode, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.EDIT_RECORD_METADATA, true);
|
||||
|
||||
// Create the unfiled record container
|
||||
return filePlanService.createUnfiledContainer(rmRootNode);
|
||||
}
|
||||
|
@@ -20,16 +20,7 @@ package org.alfresco.module.org_alfresco_module_rm.security;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.repo.security.permissions.DynamicAuthority;
|
||||
import org.alfresco.repo.security.permissions.PermissionReference;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.security.AuthorityType;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
/**
|
||||
* Extended readers dynamic authority implementation.
|
||||
@@ -37,73 +28,11 @@ import org.springframework.context.ApplicationContextAware;
|
||||
* @author Roy Wetherall
|
||||
* @since 2.1
|
||||
*/
|
||||
public class ExtendedReaderDynamicAuthority implements DynamicAuthority,
|
||||
RecordsManagementModel,
|
||||
ApplicationContextAware
|
||||
public class ExtendedReaderDynamicAuthority extends ExtendedSecurityBaseDynamicAuthority
|
||||
{
|
||||
/** Extended reader role */
|
||||
public static final String EXTENDED_READER = "ROLE_EXTENDED_READER";
|
||||
|
||||
/** Authority service */
|
||||
private AuthorityService authorityService;
|
||||
|
||||
/** Extended security service */
|
||||
private ExtendedSecurityService extendedSecurityService;
|
||||
|
||||
/** Node service */
|
||||
private NodeService nodeService;
|
||||
|
||||
/** Application context */
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
// NOTE: we get the services directly from the application context in this way to avoid
|
||||
// cyclic relationships and issues when loading the application context
|
||||
|
||||
/**
|
||||
* @return authority service
|
||||
*/
|
||||
private AuthorityService getAuthorityService()
|
||||
{
|
||||
if (authorityService == null)
|
||||
{
|
||||
authorityService = (AuthorityService)applicationContext.getBean("authorityService");
|
||||
}
|
||||
return authorityService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return extended security service
|
||||
*/
|
||||
public ExtendedSecurityService getExtendedSecurityService()
|
||||
{
|
||||
if (extendedSecurityService == null)
|
||||
{
|
||||
extendedSecurityService = (ExtendedSecurityService)applicationContext.getBean("extendedSecurityService");
|
||||
}
|
||||
return extendedSecurityService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return node service
|
||||
*/
|
||||
public NodeService getNodeService()
|
||||
{
|
||||
if (nodeService == null)
|
||||
{
|
||||
nodeService = (NodeService)applicationContext.getBean("nodeService");
|
||||
}
|
||||
return nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
{
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.security.permissions.DynamicAuthority#getAuthority()
|
||||
*/
|
||||
@@ -114,61 +43,10 @@ public class ExtendedReaderDynamicAuthority implements DynamicAuthority,
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.security.permissions.DynamicAuthority#hasAuthority(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public boolean hasAuthority(NodeRef nodeRef, String userName)
|
||||
protected Set<String> getAuthorites(NodeRef nodeRef)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_READERS) == true)
|
||||
{
|
||||
Set<String> readers = getExtendedSecurityService().getExtendedReaders(nodeRef);
|
||||
if (readers != null)
|
||||
{
|
||||
for (String reader : readers)
|
||||
{
|
||||
if ("GROUP_EVERYONE".equals(reader) == true)
|
||||
{
|
||||
// 'eveyone' has read
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
else if (reader.startsWith("GROUP_") == true)
|
||||
{
|
||||
// check group to see if the user is contained
|
||||
Set<String> contained = getAuthorityService().getContainedAuthorities(AuthorityType.USER, reader, false);
|
||||
if (contained.isEmpty() == false &&
|
||||
contained.contains(userName) == true)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// presume we have a user
|
||||
if (reader.equals(userName) == true)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
|
||||
*/
|
||||
@Override
|
||||
public Set<PermissionReference> requiredFor()
|
||||
{
|
||||
// TODO ... should we set something here? ReadRecord?
|
||||
|
||||
return null;
|
||||
}
|
||||
return getExtendedSecurityService().getExtendedReaders(nodeRef);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.repo.security.permissions.DynamicAuthority;
|
||||
import org.alfresco.repo.security.permissions.PermissionReference;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.security.AuthorityType;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
/**
|
||||
* Extended readers dynamic authority implementation.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
* @since 2.1
|
||||
*/
|
||||
public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAuthority,
|
||||
RecordsManagementModel,
|
||||
ApplicationContextAware
|
||||
{
|
||||
/** Authority service */
|
||||
private AuthorityService authorityService;
|
||||
|
||||
/** Extended security service */
|
||||
private ExtendedSecurityService extendedSecurityService;
|
||||
|
||||
/** Node service */
|
||||
private NodeService nodeService;
|
||||
|
||||
/** Application context */
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
// NOTE: we get the services directly from the application context in this way to avoid
|
||||
// cyclic relationships and issues when loading the application context
|
||||
|
||||
/**
|
||||
* @return authority service
|
||||
*/
|
||||
protected AuthorityService getAuthorityService()
|
||||
{
|
||||
if (authorityService == null)
|
||||
{
|
||||
authorityService = (AuthorityService)applicationContext.getBean("authorityService");
|
||||
}
|
||||
return authorityService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return extended security service
|
||||
*/
|
||||
protected ExtendedSecurityService getExtendedSecurityService()
|
||||
{
|
||||
if (extendedSecurityService == null)
|
||||
{
|
||||
extendedSecurityService = (ExtendedSecurityService)applicationContext.getBean("extendedSecurityService");
|
||||
}
|
||||
return extendedSecurityService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return node service
|
||||
*/
|
||||
protected NodeService getNodeService()
|
||||
{
|
||||
if (nodeService == null)
|
||||
{
|
||||
nodeService = (NodeService)applicationContext.getBean("nodeService");
|
||||
}
|
||||
return nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
{
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of the authorities from the extended security aspect that this dynamic
|
||||
* authority is checking against.
|
||||
*
|
||||
* @param nodeRef
|
||||
* @return
|
||||
*/
|
||||
protected abstract Set<String> getAuthorites(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.security.permissions.DynamicAuthority#hasAuthority(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean hasAuthority(NodeRef nodeRef, String userName)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY) == true)
|
||||
{
|
||||
Set<String> authorities = getAuthorites(nodeRef);
|
||||
if (authorities != null)
|
||||
{
|
||||
for (String authority : authorities)
|
||||
{
|
||||
if ("GROUP_EVERYONE".equals(authority) == true)
|
||||
{
|
||||
// 'eveyone' is there so break
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
else if (authority.startsWith("GROUP_") == true)
|
||||
{
|
||||
// check group to see if the user is contained
|
||||
Set<String> contained = getAuthorityService().getContainedAuthorities(AuthorityType.USER, authority, false);
|
||||
if (contained.isEmpty() == false &&
|
||||
contained.contains(userName) == true)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// presume we have a user
|
||||
if (authority.equals(userName) == true)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Base implementation
|
||||
*
|
||||
* @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
|
||||
*/
|
||||
@Override
|
||||
public Set<PermissionReference> requiredFor()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -30,13 +30,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
||||
*/
|
||||
public interface ExtendedSecurityService
|
||||
{
|
||||
/**
|
||||
* Indicates whether the node has any extended readers set or not.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @return boolean true if the node has extended readers set, false otherwise
|
||||
*/
|
||||
boolean hasExtendedReaders(NodeRef nodeRef);
|
||||
boolean hasExtendedSecurity(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Gets the set authorities that are extended readers for the given node.
|
||||
@@ -47,63 +41,22 @@ public interface ExtendedSecurityService
|
||||
Set<String> getExtendedReaders(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Set the authorities that are extended readers on the node. Applies extended readers to
|
||||
* file plan parent hierarchy.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param readers extended readers
|
||||
* @param nodeRef
|
||||
* @return
|
||||
*/
|
||||
void setExtendedReaders(NodeRef nodeRef, Set<String> readers);
|
||||
Set<String> getExtendedWriters(NodeRef nodeRef);
|
||||
|
||||
void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers);
|
||||
|
||||
/**
|
||||
* Set the authorities that have extended reading permissions on the node.
|
||||
* <p>
|
||||
* Optionally applies the extended readers to the file plan hierarchy.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param readers extended readers
|
||||
* @param applyToParents true if applied to file plan hierarchy, false otherwise
|
||||
*/
|
||||
void setExtendedReaders(NodeRef nodeRef, Set<String> readers, boolean applyToParents);
|
||||
void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents);
|
||||
|
||||
/**
|
||||
* Removes the given authorities from the extended readers set for this node.
|
||||
* <p>
|
||||
* Applies to file plan hierarchy.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param readers extended readers
|
||||
*/
|
||||
void removeExtendedReaders(NodeRef nodeRef, Set<String> readers);
|
||||
void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers);
|
||||
|
||||
/**
|
||||
* Removes the given authorities from the extended readers set for this node.
|
||||
* <p>
|
||||
* Optionally applies the removal to the file plan hierarchy.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param readers extended readers
|
||||
* @param applyToParents true if applied to the file plan hierarchy, false otherwise
|
||||
*/
|
||||
void removeExtendedReaders(NodeRef nodeRef, Set<String> readers, boolean applyToParents);
|
||||
void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents);
|
||||
|
||||
/**
|
||||
* Removes all extended readers from this node.
|
||||
* <p>
|
||||
* Applies removal to the file plan hierarchy.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
*/
|
||||
void removeAllExtendedReaders(NodeRef nodeRef);
|
||||
void removeAllExtendedSecurity(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Removes all extended readers from this node.
|
||||
* <p>
|
||||
* Optionally applies the removal to the file plan hierarchy.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param applyToParents true if applied to the file plan hierarchy, false otherwise
|
||||
*/
|
||||
void removeAllExtendedReaders(NodeRef nodeRef, boolean applyToParents);
|
||||
void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents);
|
||||
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@ import org.alfresco.model.RenditionModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
|
||||
import org.alfresco.repo.node.NodeServicePolicies;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
@@ -36,7 +37,6 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
|
||||
@@ -46,16 +46,14 @@ import org.alfresco.util.ParameterCheck;
|
||||
* @author Roy Wetherall
|
||||
* @since 2.1
|
||||
*/
|
||||
public class ExtendedSecurityServiceImpl implements ExtendedSecurityService,
|
||||
public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
implements ExtendedSecurityService,
|
||||
RecordsManagementModel,
|
||||
NodeServicePolicies.OnMoveNodePolicy
|
||||
{
|
||||
/** Policy component */
|
||||
private PolicyComponent policyComponent;
|
||||
|
||||
/** Node service */
|
||||
private NodeService nodeService;
|
||||
|
||||
/** Records management service */
|
||||
private RecordsManagementService recordsManagementService;
|
||||
|
||||
@@ -86,14 +84,6 @@ public class ExtendedSecurityServiceImpl implements ExtendedSecurityService,
|
||||
this.recordsManagementService = recordsManagementService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeService node service
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init method
|
||||
*/
|
||||
@@ -101,23 +91,16 @@ public class ExtendedSecurityServiceImpl implements ExtendedSecurityService,
|
||||
{
|
||||
policyComponent.bindClassBehaviour(
|
||||
NodeServicePolicies.OnMoveNodePolicy.QNAME,
|
||||
ASPECT_EXTENDED_READERS,
|
||||
ASPECT_EXTENDED_SECURITY,
|
||||
new JavaBehaviour(this, "onMoveNode", NotificationFrequency.TRANSACTION_COMMIT));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#hasExtendedReaders(org.alfresco.service.cmr.repository.NodeRef)
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#hasExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public boolean hasExtendedReaders(NodeRef nodeRef)
|
||||
public boolean hasExtendedSecurity(NodeRef nodeRef)
|
||||
{
|
||||
boolean result = false;
|
||||
Set<String> extendedReaders = getExtendedReaders(nodeRef);
|
||||
if (extendedReaders != null && extendedReaders.size() != 0)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
return nodeService.hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,61 +120,72 @@ public class ExtendedSecurityServiceImpl implements ExtendedSecurityService,
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#setExtendedReaders(org.alfresco.service.cmr.repository.NodeRef, java.util.Set)
|
||||
*/
|
||||
@Override
|
||||
public void setExtendedReaders(NodeRef nodeRef, Set<String> readers)
|
||||
{
|
||||
setExtendedReaders(nodeRef, readers, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#setExtendedReaders(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, boolean)
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#getExtendedWriters(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void setExtendedReaders(NodeRef nodeRef, java.util.Set<String> readers, boolean applyToParents)
|
||||
{
|
||||
public Set<String> getExtendedWriters(NodeRef nodeRef)
|
||||
{
|
||||
Set<String> result = null;
|
||||
|
||||
Map<String, Integer> map = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_WRITERS);
|
||||
if (map != null)
|
||||
{
|
||||
result = map.keySet();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
|
||||
*/
|
||||
@Override
|
||||
public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
||||
{
|
||||
addExtendedSecurity(nodeRef, readers, writers, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
ParameterCheck.mandatory("readers", readers);
|
||||
ParameterCheck.mandatory("applyToParents", applyToParents);
|
||||
|
||||
if (nodeRef != null && readers.isEmpty() == false)
|
||||
if (nodeRef != null)
|
||||
{
|
||||
// add the aspect if missing
|
||||
if (nodeService.hasAspect(nodeRef, ASPECT_EXTENDED_READERS) == false)
|
||||
if (nodeService.hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY) == false)
|
||||
{
|
||||
nodeService.addAspect(nodeRef, ASPECT_EXTENDED_READERS, null);
|
||||
nodeService.addAspect(nodeRef, ASPECT_EXTENDED_SECURITY, null);
|
||||
}
|
||||
|
||||
// get reader map
|
||||
Map<String, Integer> readersMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
|
||||
if (readersMap == null)
|
||||
// update the readers map
|
||||
if (readers != null && readers.size() != 0)
|
||||
{
|
||||
// create reader map
|
||||
readersMap = new HashMap<String, Integer>(7);
|
||||
// get reader map
|
||||
Map<String, Integer> readersMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
|
||||
|
||||
// set the readers property (this will in turn apply the aspect if required)
|
||||
nodeService.setProperty(nodeRef, PROP_READERS, (Serializable)addToMap(readersMap, readers));
|
||||
}
|
||||
|
||||
for (String reader : readers)
|
||||
// update the writers map
|
||||
if (writers != null && writers.size() != 0)
|
||||
{
|
||||
if (readersMap.containsKey(reader) == true)
|
||||
{
|
||||
// increment reference count
|
||||
Integer count = readersMap.get(reader);
|
||||
readersMap.put(reader, Integer.valueOf(count.intValue()+1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// add reader with initial count
|
||||
readersMap.put(reader, Integer.valueOf(1));
|
||||
}
|
||||
// get writer map
|
||||
Map<String, Integer> writersMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_WRITERS);
|
||||
|
||||
// set the writers property (this will in turn apply the aspect if required)
|
||||
nodeService.setProperty(nodeRef, PROP_WRITERS, (Serializable)addToMap(writersMap, writers));
|
||||
}
|
||||
|
||||
// set the readers property (this will in turn apply the aspect if required)
|
||||
nodeService.setProperty(nodeRef, PROP_READERS, (Serializable)readersMap);
|
||||
|
||||
// apply the readers to any renditions of the content
|
||||
if (recordService.isRecord(nodeRef) == true)
|
||||
{
|
||||
@@ -199,41 +193,69 @@ public class ExtendedSecurityServiceImpl implements ExtendedSecurityService,
|
||||
for (ChildAssociationRef assoc : assocs)
|
||||
{
|
||||
NodeRef child = assoc.getChildRef();
|
||||
setExtendedReaders(child, readers, false);
|
||||
addExtendedSecurity(child, readers, writers, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (applyToParents == true)
|
||||
{
|
||||
{
|
||||
// apply the extended readers up the file plan primary hierarchy
|
||||
NodeRef parent = nodeService.getPrimaryParent(nodeRef).getParentRef();
|
||||
if (parent != null &&
|
||||
recordsManagementService.isFilePlanComponent(parent) == true)
|
||||
{
|
||||
setExtendedReaders(parent, readers);
|
||||
addExtendedSecurity(parent, readers, null);
|
||||
addExtendedSecurity(parent, writers, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#removeExtendedReaders(org.alfresco.service.cmr.repository.NodeRef, java.util.Set)
|
||||
*
|
||||
* @param map
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void removeExtendedReaders(NodeRef nodeRef, Set<String> readers)
|
||||
private Map<String, Integer> addToMap(Map<String, Integer> map, Set<String> keys)
|
||||
{
|
||||
removeExtendedReaders(nodeRef, readers, true);
|
||||
if (map == null)
|
||||
{
|
||||
// create map
|
||||
map = new HashMap<String, Integer>(7);
|
||||
}
|
||||
|
||||
for (String key : keys)
|
||||
{
|
||||
if (map.containsKey(key) == true)
|
||||
{
|
||||
// increment reference count
|
||||
Integer count = map.get(key);
|
||||
map.put(key, Integer.valueOf(count.intValue()+1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// add key with initial count
|
||||
map.put(key, Integer.valueOf(1));
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#removeExtendedReaders(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, boolean)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void removeExtendedReaders(NodeRef nodeRef, Set<String> readers, boolean applyToParents)
|
||||
public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
||||
{
|
||||
if (hasExtendedReaders(nodeRef) == true)
|
||||
removeExtendedSecurity(nodeRef, readers, writers, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String>writers, boolean applyToParents)
|
||||
{
|
||||
if (hasExtendedSecurity(nodeRef) == true)
|
||||
{
|
||||
removeExtendedReadersImpl(nodeRef, readers);
|
||||
removeExtendedSecurityImpl(nodeRef, readers, writers);
|
||||
|
||||
// remove the readers from any renditions of the content
|
||||
if (recordService.isRecord(nodeRef) == true)
|
||||
@@ -242,7 +264,7 @@ public class ExtendedSecurityServiceImpl implements ExtendedSecurityService,
|
||||
for (ChildAssociationRef assoc : assocs)
|
||||
{
|
||||
NodeRef child = assoc.getChildRef();
|
||||
removeExtendedReadersImpl(child, readers);
|
||||
removeExtendedSecurityImpl(child, readers, writers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,80 +275,83 @@ public class ExtendedSecurityServiceImpl implements ExtendedSecurityService,
|
||||
if (parent != null &&
|
||||
recordsManagementService.isFilePlanComponent(parent) == true)
|
||||
{
|
||||
removeExtendedReaders(parent, readers, applyToParents);
|
||||
removeExtendedSecurity(parent, readers, null, applyToParents);
|
||||
removeExtendedSecurity(parent, writers, null, applyToParents);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a set of readers from a node reference.
|
||||
* Removes a set of readers and writers from a node reference.
|
||||
* <p>
|
||||
* Removes the aspect and resets the property to null if all readers are removed.
|
||||
* Removes the aspect and resets the property to null if all readers and writers are removed.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param readers {@link Set} of readers
|
||||
* @param writers {@link Set} of writers
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void removeExtendedReadersImpl(NodeRef nodeRef, Set<String> readers)
|
||||
private void removeExtendedSecurityImpl(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
||||
{
|
||||
Map<String, Integer> readersMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
|
||||
nodeService.setProperty(nodeRef, PROP_READERS, (Serializable)removeFromMap(readersMap, readers));
|
||||
|
||||
// remove the readers
|
||||
for (String reader : readers)
|
||||
Map<String, Integer> writersMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_WRITERS);
|
||||
nodeService.setProperty(nodeRef, PROP_WRITERS, (Serializable)removeFromMap(writersMap, writers));
|
||||
|
||||
if (readersMap == null && writersMap == null)
|
||||
{
|
||||
Integer readerCount = readersMap.get(reader);
|
||||
if (readerCount != null)
|
||||
// remove the aspect
|
||||
nodeService.removeAspect(nodeRef, ASPECT_EXTENDED_SECURITY);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Integer> removeFromMap(Map<String, Integer> map, Set<String> keys)
|
||||
{
|
||||
if (map != null && keys != null && keys.size() != 0)
|
||||
{
|
||||
// remove the keys
|
||||
for (String key : keys)
|
||||
{
|
||||
if (readerCount == 1)
|
||||
Integer count = map.get(key);
|
||||
if (count != null)
|
||||
{
|
||||
// remove entry all together if the reference count is now 0
|
||||
readersMap.remove(reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
// decrement the reference count by 1
|
||||
readersMap.put(reader, Integer.valueOf(readerCount.intValue()-1));
|
||||
if (count == 1)
|
||||
{
|
||||
// remove entry all together if the reference count is now 0
|
||||
map.remove(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
// decrement the reference count by 1
|
||||
map.put(key, Integer.valueOf(count.intValue()-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reset the map to null if now empty
|
||||
if (readersMap.isEmpty() == true)
|
||||
if (map != null && map.isEmpty() == true)
|
||||
{
|
||||
readersMap = null;
|
||||
map = null;
|
||||
}
|
||||
|
||||
// set the property and remove the aspect if appropriate
|
||||
nodeService.setProperty(nodeRef, PROP_READERS, (Serializable)readersMap);
|
||||
if (readersMap == null)
|
||||
{
|
||||
nodeService.removeAspect(nodeRef, ASPECT_EXTENDED_READERS);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#removeAllExtendedReaders(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public void removeAllExtendedReaders(NodeRef nodeRef)
|
||||
public void removeAllExtendedSecurity(NodeRef nodeRef)
|
||||
{
|
||||
removeAllExtendedReaders(nodeRef, true);
|
||||
removeAllExtendedSecurity(nodeRef, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#removeAllExtendedReaders(org.alfresco.service.cmr.repository.NodeRef, boolean)
|
||||
*/
|
||||
@Override
|
||||
public void removeAllExtendedReaders(NodeRef nodeRef, boolean applyToParents)
|
||||
public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents)
|
||||
{
|
||||
if (hasExtendedReaders(nodeRef) == true)
|
||||
if (hasExtendedSecurity(nodeRef) == true)
|
||||
{
|
||||
Set<String> readers = getExtendedReaders(nodeRef);
|
||||
if (readers != null && readers.isEmpty() == false)
|
||||
{
|
||||
removeExtendedReaders(nodeRef, readers);
|
||||
}
|
||||
removeExtendedSecurity(nodeRef, getExtendedReaders(nodeRef), getExtendedWriters(nodeRef));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,11 +371,10 @@ public class ExtendedSecurityServiceImpl implements ExtendedSecurityService,
|
||||
NodeRef oldParent = origAssoc.getParentRef();
|
||||
|
||||
Set<String> readers = getExtendedReaders(record);
|
||||
if (readers != null && readers.size() != 0)
|
||||
{
|
||||
setExtendedReaders(newParent, readers);
|
||||
removeExtendedReaders(oldParent, readers);
|
||||
}
|
||||
Set<String> writers = getExtendedWriters(record);
|
||||
|
||||
addExtendedSecurity(newParent, readers, writers);
|
||||
removeExtendedSecurity(oldParent, readers, writers);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* Extended writers dynamic authority implementation.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
* @since 2.1
|
||||
*/
|
||||
public class ExtendedWriterDynamicAuthority extends ExtendedSecurityBaseDynamicAuthority
|
||||
{
|
||||
/** Extended writer role */
|
||||
public static final String EXTENDED_WRITER = "ROLE_EXTENDED_WRITER";
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.security.permissions.DynamicAuthority#getAuthority()
|
||||
*/
|
||||
@Override
|
||||
public String getAuthority()
|
||||
{
|
||||
return EXTENDED_WRITER;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
protected Set<String> getAuthorites(NodeRef nodeRef)
|
||||
{
|
||||
return getExtendedSecurityService().getExtendedWriters(nodeRef);
|
||||
}
|
||||
}
|
@@ -171,14 +171,15 @@ public class FilePlanPermissionServiceImpl implements FilePlanPermissionService,
|
||||
final NodeRef catNodeRef = childAssocRef.getParentRef();
|
||||
if (nodeService.exists(catNodeRef) == true)
|
||||
{
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
public Object doWork()
|
||||
{
|
||||
Set<AccessPermission> perms = permissionService.getAllSetPermissions(catNodeRef);
|
||||
for (AccessPermission perm : perms)
|
||||
{
|
||||
if (ExtendedReaderDynamicAuthority.EXTENDED_READER.equals(perm.getAuthority()) == false)
|
||||
if (ExtendedReaderDynamicAuthority.EXTENDED_READER.equals(perm.getAuthority()) == false &&
|
||||
ExtendedWriterDynamicAuthority.EXTENDED_WRITER.equals(perm.getAuthority()) == false)
|
||||
{
|
||||
AccessStatus accessStatus = perm.getAccessStatus();
|
||||
boolean allow = false;
|
||||
@@ -217,6 +218,7 @@ public class FilePlanPermissionServiceImpl implements FilePlanPermissionService,
|
||||
|
||||
// set extended reader permissions
|
||||
permissionService.setPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true);
|
||||
permissionService.setPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.security.permissions.impl;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
|
||||
/**
|
||||
* Extended Permission Service Interface used in RM.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
* @since 2.1
|
||||
*/
|
||||
public interface ExtendedPermissionService extends PermissionService
|
||||
{
|
||||
public Set<String> getWriters(Long aclId);
|
||||
}
|
@@ -18,14 +18,18 @@
|
||||
*/
|
||||
package org.alfresco.repo.security.permissions.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.repo.security.permissions.AccessControlEntry;
|
||||
import org.alfresco.repo.security.permissions.AccessControlList;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
* Extends the core permission service implementation allowing the consideration of the read records
|
||||
@@ -36,7 +40,31 @@ import org.alfresco.service.cmr.security.PermissionService;
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class RMPermissionServiceImpl extends PermissionServiceImpl
|
||||
implements ExtendedPermissionService
|
||||
{
|
||||
protected SimpleCache<Serializable, Set<String>> writersCache;
|
||||
|
||||
@Override
|
||||
public void setAnyDenyDenies(boolean anyDenyDenies)
|
||||
{
|
||||
super.setAnyDenyDenies(anyDenyDenies);
|
||||
writersCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param writersCache the writersCache to set
|
||||
*/
|
||||
public void setWritersCache(SimpleCache<Serializable, Set<String>> writersCache)
|
||||
{
|
||||
this.writersCache = writersCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
super.onBootstrap(event);
|
||||
PropertyCheck.mandatory(this, "writersCache", writersCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the set of authorities who can read the given ACL. No caching is done here.
|
||||
@@ -103,5 +131,44 @@ public class RMPermissionServiceImpl extends PermissionServiceImpl
|
||||
}
|
||||
|
||||
return denied;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.security.permissions.impl.ExtendedPermissionService#getWriters(java.lang.Long)
|
||||
*/
|
||||
public Set<String> getWriters(Long aclId)
|
||||
{
|
||||
AccessControlList acl = aclDaoComponent.getAccessControlList(aclId);
|
||||
if (acl == null)
|
||||
{
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
Set<String> aclWriters = writersCache.get((Serializable)acl.getProperties());
|
||||
if (aclWriters != null)
|
||||
{
|
||||
return aclWriters;
|
||||
}
|
||||
|
||||
HashSet<String> assigned = new HashSet<String>();
|
||||
HashSet<String> readers = new HashSet<String>();
|
||||
|
||||
for (AccessControlEntry ace : acl.getEntries())
|
||||
{
|
||||
assigned.add(ace.getAuthority());
|
||||
}
|
||||
|
||||
for (String authority : assigned)
|
||||
{
|
||||
UnconditionalAclTest test = new UnconditionalAclTest(getPermissionReference(PermissionService.WRITE));
|
||||
if (test.evaluate(authority, aclId))
|
||||
{
|
||||
readers.add(authority);
|
||||
}
|
||||
}
|
||||
|
||||
aclWriters = Collections.unmodifiableSet(readers);
|
||||
writersCache.put((Serializable)acl.getProperties(), aclWriters);
|
||||
return aclWriters;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user