mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Merge release/V2.3 into release/2.4
This commit is contained in:
@@ -60,6 +60,7 @@
|
|||||||
org.alfresco.service.cmr.security.PermissionService.hasPermission=ACL_ALLOW
|
org.alfresco.service.cmr.security.PermissionService.hasPermission=ACL_ALLOW
|
||||||
org.alfresco.service.cmr.security.PermissionService.getReaders=ACL_METHOD.ROLE_ADMINISTRATOR
|
org.alfresco.service.cmr.security.PermissionService.getReaders=ACL_METHOD.ROLE_ADMINISTRATOR
|
||||||
org.alfresco.repo.security.permissions.impl.ExtendedPermissionService.getWriters=ACL_METHOD.ROLE_ADMINISTRATOR
|
org.alfresco.repo.security.permissions.impl.ExtendedPermissionService.getWriters=ACL_METHOD.ROLE_ADMINISTRATOR
|
||||||
|
org.alfresco.repo.security.permissions.impl.ExtendedPermissionService.getReadersAndWriters=ACL_METHOD.ROLE_ADMINISTRATOR
|
||||||
org.alfresco.service.cmr.security.PermissionService.deletePermissions=ACL_NODE.0.sys:base.ChangePermissions
|
org.alfresco.service.cmr.security.PermissionService.deletePermissions=ACL_NODE.0.sys:base.ChangePermissions
|
||||||
org.alfresco.service.cmr.security.PermissionService.deletePermission=ACL_NODE.0.sys:base.ChangePermissions
|
org.alfresco.service.cmr.security.PermissionService.deletePermission=ACL_NODE.0.sys:base.ChangePermissions
|
||||||
org.alfresco.service.cmr.security.PermissionService.setPermission=ACL_NODE.0.sys:base.ChangePermissions
|
org.alfresco.service.cmr.security.PermissionService.setPermission=ACL_NODE.0.sys:base.ChangePermissions
|
||||||
|
@@ -55,4 +55,5 @@ log4j.logger.org.alfresco.module.org_alfresco_module_rm.patch=info
|
|||||||
#
|
#
|
||||||
# Job debug
|
# Job debug
|
||||||
#
|
#
|
||||||
#log4j.logger.org.alfresco.module.org_alfresco_module_rm.job=debug
|
#log4j.logger.org.alfresco.module.org_alfresco_module_rm.job=debug
|
||||||
|
log4j.logger.org.alfresco.repo.web.scripts.roles.DynamicAuthoritiesGet=info
|
@@ -573,7 +573,10 @@
|
|||||||
parent="baseService">
|
parent="baseService">
|
||||||
<property name="nodeService" ref="nodeService"/>
|
<property name="nodeService" ref="nodeService"/>
|
||||||
<property name="filePlanService" ref="filePlanService" />
|
<property name="filePlanService" ref="filePlanService" />
|
||||||
<property name="filePlanRoleService" ref="filePlanRoleService" />
|
<property name="filePlanRoleService" ref="filePlanRoleService" />
|
||||||
|
<property name="authorityService" ref="authorityService"/>
|
||||||
|
<property name="permissionService" ref="permissionService"/>
|
||||||
|
<property name="transactionService" ref="transactionService"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="ExtendedSecurityService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
<bean id="ExtendedSecurityService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||||
|
@@ -28,7 +28,6 @@
|
|||||||
<property name="cmObjectType" ref="cm.object" />
|
<property name="cmObjectType" ref="cm.object" />
|
||||||
<property name="extendedPermissionService" ref="ExtendedPermissionService" />
|
<property name="extendedPermissionService" ref="ExtendedPermissionService" />
|
||||||
<property name="extendedSecurityService" ref="ExtendedSecurityService" />
|
<property name="extendedSecurityService" ref="ExtendedSecurityService" />
|
||||||
<property name="ownableService" ref="OwnableService" />
|
|
||||||
</bean>
|
</bean>
|
||||||
<bean class="org.alfresco.util.BeanExtender">
|
<bean class="org.alfresco.util.BeanExtender">
|
||||||
<property name="beanName" value="versionService" />
|
<property name="beanName" value="versionService" />
|
||||||
|
@@ -587,6 +587,19 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- Remove Dynamic Authorities GET webscript -->
|
||||||
|
<bean id="webscript.org.alfresco.repository.roles.rm-dynamicauthorities.get"
|
||||||
|
class="org.alfresco.repo.web.scripts.roles.DynamicAuthoritiesGet"
|
||||||
|
parent="webscript">
|
||||||
|
<property name="patchDAO" ref="patchDAO"/>
|
||||||
|
<property name="nodeDAO" ref="nodeDAO"/>
|
||||||
|
<property name="qnameDAO" ref="qnameDAO"/>
|
||||||
|
<property name="nodeService" ref="nodeService"/>
|
||||||
|
<property name="permissionService" ref="permissionService"/>
|
||||||
|
<property name="extendedSecurityService" ref="extendedSecurityService"/>
|
||||||
|
<property name="transactionService" ref="transactionService"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<!-- REST impl for GET Holds -->
|
<!-- REST impl for GET Holds -->
|
||||||
<bean id="webscript.org.alfresco.rma.holds.get"
|
<bean id="webscript.org.alfresco.rma.holds.get"
|
||||||
class="org.alfresco.module.org_alfresco_module_rm.script.hold.HoldsGet"
|
class="org.alfresco.module.org_alfresco_module_rm.script.hold.HoldsGet"
|
||||||
|
@@ -0,0 +1,13 @@
|
|||||||
|
<webscript>
|
||||||
|
<shortname>Removes dynamic authorities</shortname>
|
||||||
|
<description><![CDATA[
|
||||||
|
Removes dynamic authorities from in place records created in previous verssions.<br/>
|
||||||
|
URL parameter batchsize is mandatory, and represents the number of records that are processed in one transaction.<br/>
|
||||||
|
URL parameter maxProcessedRecords is optional, and represents the maximum number of records that will be processed in one request.<br/>
|
||||||
|
]]>
|
||||||
|
</description>
|
||||||
|
<url>/api/rm/rm-dynamicauthorities?batchsize={batchsize}&maxProcessedRecords={maxProcessedRecords?}</url>
|
||||||
|
<format default="json">argument</format>
|
||||||
|
<authentication>admin</authentication>
|
||||||
|
<transaction allow="readonly">required</transaction>
|
||||||
|
</webscript>
|
@@ -0,0 +1,30 @@
|
|||||||
|
<#--
|
||||||
|
#%L
|
||||||
|
Alfresco Records Management Module
|
||||||
|
%%
|
||||||
|
Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
|
%%
|
||||||
|
This file is part of the Alfresco software.
|
||||||
|
-
|
||||||
|
If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
provided under the following open source license terms:
|
||||||
|
-
|
||||||
|
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/>.
|
||||||
|
#L%
|
||||||
|
-->
|
||||||
|
{
|
||||||
|
"responsestatus" : "${responsestatus?json_string}",
|
||||||
|
"message" : "${message?json_string}"
|
||||||
|
}
|
@@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* 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/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated extended security service for compatibility.
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
*/
|
||||||
|
public interface DeprecatedExtendedSecurityService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Gets the set of authorities that are extended readers for the given node.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @return {@link Set}<{@link String}> set of extended readers
|
||||||
|
*
|
||||||
|
* @deprecated as of 2.5, use {@link ExtendedSecurityService#getReaders(NodeRef)}
|
||||||
|
*/
|
||||||
|
Set<String> getExtendedReaders(NodeRef nodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the set of authorities that are extended writers for the given node.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @return {@link Set}<{@link String}> set of extended writers
|
||||||
|
*
|
||||||
|
* @deprecated as of 2.5, use {@link ExtendedSecurityService#getWriters(NodeRef)}
|
||||||
|
*/
|
||||||
|
Set<String> getExtendedWriters(NodeRef nodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add extended security for the specified authorities to a node.
|
||||||
|
*
|
||||||
|
* As of, 2.5 this method no longer applies the extended security to parents.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @param readers set of authorities to add extended read permissions
|
||||||
|
* @param writers set of authorities to add extended write permissions
|
||||||
|
*
|
||||||
|
* @deprecated as of 2.5, use {@link ExtendedSecurityService#set(NodeRef, Set, Set)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add extended security for the specified authorities to a node.
|
||||||
|
* <p>
|
||||||
|
* If specified, the read and write extended permissions are applied to all parents up to the file plan as
|
||||||
|
* extended read. This ensures parental read, but not parental write.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @param readers set of authorities to add extended read permissions
|
||||||
|
* @param writers set of authorities to add extended write permissions
|
||||||
|
* @param applyToParents true if extended security applied to parents (read only) false otherwise.
|
||||||
|
*
|
||||||
|
* @deprecated as of 2.5, because extended security is no longer applied to parents. Note that calling this method will
|
||||||
|
* only apply the extended security to the node and the applyToParents parameter value will be ignored.
|
||||||
|
*
|
||||||
|
* @see ExtendedSecurityService#set(NodeRef, Set, Set)
|
||||||
|
*/
|
||||||
|
@Deprecated void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all extended readers and writers from the given node reference.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
*
|
||||||
|
* @deprecated as of 2.5, see {@link ExtendedSecurityService#remove(NodeRef)}
|
||||||
|
*/
|
||||||
|
@Deprecated void removeAllExtendedSecurity(NodeRef nodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the extended security for the specified authorities from a node.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @param readers set of authorities to remove as extended readers
|
||||||
|
* @param writers set of authorities to remove as extended writers
|
||||||
|
*
|
||||||
|
* @deprecated as of 2.5, because partial removal of readers and writers from node or parents is no longer supported.
|
||||||
|
* Note that calling this method will now remove all extended security from the node and never applied to parents.
|
||||||
|
*
|
||||||
|
* @see {@link ExtendedSecurityService#remove(NodeRef)}
|
||||||
|
*/
|
||||||
|
@Deprecated void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the extended security for the specified authorities from a node.
|
||||||
|
* <p>
|
||||||
|
* If specified, extended security will also be removed from the parent hierarchy.(read only). Note that
|
||||||
|
* extended security is records as a reference count, so security will only be utterly removed from the parent
|
||||||
|
* hierarchy if all references to the authority are removed.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @param readers set of authorities to remove as extended readers
|
||||||
|
* @param writers set of authorities to remove as extedned writers
|
||||||
|
* @param applyToParents true if removal of extended security is applied to parent hierarchy (read only), false
|
||||||
|
* otherwise
|
||||||
|
*
|
||||||
|
* @deprecated as of 2.5, because partial removal of readers and writers from node or parents is no longer supported.
|
||||||
|
* Note that calling this method will now remove all extended security from the node and never applied to parents.
|
||||||
|
*
|
||||||
|
* @see {@link ExtendedSecurityService#remove(NodeRef)}
|
||||||
|
*/
|
||||||
|
@Deprecated void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all extended readers and writers from the given node reference.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @param applyToParents if true then apply removal to parent hierarchy (read only) false otherwise.
|
||||||
|
*
|
||||||
|
* @deprecated as of 2.5, because partial removal of readers and writers from node or parents is no longer supported.
|
||||||
|
* Note that calling this method will now remove all extended security from the node and never applied to parents.
|
||||||
|
*
|
||||||
|
* @see {@link ExtendedSecurityService#remove(NodeRef)}
|
||||||
|
*/
|
||||||
|
@Deprecated void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents);
|
||||||
|
}
|
@@ -1,97 +1,98 @@
|
|||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* Alfresco Records Management Module
|
* Alfresco Records Management Module
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* -
|
* -
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
* the paid license agreement will prevail. Otherwise, the software is
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
* provided under the following open source license terms:
|
* provided under the following open source license terms:
|
||||||
* -
|
* -
|
||||||
* Alfresco is free software: you can redistribute it and/or modify
|
* 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
|
* 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
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
* -
|
* -
|
||||||
* Alfresco is distributed in the hope that it will be useful,
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
* -
|
* -
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.alfresco.module.org_alfresco_module_rm.security;
|
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||||
import org.alfresco.repo.security.permissions.PermissionReference;
|
import org.alfresco.repo.security.permissions.PermissionReference;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extended readers dynamic authority implementation.
|
* Extended readers dynamic authority implementation.
|
||||||
*
|
*
|
||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
* @since 2.1
|
* @since 2.1
|
||||||
*/
|
*/
|
||||||
public class ExtendedReaderDynamicAuthority extends ExtendedSecurityBaseDynamicAuthority
|
@Deprecated
|
||||||
{
|
public class ExtendedReaderDynamicAuthority extends ExtendedSecurityBaseDynamicAuthority
|
||||||
/** Extended reader role */
|
{
|
||||||
public static final String EXTENDED_READER = "ROLE_EXTENDED_READER";
|
/** Extended reader role */
|
||||||
|
public static final String EXTENDED_READER = "ROLE_EXTENDED_READER";
|
||||||
/**
|
|
||||||
* @see org.alfresco.repo.security.permissions.DynamicAuthority#getAuthority()
|
/**
|
||||||
*/
|
* @see org.alfresco.repo.security.permissions.DynamicAuthority#getAuthority()
|
||||||
@Override
|
*/
|
||||||
public String getAuthority()
|
@Override
|
||||||
{
|
public String getAuthority()
|
||||||
return EXTENDED_READER;
|
{
|
||||||
}
|
return EXTENDED_READER;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
|
/**
|
||||||
*/
|
* @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
|
||||||
@Override
|
*/
|
||||||
public Set<PermissionReference> requiredFor()
|
@Override
|
||||||
{
|
public Set<PermissionReference> requiredFor()
|
||||||
if (requiredFor == null)
|
{
|
||||||
{
|
if (requiredFor == null)
|
||||||
requiredFor = Collections.singleton(getModelDAO().getPermissionReference(null, RMPermissionModel.READ_RECORDS));
|
{
|
||||||
}
|
requiredFor = Collections.singleton(getModelDAO().getPermissionReference(null, RMPermissionModel.READ_RECORDS));
|
||||||
|
}
|
||||||
return requiredFor;
|
|
||||||
}
|
return requiredFor;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef)
|
/**
|
||||||
*/
|
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
@SuppressWarnings("unchecked")
|
*/
|
||||||
protected Set<String> getAuthorites(NodeRef nodeRef)
|
@SuppressWarnings("unchecked")
|
||||||
{
|
protected Set<String> getAuthorites(NodeRef nodeRef)
|
||||||
Set<String> result = null;
|
{
|
||||||
|
Set<String> result = null;
|
||||||
Map<String, Integer> readerMap = (Map<String, Integer>)getNodeService().getProperty(nodeRef, PROP_READERS);
|
|
||||||
if (readerMap != null)
|
Map<String, Integer> readerMap = (Map<String, Integer>)getNodeService().getProperty(nodeRef, PROP_READERS);
|
||||||
{
|
if (readerMap != null)
|
||||||
result = readerMap.keySet();
|
{
|
||||||
}
|
result = readerMap.keySet();
|
||||||
|
}
|
||||||
return result;
|
|
||||||
}
|
return result;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName()
|
/**
|
||||||
*/
|
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName()
|
||||||
@Override
|
*/
|
||||||
protected String getTransactionCacheName()
|
@Override
|
||||||
{
|
protected String getTransactionCacheName()
|
||||||
return "rm.extendedreaderdynamicauthority";
|
{
|
||||||
}
|
return "rm.extendedreaderdynamicauthority";
|
||||||
}
|
}
|
||||||
|
}
|
@@ -1,191 +1,192 @@
|
|||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* Alfresco Records Management Module
|
* Alfresco Records Management Module
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* -
|
* -
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
* the paid license agreement will prevail. Otherwise, the software is
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
* provided under the following open source license terms:
|
* provided under the following open source license terms:
|
||||||
* -
|
* -
|
||||||
* Alfresco is free software: you can redistribute it and/or modify
|
* 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
|
* 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
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
* -
|
* -
|
||||||
* Alfresco is distributed in the hope that it will be useful,
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
* -
|
* -
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.alfresco.module.org_alfresco_module_rm.security;
|
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||||
import org.alfresco.repo.security.permissions.DynamicAuthority;
|
import org.alfresco.repo.security.permissions.DynamicAuthority;
|
||||||
import org.alfresco.repo.security.permissions.PermissionReference;
|
import org.alfresco.repo.security.permissions.PermissionReference;
|
||||||
import org.alfresco.repo.security.permissions.impl.ModelDAO;
|
import org.alfresco.repo.security.permissions.impl.ModelDAO;
|
||||||
import org.alfresco.repo.transaction.TransactionalResourceHelper;
|
import org.alfresco.repo.transaction.TransactionalResourceHelper;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
import org.alfresco.service.cmr.security.AuthorityService;
|
import org.alfresco.service.cmr.security.AuthorityService;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extended readers dynamic authority implementation.
|
* Extended readers dynamic authority implementation.
|
||||||
*
|
*
|
||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
* @since 2.1
|
* @since 2.1
|
||||||
*/
|
*/
|
||||||
public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAuthority,
|
@Deprecated
|
||||||
RecordsManagementModel,
|
public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAuthority,
|
||||||
ApplicationContextAware
|
RecordsManagementModel,
|
||||||
{
|
ApplicationContextAware
|
||||||
/** Authority service */
|
{
|
||||||
private AuthorityService authorityService;
|
/** Authority service */
|
||||||
|
private AuthorityService authorityService;
|
||||||
/** Extended security service */
|
|
||||||
private ExtendedSecurityService extendedSecurityService;
|
/** Extended security service */
|
||||||
|
private ExtendedSecurityService extendedSecurityService;
|
||||||
/** Node service */
|
|
||||||
private NodeService nodeService;
|
/** Node service */
|
||||||
|
private NodeService nodeService;
|
||||||
/** Application context */
|
|
||||||
protected ApplicationContext applicationContext;
|
/** Application context */
|
||||||
|
protected ApplicationContext applicationContext;
|
||||||
/** model DAO */
|
|
||||||
protected ModelDAO modelDAO;
|
/** model DAO */
|
||||||
|
protected ModelDAO modelDAO;
|
||||||
/** permission reference */
|
|
||||||
protected Set<PermissionReference> requiredFor;
|
/** permission reference */
|
||||||
|
protected Set<PermissionReference> requiredFor;
|
||||||
// NOTE: we get the services directly from the application context in this way to avoid
|
|
||||||
// cyclic relationships and issues when loading the application context
|
// 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
|
/**
|
||||||
*/
|
* @return authority service
|
||||||
protected AuthorityService getAuthorityService()
|
*/
|
||||||
{
|
protected AuthorityService getAuthorityService()
|
||||||
if (authorityService == null)
|
{
|
||||||
{
|
if (authorityService == null)
|
||||||
authorityService = (AuthorityService)applicationContext.getBean("authorityService");
|
{
|
||||||
}
|
authorityService = (AuthorityService)applicationContext.getBean("authorityService");
|
||||||
return authorityService;
|
}
|
||||||
}
|
return authorityService;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @return extended security service
|
/**
|
||||||
*/
|
* @return extended security service
|
||||||
protected ExtendedSecurityService getExtendedSecurityService()
|
*/
|
||||||
{
|
protected ExtendedSecurityService getExtendedSecurityService()
|
||||||
if (extendedSecurityService == null)
|
{
|
||||||
{
|
if (extendedSecurityService == null)
|
||||||
extendedSecurityService = (ExtendedSecurityService)applicationContext.getBean("extendedSecurityService");
|
{
|
||||||
}
|
extendedSecurityService = (ExtendedSecurityService)applicationContext.getBean("extendedSecurityService");
|
||||||
return extendedSecurityService;
|
}
|
||||||
}
|
return extendedSecurityService;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @return node service
|
/**
|
||||||
*/
|
* @return node service
|
||||||
protected NodeService getNodeService()
|
*/
|
||||||
{
|
protected NodeService getNodeService()
|
||||||
if (nodeService == null)
|
{
|
||||||
{
|
if (nodeService == null)
|
||||||
nodeService = (NodeService)applicationContext.getBean("dbNodeService");
|
{
|
||||||
}
|
nodeService = (NodeService)applicationContext.getBean("dbNodeService");
|
||||||
return nodeService;
|
}
|
||||||
}
|
return nodeService;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @return model DAO
|
/**
|
||||||
*/
|
* @return model DAO
|
||||||
protected ModelDAO getModelDAO()
|
*/
|
||||||
{
|
protected ModelDAO getModelDAO()
|
||||||
if (modelDAO == null)
|
{
|
||||||
{
|
if (modelDAO == null)
|
||||||
modelDAO = (ModelDAO)applicationContext.getBean("permissionsModelDAO");
|
{
|
||||||
}
|
modelDAO = (ModelDAO)applicationContext.getBean("permissionsModelDAO");
|
||||||
return modelDAO;
|
}
|
||||||
}
|
return modelDAO;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @return String transaction cache name
|
/**
|
||||||
*/
|
* @return String transaction cache name
|
||||||
protected abstract String getTransactionCacheName();
|
*/
|
||||||
|
protected abstract String getTransactionCacheName();
|
||||||
/**
|
|
||||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
/**
|
||||||
*/
|
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||||
@Override
|
*/
|
||||||
public void setApplicationContext(ApplicationContext applicationContext)
|
@Override
|
||||||
{
|
public void setApplicationContext(ApplicationContext applicationContext)
|
||||||
this.applicationContext = applicationContext;
|
{
|
||||||
}
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Gets a list of the authorities from the extended security aspect that this dynamic
|
/**
|
||||||
* authority is checking against.
|
* Gets a list of the authorities from the extended security aspect that this dynamic
|
||||||
*
|
* authority is checking against.
|
||||||
* @param nodeRef
|
*
|
||||||
* @return
|
* @param nodeRef
|
||||||
*/
|
* @return
|
||||||
protected abstract Set<String> getAuthorites(NodeRef nodeRef);
|
*/
|
||||||
|
protected abstract Set<String> getAuthorites(NodeRef nodeRef);
|
||||||
/**
|
|
||||||
* @see org.alfresco.repo.security.permissions.DynamicAuthority#hasAuthority(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
|
/**
|
||||||
*/
|
* @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)
|
@Override
|
||||||
{
|
public boolean hasAuthority(NodeRef nodeRef, String userName)
|
||||||
boolean result = false;
|
{
|
||||||
|
boolean result = false;
|
||||||
Map<Pair<NodeRef, String>, Boolean> transactionCache = TransactionalResourceHelper.getMap(getTransactionCacheName());
|
|
||||||
Pair<NodeRef, String> key = new Pair<NodeRef, String>(nodeRef, userName);
|
Map<Pair<NodeRef, String>, Boolean> transactionCache = TransactionalResourceHelper.getMap(getTransactionCacheName());
|
||||||
|
Pair<NodeRef, String> key = new Pair<NodeRef, String>(nodeRef, userName);
|
||||||
if (transactionCache.containsKey(key))
|
|
||||||
{
|
if (transactionCache.containsKey(key))
|
||||||
result = transactionCache.get(key);
|
{
|
||||||
}
|
result = transactionCache.get(key);
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY))
|
{
|
||||||
{
|
if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY))
|
||||||
Set<String> authorities = getAuthorites(nodeRef);
|
{
|
||||||
if (authorities != null)
|
Set<String> authorities = getAuthorites(nodeRef);
|
||||||
{
|
if (authorities != null)
|
||||||
// check for everyone or the user
|
{
|
||||||
if (authorities.contains("GROUP_EVEYONE") ||
|
// check for everyone or the user
|
||||||
authorities.contains(userName))
|
if (authorities.contains("GROUP_EVEYONE") ||
|
||||||
{
|
authorities.contains(userName))
|
||||||
result = true;
|
{
|
||||||
}
|
result = true;
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
// determine whether any of the users groups are in the extended security
|
{
|
||||||
Set<String> contained = getAuthorityService().getAuthoritiesForUser(userName);
|
// determine whether any of the users groups are in the extended security
|
||||||
authorities.retainAll(contained);
|
Set<String> contained = getAuthorityService().getAuthoritiesForUser(userName);
|
||||||
result = (authorities.size() != 0);
|
authorities.retainAll(contained);
|
||||||
}
|
result = (authorities.size() != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// cache result
|
|
||||||
transactionCache.put(key, result);
|
// cache result
|
||||||
}
|
transactionCache.put(key, result);
|
||||||
|
}
|
||||||
return result;
|
|
||||||
}
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
@@ -1,102 +1,103 @@
|
|||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* Alfresco Records Management Module
|
* Alfresco Records Management Module
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* -
|
* -
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
* the paid license agreement will prevail. Otherwise, the software is
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
* provided under the following open source license terms:
|
* provided under the following open source license terms:
|
||||||
* -
|
* -
|
||||||
* Alfresco is free software: you can redistribute it and/or modify
|
* 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
|
* 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
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
* -
|
* -
|
||||||
* Alfresco is distributed in the hope that it will be useful,
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
* -
|
* -
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.alfresco.module.org_alfresco_module_rm.security;
|
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||||
import org.alfresco.repo.security.permissions.PermissionReference;
|
import org.alfresco.repo.security.permissions.PermissionReference;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extended writers dynamic authority implementation.
|
* Extended writers dynamic authority implementation.
|
||||||
*
|
*
|
||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
* @since 2.1
|
* @since 2.1
|
||||||
*/
|
*/
|
||||||
public class ExtendedWriterDynamicAuthority extends ExtendedSecurityBaseDynamicAuthority
|
@Deprecated
|
||||||
{
|
public class ExtendedWriterDynamicAuthority extends ExtendedSecurityBaseDynamicAuthority
|
||||||
/** Extended writer role */
|
{
|
||||||
public static final String EXTENDED_WRITER = "ROLE_EXTENDED_WRITER";
|
/** Extended writer role */
|
||||||
|
public static final String EXTENDED_WRITER = "ROLE_EXTENDED_WRITER";
|
||||||
/**
|
|
||||||
* @see org.alfresco.repo.security.permissions.DynamicAuthority#getAuthority()
|
/**
|
||||||
*/
|
* @see org.alfresco.repo.security.permissions.DynamicAuthority#getAuthority()
|
||||||
@Override
|
*/
|
||||||
public String getAuthority()
|
@Override
|
||||||
{
|
public String getAuthority()
|
||||||
return EXTENDED_WRITER;
|
{
|
||||||
}
|
return EXTENDED_WRITER;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
|
/**
|
||||||
*/
|
* @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
|
||||||
@Override
|
*/
|
||||||
public Set<PermissionReference> requiredFor()
|
@Override
|
||||||
{
|
public Set<PermissionReference> requiredFor()
|
||||||
if (requiredFor == null)
|
{
|
||||||
{
|
if (requiredFor == null)
|
||||||
requiredFor = new HashSet<PermissionReference>(3);
|
{
|
||||||
Collections.addAll(requiredFor,
|
requiredFor = new HashSet<PermissionReference>(3);
|
||||||
getModelDAO().getPermissionReference(null, RMPermissionModel.READ_RECORDS),
|
Collections.addAll(requiredFor,
|
||||||
getModelDAO().getPermissionReference(null, RMPermissionModel.FILING),
|
getModelDAO().getPermissionReference(null, RMPermissionModel.READ_RECORDS),
|
||||||
getModelDAO().getPermissionReference(null, RMPermissionModel.FILE_RECORDS));
|
getModelDAO().getPermissionReference(null, RMPermissionModel.FILING),
|
||||||
}
|
getModelDAO().getPermissionReference(null, RMPermissionModel.FILE_RECORDS));
|
||||||
|
}
|
||||||
return requiredFor;
|
|
||||||
}
|
return requiredFor;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef)
|
/**
|
||||||
*/
|
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
@SuppressWarnings("unchecked")
|
*/
|
||||||
protected Set<String> getAuthorites(NodeRef nodeRef)
|
@SuppressWarnings("unchecked")
|
||||||
{
|
protected Set<String> getAuthorites(NodeRef nodeRef)
|
||||||
Set<String> result = null;
|
{
|
||||||
|
Set<String> result = null;
|
||||||
Map<String, Integer> map = (Map<String, Integer>)getNodeService().getProperty(nodeRef, PROP_WRITERS);
|
|
||||||
if (map != null)
|
Map<String, Integer> map = (Map<String, Integer>)getNodeService().getProperty(nodeRef, PROP_WRITERS);
|
||||||
{
|
if (map != null)
|
||||||
result = map.keySet();
|
{
|
||||||
}
|
result = map.keySet();
|
||||||
|
}
|
||||||
return result;
|
|
||||||
}
|
return result;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName()
|
/**
|
||||||
*/
|
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName()
|
||||||
@Override
|
*/
|
||||||
protected String getTransactionCacheName()
|
@Override
|
||||||
{
|
protected String getTransactionCacheName()
|
||||||
return "rm.extendedwriterdynamicauthority";
|
{
|
||||||
}
|
return "rm.extendedwriterdynamicauthority";
|
||||||
}
|
}
|
||||||
|
}
|
@@ -1,58 +1,59 @@
|
|||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* Alfresco Records Management Module
|
* Alfresco Records Management Module
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* -
|
* -
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
* the paid license agreement will prevail. Otherwise, the software is
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
* provided under the following open source license terms:
|
* provided under the following open source license terms:
|
||||||
* -
|
* -
|
||||||
* Alfresco is free software: you can redistribute it and/or modify
|
* 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
|
* 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
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
* -
|
* -
|
||||||
* Alfresco is distributed in the hope that it will be useful,
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
* -
|
* -
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.alfresco.module.org_alfresco_module_rm.security;
|
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||||
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File plan authentication service.
|
* File plan authentication service.
|
||||||
*
|
*
|
||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
* @since 2.1
|
* @since 2.1
|
||||||
*/
|
* @deprecated as of 2.2, use {@link AuthenticationUtil}.
|
||||||
public interface FilePlanAuthenticationService
|
*/
|
||||||
{
|
public interface FilePlanAuthenticationService
|
||||||
/**
|
{
|
||||||
* @return rm admin user name
|
/**
|
||||||
*
|
* @return rm admin user name
|
||||||
* @deprecated as of 2.2, use {@link AuthenticationUtil#getAdminUserName()}
|
*
|
||||||
*/
|
* @deprecated as of 2.2, use {@link AuthenticationUtil#getAdminUserName()}
|
||||||
String getRmAdminUserName();
|
*/
|
||||||
|
String getRmAdminUserName();
|
||||||
/**
|
|
||||||
* Run provided work as the global rm admin user.
|
/**
|
||||||
*
|
* Run provided work as the global rm admin user.
|
||||||
* @param <R> return type
|
*
|
||||||
* @param runAsWork work to execute as the rm admin user
|
* @param <R> return type
|
||||||
* @return R result of work execution
|
* @param runAsWork work to execute as the rm admin user
|
||||||
*
|
* @return R result of work execution
|
||||||
* @deprecated as of 2.2, use {@link AuthenticationUtil#runAs(RunAsWork, AuthenticationUtil#getAdminUserName())}
|
*
|
||||||
*/
|
* @deprecated as of 2.2, use {@link AuthenticationUtil#runAs(RunAsWork, AuthenticationUtil#getAdminUserName())}
|
||||||
<R> R runAsRmAdmin(RunAsWork<R> runAsWork);
|
*/
|
||||||
}
|
<R> R runAsRmAdmin(RunAsWork<R> runAsWork);
|
||||||
|
}
|
@@ -1,62 +1,63 @@
|
|||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* Alfresco Records Management Module
|
* Alfresco Records Management Module
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* -
|
* -
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
* the paid license agreement will prevail. Otherwise, the software is
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
* provided under the following open source license terms:
|
* provided under the following open source license terms:
|
||||||
* -
|
* -
|
||||||
* Alfresco is free software: you can redistribute it and/or modify
|
* 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
|
* 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
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
* -
|
* -
|
||||||
* Alfresco is distributed in the hope that it will be useful,
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
* -
|
* -
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.alfresco.module.org_alfresco_module_rm.security;
|
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||||
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
* @since 2.1
|
* @since 2.1
|
||||||
*/
|
*/
|
||||||
public class FilePlanAuthenticationServiceImpl implements FilePlanAuthenticationService
|
@Deprecated
|
||||||
{
|
public class FilePlanAuthenticationServiceImpl implements FilePlanAuthenticationService
|
||||||
/** Default rm admin user values */
|
{
|
||||||
@Deprecated
|
/** Default rm admin user values */
|
||||||
public static final String DEFAULT_RM_ADMIN_USER = "rmadmin";
|
@Deprecated
|
||||||
|
public static final String DEFAULT_RM_ADMIN_USER = "rmadmin";
|
||||||
/**
|
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.FilePlanAuthenticationService#getRMAdminUserName()
|
/**
|
||||||
*/
|
* @see org.alfresco.module.org_alfresco_module_rm.security.FilePlanAuthenticationService#getRMAdminUserName()
|
||||||
@Override
|
*/
|
||||||
@Deprecated
|
@Override
|
||||||
public String getRmAdminUserName()
|
@Deprecated
|
||||||
{
|
public String getRmAdminUserName()
|
||||||
return AuthenticationUtil.getAdminUserName();
|
{
|
||||||
}
|
return AuthenticationUtil.getAdminUserName();
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.FilePlanAuthenticationService#runAsRMAdmin(org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork)
|
/**
|
||||||
*/
|
* @see org.alfresco.module.org_alfresco_module_rm.security.FilePlanAuthenticationService#runAsRMAdmin(org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork)
|
||||||
@Override
|
*/
|
||||||
@Deprecated
|
@Override
|
||||||
public <R> R runAsRmAdmin(RunAsWork<R> runAsWork)
|
@Deprecated
|
||||||
{
|
public <R> R runAsRmAdmin(RunAsWork<R> runAsWork)
|
||||||
return AuthenticationUtil.runAs(runAsWork, AuthenticationUtil.getAdminUserName());
|
{
|
||||||
}
|
return AuthenticationUtil.runAs(runAsWork, AuthenticationUtil.getAdminUserName());
|
||||||
}
|
}
|
||||||
|
}
|
@@ -143,7 +143,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
|||||||
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
|
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected synchronized void executeImpl(Action action, final NodeRef actionedUponNodeRef)
|
protected synchronized void executeImpl(final Action action, final NodeRef actionedUponNodeRef)
|
||||||
{
|
{
|
||||||
String actionName = action.getActionDefinitionName();
|
String actionName = action.getActionDefinitionName();
|
||||||
if (isOkToProceedWithAction(actionedUponNodeRef, actionName))
|
if (isOkToProceedWithAction(actionedUponNodeRef, actionName))
|
||||||
@@ -165,8 +165,25 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
|||||||
NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER);
|
NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER);
|
||||||
if (recordFolder == null)
|
if (recordFolder == null)
|
||||||
{
|
{
|
||||||
final boolean finaltargetIsUnfiledRecords = targetIsUnfiledRecords;
|
final boolean finaltargetIsUnfiledRecords = targetIsUnfiledRecords;
|
||||||
recordFolder = createOrResolvePath(action, actionedUponNodeRef, finaltargetIsUnfiledRecords);
|
recordFolder = retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<NodeRef>()
|
||||||
|
{
|
||||||
|
public NodeRef execute() throws Throwable
|
||||||
|
{
|
||||||
|
NodeRef result = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// get the reference to the record folder based on the relative path
|
||||||
|
result = createOrResolvePath(action, actionedUponNodeRef, finaltargetIsUnfiledRecords);
|
||||||
|
}
|
||||||
|
catch (DuplicateChildNodeNameException ex)
|
||||||
|
{
|
||||||
|
throw new ConcurrencyFailureException("Cannot create or resolve path.", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now we have the reference to the target folder we can do some final checks to see if the action is valid
|
// now we have the reference to the target folder we can do some final checks to see if the action is valid
|
||||||
@@ -180,29 +197,30 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(getMode() == CopyMoveLinkFileToActionMode.MOVE)
|
synchronized (this)
|
||||||
{
|
{
|
||||||
fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null);
|
if (getMode() == CopyMoveLinkFileToActionMode.MOVE)
|
||||||
}
|
{
|
||||||
else if(getMode() == CopyMoveLinkFileToActionMode.COPY)
|
fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null);
|
||||||
{
|
}
|
||||||
fileFolderService.copy(actionedUponNodeRef, finalRecordFolder, null);
|
else if (getMode() == CopyMoveLinkFileToActionMode.COPY)
|
||||||
}
|
{
|
||||||
else if(getMode() == CopyMoveLinkFileToActionMode.LINK)
|
fileFolderService.copy(actionedUponNodeRef, finalRecordFolder, null);
|
||||||
{
|
}
|
||||||
getRecordService().link(actionedUponNodeRef, finalRecordFolder);
|
else if (getMode() == CopyMoveLinkFileToActionMode.LINK)
|
||||||
|
{
|
||||||
|
getRecordService().link(actionedUponNodeRef, finalRecordFolder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException fileNotFound)
|
catch (FileNotFoundException fileNotFound)
|
||||||
{
|
{
|
||||||
throw new AlfrescoRuntimeException(
|
throw new AlfrescoRuntimeException("Unable to execute file to action, because the " + (mode == CopyMoveLinkFileToActionMode.MOVE ? "move" : "copy") + " operation failed.", fileNotFound);
|
||||||
"Unable to execute file to action, because the " + (mode == CopyMoveLinkFileToActionMode.MOVE ? "move" : "copy") + " operation failed.",
|
|
||||||
fileNotFound
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -389,7 +407,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
|||||||
*/
|
*/
|
||||||
private NodeRef getChild(NodeRef parent, String childName)
|
private NodeRef getChild(NodeRef parent, String childName)
|
||||||
{
|
{
|
||||||
return getNodeService().getChildByName(parent, ContentModel.ASSOC_CONTAINS, childName);
|
return getNodeService().getChildByName(parent, ContentModel.ASSOC_CONTAINS, childName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -42,8 +42,6 @@ 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.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.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.module.org_alfresco_module_rm.util.ServiceBaseImpl;
|
||||||
import org.alfresco.repo.cache.SimpleCache;
|
import org.alfresco.repo.cache.SimpleCache;
|
||||||
import org.alfresco.repo.domain.node.NodeDAO;
|
import org.alfresco.repo.domain.node.NodeDAO;
|
||||||
@@ -360,8 +358,6 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
|
|||||||
// set inheritance to false
|
// set inheritance to false
|
||||||
getPermissionService().setInheritParentPermissions(container, false);
|
getPermissionService().setInheritParentPermissions(container, false);
|
||||||
getPermissionService().setPermission(container, allRoles, RMPermissionModel.READ_RECORDS, true);
|
getPermissionService().setPermission(container, allRoles, RMPermissionModel.READ_RECORDS, true);
|
||||||
getPermissionService().setPermission(container, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
getPermissionService().setPermission(container, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true);
|
|
||||||
|
|
||||||
// prevent inheritance of rules
|
// prevent inheritance of rules
|
||||||
nodeService.addAspect(container, RuleModel.ASPECT_IGNORE_INHERITED_RULES, null);
|
nodeService.addAspect(container, RuleModel.ASPECT_IGNORE_INHERITED_RULES, null);
|
||||||
|
@@ -251,9 +251,10 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel
|
|||||||
QName PROP_LOADED_DATA_SET_IDS = QName.createQName(RM_URI, "loadedDataSetIds");
|
QName PROP_LOADED_DATA_SET_IDS = QName.createQName(RM_URI, "loadedDataSetIds");
|
||||||
|
|
||||||
// Extended security aspect
|
// Extended security aspect
|
||||||
QName ASPECT_EXTENDED_SECURITY = QName.createQName(RM_URI, "extendedSecurity");
|
// @deprecated as of 2.5, because of performance issues
|
||||||
QName PROP_READERS = QName.createQName(RM_URI, "readers");
|
@Deprecated QName ASPECT_EXTENDED_SECURITY = QName.createQName(RM_URI, "extendedSecurity");
|
||||||
QName PROP_WRITERS = QName.createQName(RM_URI, "writers");
|
@Deprecated QName PROP_READERS = QName.createQName(RM_URI, "readers");
|
||||||
|
@Deprecated QName PROP_WRITERS = QName.createQName(RM_URI, "writers");
|
||||||
|
|
||||||
// Originating details of a record
|
// Originating details of a record
|
||||||
QName ASPECT_RECORD_ORIGINATING_DETAILS = QName.createQName(RM_URI, "recordOriginatingDetails");
|
QName ASPECT_RECORD_ORIGINATING_DETAILS = QName.createQName(RM_URI, "recordOriginatingDetails");
|
||||||
|
@@ -39,6 +39,7 @@ import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
|
|||||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
|
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
|
||||||
import org.alfresco.repo.copy.CopyBehaviourCallback;
|
import org.alfresco.repo.copy.CopyBehaviourCallback;
|
||||||
import org.alfresco.repo.copy.CopyDetails;
|
import org.alfresco.repo.copy.CopyDetails;
|
||||||
|
import org.alfresco.repo.copy.CopyServicePolicies;
|
||||||
import org.alfresco.repo.copy.DefaultCopyBehaviourCallback;
|
import org.alfresco.repo.copy.DefaultCopyBehaviourCallback;
|
||||||
import org.alfresco.repo.node.NodeServicePolicies;
|
import org.alfresco.repo.node.NodeServicePolicies;
|
||||||
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
|
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
|
||||||
@@ -65,7 +66,8 @@ public class RecordAspect extends AbstractDisposableItem
|
|||||||
implements NodeServicePolicies.OnCreateChildAssociationPolicy,
|
implements NodeServicePolicies.OnCreateChildAssociationPolicy,
|
||||||
RecordsManagementPolicies.OnCreateReference,
|
RecordsManagementPolicies.OnCreateReference,
|
||||||
RecordsManagementPolicies.OnRemoveReference,
|
RecordsManagementPolicies.OnRemoveReference,
|
||||||
NodeServicePolicies.OnMoveNodePolicy
|
NodeServicePolicies.OnMoveNodePolicy,
|
||||||
|
CopyServicePolicies.OnCopyCompletePolicy
|
||||||
{
|
{
|
||||||
/** Well-known location of the scripts folder. */
|
/** Well-known location of the scripts folder. */
|
||||||
// TODO make configurable
|
// TODO make configurable
|
||||||
@@ -132,11 +134,11 @@ public class RecordAspect extends AbstractDisposableItem
|
|||||||
|
|
||||||
// manage any extended readers
|
// manage any extended readers
|
||||||
NodeRef parent = childAssocRef.getParentRef();
|
NodeRef parent = childAssocRef.getParentRef();
|
||||||
Set<String> readers = extendedSecurityService.getExtendedReaders(parent);
|
Set<String> readers = extendedSecurityService.getReaders(parent);
|
||||||
Set<String> writers = extendedSecurityService.getExtendedWriters(parent);
|
Set<String> writers = extendedSecurityService.getWriters(parent);
|
||||||
if (readers != null && readers.size() != 0)
|
if (readers != null && readers.size() != 0)
|
||||||
{
|
{
|
||||||
extendedSecurityService.addExtendedSecurity(thumbnail, readers, writers, false);
|
extendedSecurityService.set(thumbnail, readers, writers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,4 +307,33 @@ public class RecordAspect extends AbstractDisposableItem
|
|||||||
scriptService.executeScript(scriptNodeRef, null, objectModel);
|
scriptService.executeScript(scriptNodeRef, null, objectModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On copy complete behaviour for record aspect.
|
||||||
|
*
|
||||||
|
* @param classRef
|
||||||
|
* @param sourceNodeRef
|
||||||
|
* @param targetNodeRef
|
||||||
|
* @param copyToNewNode
|
||||||
|
* @param copyMap
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Behaviour
|
||||||
|
(
|
||||||
|
kind = BehaviourKind.CLASS
|
||||||
|
)
|
||||||
|
public void onCopyComplete(QName classRef,
|
||||||
|
NodeRef sourceNodeRef,
|
||||||
|
NodeRef targetNodeRef,
|
||||||
|
boolean copyToNewNode,
|
||||||
|
Map<NodeRef, NodeRef> copyMap)
|
||||||
|
{
|
||||||
|
// given the node exists and is a record
|
||||||
|
if (nodeService.exists(targetNodeRef) &&
|
||||||
|
nodeService.hasAspect(targetNodeRef, ASPECT_RECORD))
|
||||||
|
{
|
||||||
|
// then remove any extended security from the newly copied record
|
||||||
|
extendedSecurityService.remove(targetNodeRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,13 +34,10 @@ import java.util.Set;
|
|||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
|
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
|
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
|
||||||
import org.alfresco.module.org_alfresco_module_rm.dod5015.DOD5015Model;
|
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.fileplan.FilePlanService;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
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.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.security.FilePlanPermissionService;
|
import org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionService;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
@@ -164,10 +161,6 @@ public class RMv21InPlacePatch extends RMv21PatchComponent
|
|||||||
ruleService.disableRules();
|
ruleService.disableRules();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// set permissions
|
|
||||||
filePlanPermissionService.setPermission(filePlan, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS);
|
|
||||||
filePlanPermissionService.setPermission(filePlan, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING);
|
|
||||||
|
|
||||||
// create fileplan containers
|
// create fileplan containers
|
||||||
filePlanService.createHoldContainer(filePlan);
|
filePlanService.createHoldContainer(filePlan);
|
||||||
filePlanService.createTransferContainer(filePlan);
|
filePlanService.createTransferContainer(filePlan);
|
||||||
|
@@ -30,7 +30,6 @@ package org.alfresco.module.org_alfresco_module_rm.record;
|
|||||||
import static org.alfresco.model.ContentModel.ASPECT_PENDING_DELETE;
|
import static org.alfresco.model.ContentModel.ASPECT_PENDING_DELETE;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||||
@@ -104,22 +103,26 @@ public class InplaceRecordServiceImpl extends ServiceBaseImpl implements Inplace
|
|||||||
{
|
{
|
||||||
// remove the child association
|
// remove the child association
|
||||||
NodeRef originatingLocation = (NodeRef) nodeService.getProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION);
|
NodeRef originatingLocation = (NodeRef) nodeService.getProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION);
|
||||||
List<ChildAssociationRef> parentAssocs = nodeService.getParentAssocs(nodeRef);
|
|
||||||
for (ChildAssociationRef childAssociationRef : parentAssocs)
|
if (originatingLocation != null)
|
||||||
{
|
{
|
||||||
if (!childAssociationRef.isPrimary() &&
|
List<ChildAssociationRef> parentAssocs = nodeService.getParentAssocs(nodeRef);
|
||||||
childAssociationRef.getParentRef().equals(originatingLocation) &&
|
for (ChildAssociationRef childAssociationRef : parentAssocs)
|
||||||
!nodeService.hasAspect(childAssociationRef.getChildRef(), ASPECT_PENDING_DELETE))
|
|
||||||
{
|
{
|
||||||
nodeService.removeChildAssociation(childAssociationRef);
|
if (!childAssociationRef.isPrimary() &&
|
||||||
break;
|
childAssociationRef.getParentRef().equals(originatingLocation) &&
|
||||||
|
!nodeService.hasAspect(childAssociationRef.getChildRef(), ASPECT_PENDING_DELETE))
|
||||||
|
{
|
||||||
|
nodeService.removeChildAssociation(childAssociationRef);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove the extended security from the node
|
||||||
|
// this prevents the users from continuing to see the record in searchs and other linked locations
|
||||||
|
extendedSecurityService.remove(nodeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the extended security from the node
|
|
||||||
// this prevents the users from continuing to see the record in searchs and other linked locations
|
|
||||||
extendedSecurityService.removeAllExtendedSecurity(nodeRef);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -173,18 +176,11 @@ public class InplaceRecordServiceImpl extends ServiceBaseImpl implements Inplace
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Get the extended readers/writers
|
|
||||||
Set<String> extendedReaders = extendedSecurityService.getExtendedReaders(nodeRef);
|
|
||||||
Set<String> extendedWriters = extendedSecurityService.getExtendedWriters(nodeRef);
|
|
||||||
|
|
||||||
// Move the record
|
// Move the record
|
||||||
fileFolderService.moveFrom(nodeRef, source, targetNodeRef, null);
|
fileFolderService.moveFrom(nodeRef, source, targetNodeRef, null);
|
||||||
|
|
||||||
// Update the originating location property
|
// Update the originating location property
|
||||||
nodeService.setProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION, targetNodeRef);
|
nodeService.setProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION, targetNodeRef);
|
||||||
|
|
||||||
// Set the extended readers/writers
|
|
||||||
extendedSecurityService.addExtendedSecurity(nodeRef, extendedReaders, extendedWriters);
|
|
||||||
}
|
}
|
||||||
catch (FileExistsException | FileNotFoundException ex)
|
catch (FileExistsException | FileNotFoundException ex)
|
||||||
{
|
{
|
||||||
|
@@ -107,6 +107,7 @@ import org.alfresco.service.namespace.NamespaceService;
|
|||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
import org.alfresco.util.EqualsHelper;
|
import org.alfresco.util.EqualsHelper;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
import org.alfresco.util.ParameterCheck;
|
import org.alfresco.util.ParameterCheck;
|
||||||
import org.alfresco.util.PropertyMap;
|
import org.alfresco.util.PropertyMap;
|
||||||
import org.apache.commons.lang.ArrayUtils;
|
import org.apache.commons.lang.ArrayUtils;
|
||||||
@@ -253,10 +254,6 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
|||||||
this,
|
this,
|
||||||
"onCreateChildAssociation",
|
"onCreateChildAssociation",
|
||||||
NotificationFrequency.FIRST_EVENT);
|
NotificationFrequency.FIRST_EVENT);
|
||||||
private JavaBehaviour onDeleteDeclaredRecordLink = new JavaBehaviour(
|
|
||||||
this,
|
|
||||||
"onDeleteDeclaredRecordLink",
|
|
||||||
NotificationFrequency.FIRST_EVENT);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param identifierService identifier service
|
* @param identifierService identifier service
|
||||||
@@ -417,11 +414,6 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
|||||||
TYPE_RECORD_FOLDER,
|
TYPE_RECORD_FOLDER,
|
||||||
ContentModel.ASSOC_CONTAINS,
|
ContentModel.ASSOC_CONTAINS,
|
||||||
onCreateChildAssociation);
|
onCreateChildAssociation);
|
||||||
policyComponent.bindAssociationBehaviour(
|
|
||||||
NodeServicePolicies.BeforeDeleteChildAssociationPolicy.QNAME,
|
|
||||||
ContentModel.TYPE_FOLDER,
|
|
||||||
ContentModel.ASSOC_CONTAINS,
|
|
||||||
onDeleteDeclaredRecordLink);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -592,27 +584,6 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
|||||||
}, AuthenticationUtil.getSystemUserName());
|
}, AuthenticationUtil.getSystemUserName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Looking specifically at linked content that was declared a record from a non-rm site.
|
|
||||||
* When the site or the folder that the link was declared in is deleted we need to remove
|
|
||||||
* the extended security property accounts in the tree
|
|
||||||
*
|
|
||||||
* @param childAssocRef
|
|
||||||
*/
|
|
||||||
public void onDeleteDeclaredRecordLink(ChildAssociationRef childAssocRef)
|
|
||||||
{
|
|
||||||
// Is the deleted child association not a primary association?
|
|
||||||
// Does the deleted child association have the rma:recordOriginatingDetails aspect?
|
|
||||||
// Is the parent of the deleted child association a folder (cm:folder)?
|
|
||||||
if (!childAssocRef.isPrimary() &&
|
|
||||||
nodeService.hasAspect(childAssocRef.getChildRef(), ASPECT_RECORD_ORIGINATING_DETAILS) &&
|
|
||||||
nodeService.getType(childAssocRef.getParentRef()).equals(ContentModel.TYPE_FOLDER))
|
|
||||||
{
|
|
||||||
// ..then remove the extended readers and writers up the tree for this remaining node
|
|
||||||
extendedSecurityService.removeExtendedSecurity(childAssocRef.getChildRef(), extendedSecurityService.getExtendedReaders(childAssocRef.getChildRef()), extendedSecurityService.getExtendedWriters(childAssocRef.getChildRef()), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#disablePropertyEditableCheck()
|
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#disablePropertyEditableCheck()
|
||||||
*/
|
*/
|
||||||
@@ -914,12 +885,10 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
|||||||
throw new AlfrescoRuntimeException("Unable to create record, because new record container could not be found.");
|
throw new AlfrescoRuntimeException("Unable to create record, because new record container could not be found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the documents readers
|
// get the documents readers and writers
|
||||||
Long aclId = nodeService.getNodeAclId(nodeRef);
|
Pair<Set<String>, Set<String>> readersAndWriters = extendedPermissionService.getReadersAndWriters(nodeRef);
|
||||||
Set<String> readers = extendedPermissionService.getReaders(aclId);
|
|
||||||
Set<String> writers = extendedPermissionService.getWriters(aclId);
|
|
||||||
|
|
||||||
// add the current owner to the list of extended writers
|
// get the current owner
|
||||||
String owner = ownableService.getOwner(nodeRef);
|
String owner = ownableService.getOwner(nodeRef);
|
||||||
|
|
||||||
// get the documents primary parent assoc
|
// get the documents primary parent assoc
|
||||||
@@ -971,13 +940,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
|||||||
nodeService.addChild(parentAssoc.getParentRef(), nodeRef, parentAssoc.getTypeQName(), parentAssoc.getQName());
|
nodeService.addChild(parentAssoc.getParentRef(), nodeRef, parentAssoc.getTypeQName(), parentAssoc.getQName());
|
||||||
|
|
||||||
// set the extended security
|
// set the extended security
|
||||||
Set<String> combinedWriters = new HashSet<String>(writers);
|
extendedSecurityService.set(nodeRef, readersAndWriters);
|
||||||
if (owner != null && !owner.isEmpty() && !owner.equals(OwnableService.NO_OWNER))
|
|
||||||
{
|
|
||||||
combinedWriters.add(owner);
|
|
||||||
}
|
|
||||||
combinedWriters.add(AuthenticationUtil.getFullyAuthenticatedUser());
|
|
||||||
extendedSecurityService.addExtendedSecurity(nodeRef, readers, combinedWriters);
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -1009,24 +972,8 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
|||||||
// get the unfiled record folder
|
// get the unfiled record folder
|
||||||
final NodeRef unfiledRecordFolder = filePlanService.getUnfiledContainer(filePlan);
|
final NodeRef unfiledRecordFolder = filePlanService.getUnfiledContainer(filePlan);
|
||||||
|
|
||||||
// get the documents readers
|
// get the documents readers and writers
|
||||||
Long aclId = nodeService.getNodeAclId(nodeRef);
|
Pair<Set<String>, Set<String>> readersAndWriters = extendedPermissionService.getReadersAndWriters(nodeRef);
|
||||||
Set<String> readers = extendedPermissionService.getReaders(aclId);
|
|
||||||
Set<String> writers = extendedPermissionService.getWriters(aclId);
|
|
||||||
|
|
||||||
// add the current owner to the list of extended writers
|
|
||||||
Set<String> modifiedWrtiers = new HashSet<String>(writers);
|
|
||||||
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_OWNABLE))
|
|
||||||
{
|
|
||||||
String owner = ownableService.getOwner(nodeRef);
|
|
||||||
if (owner != null && !owner.isEmpty() && !owner.equals(OwnableService.NO_OWNER))
|
|
||||||
{
|
|
||||||
modifiedWrtiers.add(owner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the current user as extended writer
|
|
||||||
modifiedWrtiers.add(authenticationUtil.getFullyAuthenticatedUser());
|
|
||||||
|
|
||||||
// copy version state and create record
|
// copy version state and create record
|
||||||
NodeRef record = null;
|
NodeRef record = null;
|
||||||
@@ -1095,7 +1042,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set extended security on record
|
// set extended security on record
|
||||||
extendedSecurityService.addExtendedSecurity(record, readers, writers);
|
extendedSecurityService.set(record, readersAndWriters);
|
||||||
|
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
@@ -45,8 +45,6 @@ import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
|
|||||||
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.fileplan.FilePlanService;
|
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.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.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.security.authority.RMAuthority;
|
import org.alfresco.repo.security.authority.RMAuthority;
|
||||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||||
@@ -195,8 +193,6 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService,
|
|||||||
// Set the permissions
|
// Set the permissions
|
||||||
permissionService.setInheritParentPermissions(filePlan, false);
|
permissionService.setInheritParentPermissions(filePlan, false);
|
||||||
permissionService.setPermission(filePlan, allRoles, RMPermissionModel.READ_RECORDS, true);
|
permissionService.setPermission(filePlan, allRoles, RMPermissionModel.READ_RECORDS, true);
|
||||||
permissionService.setPermission(filePlan, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
permissionService.setPermission(filePlan, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true);
|
|
||||||
|
|
||||||
// Create the transfer and hold containers
|
// Create the transfer and hold containers
|
||||||
systemContainers.add(filePlanService.createHoldContainer(filePlan));
|
systemContainers.add(filePlanService.createHoldContainer(filePlan));
|
||||||
|
@@ -29,98 +29,77 @@ package org.alfresco.module.org_alfresco_module_rm.security;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.api.AlfrescoPublicApi;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extended security service.
|
* Extended security service.
|
||||||
*
|
*
|
||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
* @since 2.1
|
* @since 2.1
|
||||||
*/
|
*/
|
||||||
public interface ExtendedSecurityService
|
@AlfrescoPublicApi
|
||||||
|
public interface ExtendedSecurityService extends DeprecatedExtendedSecurityService
|
||||||
{
|
{
|
||||||
|
/** IPR group prefix */
|
||||||
|
static final String IPR_GROUP_PREFIX = "IPR";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether a node has extended security.
|
* Indicates whether a node has extended security.
|
||||||
*
|
*
|
||||||
* @param nodeRef node reference
|
* @param nodeRef node reference
|
||||||
* @return boolean true if the node has extedned security, false otherwise
|
* @return boolean true if the node has extended security, false otherwise
|
||||||
*/
|
*/
|
||||||
boolean hasExtendedSecurity(NodeRef nodeRef);
|
boolean hasExtendedSecurity(NodeRef nodeRef);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the set of authorities that are extended readers for the given node.
|
* Gets the set of authorities that are extended readers for the given node.
|
||||||
*
|
*
|
||||||
* @param nodeRef node reference
|
* @param nodeRef node reference
|
||||||
* @return {@link Set}<{@link String}> set of extended readers
|
* @return {@link Set}<{@link String}> set of extended readers
|
||||||
*/
|
*/
|
||||||
Set<String> getExtendedReaders(NodeRef nodeRef);
|
Set<String> getReaders(NodeRef nodeRef);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the set of authorities that are extended writers for the given node.
|
* Get the set of authorities that are extended writers for the given node.
|
||||||
*
|
*
|
||||||
* @param nodeRef node reference
|
* @param nodeRef node reference
|
||||||
* @return {@link Set}<{@link String}> set of extended writers
|
* @return {@link Set}<{@link String}> set of extended writers
|
||||||
*/
|
*/
|
||||||
Set<String> getExtendedWriters(NodeRef nodeRef);
|
Set<String> getWriters(NodeRef nodeRef);
|
||||||
|
|
||||||
/**
|
|
||||||
* Add extended security for the specified authorities to a node.
|
|
||||||
*
|
|
||||||
* @param nodeRef node reference
|
|
||||||
* @param readers set of authorities to add extended read permissions
|
|
||||||
* @param writers set of authorities to add extended write permissions
|
|
||||||
*/
|
|
||||||
void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add extended security for the specified authorities to a node.
|
* Helper to allow caller to provide authority sets as a pair where the
|
||||||
|
* first is the readers and the second is the writers.
|
||||||
|
*
|
||||||
|
* @see #set(NodeRef, Set, Set)
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @param readersAndWriters pair where first is the set of readers and the
|
||||||
|
* second is the set of writers
|
||||||
|
*/
|
||||||
|
void set(NodeRef nodeRef, Pair<Set<String>, Set<String>> readersAndWriters);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set extended security for a node, where the readers will be granted ReadRecord
|
||||||
|
* permission and ViewRecord capability to the node and where the writers will be
|
||||||
|
* granted Filling permission and Filling capability to the node.
|
||||||
* <p>
|
* <p>
|
||||||
* If specified, the read and write extended permissions are applied to all parents up to the file plan as
|
* Note it is vaild to provide 'null' values for readers and/or writers.
|
||||||
* extended read. This ensures parental read, but not parental write.
|
|
||||||
*
|
*
|
||||||
* @param nodeRef node reference
|
* @param nodeRef node reference
|
||||||
* @param readers set of authorities to add extended read permissions
|
* @param readers set of readers
|
||||||
* @param writers set of authorities to add extended write permissions
|
* @param writers set of writers
|
||||||
* @param applyToParents true if extended security applied to parents (read only) false otherwise.
|
|
||||||
*/
|
|
||||||
void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the extended security for the specified authorities from a node.
|
|
||||||
*
|
*
|
||||||
* @param nodeRef node reference
|
* @since 2.5
|
||||||
* @param readers set of authorities to remove as extended readers
|
|
||||||
* @param writers set of authorities to remove as extended writers
|
|
||||||
*/
|
*/
|
||||||
void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers);
|
void set(NodeRef nodeRef, Set<String> readers, Set<String> writers);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the extended security for the specified authorities from a node.
|
* Removes all extended security from a node.
|
||||||
* <p>
|
|
||||||
* If specified, extended security will also be removed from the parent hierarchy.(read only). Note that
|
|
||||||
* extended security is records as a reference count, so security will only be utterly removed from the parent
|
|
||||||
* hierarchy if all references to the authority are removed.
|
|
||||||
*
|
|
||||||
* @param nodeRef node reference
|
|
||||||
* @param readers set of authorities to remove as extended readers
|
|
||||||
* @param writers set of authorities to remove as extedned writers
|
|
||||||
* @param applyToParents true if removal of extended security is applied to parent hierarchy (read only), false
|
|
||||||
* otherwise
|
|
||||||
*/
|
|
||||||
void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all extended readers and writers from the given node reference.
|
|
||||||
*
|
*
|
||||||
* @param nodeRef node reference
|
* @param nodeRef node reference
|
||||||
*/
|
*/
|
||||||
void removeAllExtendedSecurity(NodeRef nodeRef);
|
void remove(NodeRef nodeRef);
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all extended readers and writers from the given node reference.
|
|
||||||
*
|
|
||||||
* @param nodeRef node reference
|
|
||||||
* @param applyToParents if true then apply removal to parent hierarchy (read only) false otherwise.
|
|
||||||
*/
|
|
||||||
void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents);
|
|
||||||
}
|
}
|
||||||
|
@@ -27,23 +27,37 @@
|
|||||||
|
|
||||||
package org.alfresco.module.org_alfresco_module_rm.security;
|
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.HashMap;
|
import static org.alfresco.service.cmr.security.PermissionService.GROUP_PREFIX;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.model.RenditionModel;
|
import org.alfresco.model.RenditionModel;
|
||||||
|
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.fileplan.FilePlanService;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
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.role.FilePlanRoleService;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
|
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
|
||||||
|
import org.alfresco.query.PagingRequest;
|
||||||
|
import org.alfresco.query.PagingResults;
|
||||||
|
import org.alfresco.repo.security.authority.RMAuthority;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.security.AccessPermission;
|
||||||
|
import org.alfresco.service.cmr.security.AuthorityService;
|
||||||
|
import org.alfresco.service.cmr.security.AuthorityType;
|
||||||
import org.alfresco.service.cmr.security.PermissionService;
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
import org.alfresco.service.namespace.QName;
|
|
||||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
import org.alfresco.util.ParameterCheck;
|
import org.alfresco.util.ParameterCheck;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
|
import org.springframework.extensions.webscripts.ui.common.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extended security service implementation.
|
* Extended security service implementation.
|
||||||
@@ -53,13 +67,31 @@ import org.alfresco.util.ParameterCheck;
|
|||||||
*/
|
*/
|
||||||
public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||||
implements ExtendedSecurityService,
|
implements ExtendedSecurityService,
|
||||||
RecordsManagementModel
|
RecordsManagementModel,
|
||||||
|
ApplicationListener<ContextRefreshedEvent>
|
||||||
{
|
{
|
||||||
|
/** ipr group names */
|
||||||
|
static final String ROOT_IPR_GROUP = "INPLACE_RECORD_MANAGEMENT";
|
||||||
|
static final String READER_GROUP_PREFIX = ExtendedSecurityService.IPR_GROUP_PREFIX + "R";
|
||||||
|
static final String WRITER_GROUP_PREFIX = ExtendedSecurityService.IPR_GROUP_PREFIX + "W";
|
||||||
|
|
||||||
|
/** max page size for authority query */
|
||||||
|
private static final int MAX_ITEMS = 50;
|
||||||
|
|
||||||
/** File plan service */
|
/** File plan service */
|
||||||
private FilePlanService filePlanService;
|
private FilePlanService filePlanService;
|
||||||
|
|
||||||
/** File plan role service */
|
/** File plan role service */
|
||||||
private FilePlanRoleService filePlanRoleService;
|
private FilePlanRoleService filePlanRoleService;
|
||||||
|
|
||||||
|
/** authority service */
|
||||||
|
private AuthorityService authorityService;
|
||||||
|
|
||||||
|
/** permission service */
|
||||||
|
private PermissionService permissionService;
|
||||||
|
|
||||||
|
/** transaction service */
|
||||||
|
private TransactionService transactionService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param filePlanService file plan service
|
* @param filePlanService file plan service
|
||||||
@@ -76,118 +108,152 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
{
|
{
|
||||||
this.filePlanRoleService = filePlanRoleService;
|
this.filePlanRoleService = filePlanRoleService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param authorityService authority service
|
||||||
|
*/
|
||||||
|
public void setAuthorityService(AuthorityService authorityService)
|
||||||
|
{
|
||||||
|
this.authorityService = authorityService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param permissionService permission service
|
||||||
|
*/
|
||||||
|
public void setPermissionService(PermissionService permissionService)
|
||||||
|
{
|
||||||
|
this.permissionService = permissionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param transactionService transaction service
|
||||||
|
*/
|
||||||
|
public void setTransactionService(TransactionService transactionService)
|
||||||
|
{
|
||||||
|
this.transactionService = transactionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application context refresh event handler
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent)
|
||||||
|
{
|
||||||
|
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
// if the root group doesn't exist then create it
|
||||||
|
if (!authorityService.authorityExists(getRootIRPGroup()))
|
||||||
|
{
|
||||||
|
authorityService.createAuthority(AuthorityType.GROUP, ROOT_IPR_GROUP, ROOT_IPR_GROUP, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get root IPR group name
|
||||||
|
*/
|
||||||
|
private String getRootIRPGroup()
|
||||||
|
{
|
||||||
|
return GROUP_PREFIX + ROOT_IPR_GROUP;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#hasExtendedSecurity(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 hasExtendedSecurity(NodeRef nodeRef)
|
public boolean hasExtendedSecurity(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
return nodeService.hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY);
|
return (getIPRGroups(nodeRef) != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#getExtendedReaders(org.alfresco.service.cmr.repository.NodeRef)
|
* @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#getReaders(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getExtendedReaders(NodeRef nodeRef)
|
public Set<String> getReaders(NodeRef nodeRef)
|
||||||
{
|
|
||||||
Set<String> result = null;
|
|
||||||
|
|
||||||
Map<String, Integer> readerMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
|
|
||||||
if (readerMap != null)
|
|
||||||
{
|
|
||||||
result = readerMap.keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#getExtendedWriters(org.alfresco.service.cmr.repository.NodeRef)
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
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)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
|
|
||||||
{
|
{
|
||||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||||
ParameterCheck.mandatory("applyToParents", applyToParents);
|
|
||||||
|
Set<String> result = Collections.EMPTY_SET;
|
||||||
if (nodeRef != null)
|
Pair<String, String> iprGroups = getIPRGroups(nodeRef);
|
||||||
|
if (iprGroups != null)
|
||||||
{
|
{
|
||||||
addExtendedSecurityImpl(nodeRef, readers, writers, applyToParents);
|
result = getAuthorities(iprGroups.getFirst());
|
||||||
|
|
||||||
// add to the extended security roles
|
|
||||||
addExtendedSecurityRoles(nodeRef, readers, writers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add extended security implementation method
|
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#getWriters(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
*
|
|
||||||
* @param nodeRef
|
|
||||||
* @param readers
|
|
||||||
* @param writers
|
|
||||||
* @param applyToParents
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void addExtendedSecurityImpl(final NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
|
@Override
|
||||||
|
public Set<String> getWriters(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||||
ParameterCheck.mandatory("applyToParents", applyToParents);
|
|
||||||
|
Set<String> result = Collections.EMPTY_SET;
|
||||||
// get the properties
|
Pair<String, String> iprGroups = getIPRGroups(nodeRef);
|
||||||
final Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
|
if (iprGroups != null)
|
||||||
|
|
||||||
// update the readers map
|
|
||||||
if (readers != null && readers.size() != 0)
|
|
||||||
{
|
{
|
||||||
// get reader map
|
result = getAuthorities(iprGroups.getSecond());
|
||||||
Map<String, Integer> readersMap = (Map<String, Integer>)properties.get(PROP_READERS);
|
|
||||||
|
|
||||||
// set the readers property (this will in turn apply the aspect if required)
|
|
||||||
properties.put(PROP_READERS, (Serializable)addToMap(readersMap, readers));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the writers map
|
return result;
|
||||||
if (writers != null && writers.size() != 0)
|
}
|
||||||
{
|
|
||||||
// get writer map
|
/**
|
||||||
Map<String, Integer> writersMap = (Map<String, Integer>)properties.get(PROP_WRITERS);
|
* Helper to get authorities for a given group
|
||||||
|
*
|
||||||
// set the writers property (this will in turn apply the aspect if required)
|
* @param group group name
|
||||||
properties.put(PROP_WRITERS, (Serializable)addToMap(writersMap, writers));
|
* @return Set<String> immediate authorities
|
||||||
}
|
*/
|
||||||
|
private Set<String> getAuthorities(String group)
|
||||||
// set properties
|
{
|
||||||
nodeService.setProperties(nodeRef, properties);
|
Set<String> result = new HashSet<String>();
|
||||||
|
result.addAll(authorityService.getContainedAuthorities(null, group, true));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#set(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.util.Pair)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void set(NodeRef nodeRef, Pair<Set<String>, Set<String>> readersAndWriters)
|
||||||
|
{
|
||||||
|
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||||
|
set(nodeRef, readersAndWriters.getFirst(), readersAndWriters.getSecond());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#set(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void set(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
||||||
|
{
|
||||||
|
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||||
|
|
||||||
|
// remove existing extended security, assuming there is any
|
||||||
|
remove(nodeRef);
|
||||||
|
|
||||||
|
// find groups
|
||||||
|
Pair<String, String> iprGroups = createOrFindIPRGroups(readers, writers);
|
||||||
|
|
||||||
|
// assign groups to correct fileplan roles
|
||||||
|
NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
|
||||||
|
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, iprGroups.getFirst());
|
||||||
|
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, iprGroups.getSecond());
|
||||||
|
|
||||||
|
// assign groups to node
|
||||||
|
assignIPRGroupsToNode(iprGroups, nodeRef);
|
||||||
|
|
||||||
// apply the readers to any renditions of the content
|
// apply the readers to any renditions of the content
|
||||||
if (isRecord(nodeRef))
|
if (isRecord(nodeRef))
|
||||||
{
|
{
|
||||||
@@ -195,101 +261,300 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
for (ChildAssociationRef assoc : assocs)
|
for (ChildAssociationRef assoc : assocs)
|
||||||
{
|
{
|
||||||
NodeRef child = assoc.getChildRef();
|
NodeRef child = assoc.getChildRef();
|
||||||
addExtendedSecurityImpl(child, readers, writers, false);
|
assignIPRGroupsToNode(iprGroups, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Get the IPR groups associated with a given node reference.
|
||||||
* @param nodeRef
|
* <p>
|
||||||
* @param readers
|
* Return null if none found.
|
||||||
* @param writers
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @return Pair<String, String> where first is the read group and second if the write group, null if none found
|
||||||
*/
|
*/
|
||||||
private void addExtendedSecurityRoles(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
private Pair<String, String> getIPRGroups(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
|
Pair<String, String> result = null;
|
||||||
|
String iprReaderGroup = null;
|
||||||
addExtendedSecurityRolesImpl(filePlan, readers, FilePlanRoleService.ROLE_EXTENDED_READERS);
|
String iprWriterGroup = null;
|
||||||
addExtendedSecurityRolesImpl(filePlan, writers, FilePlanRoleService.ROLE_EXTENDED_WRITERS);
|
|
||||||
}
|
// get all the set permissions
|
||||||
|
Set<AccessPermission> permissions = permissionService.getAllSetPermissions(nodeRef);
|
||||||
/**
|
for (AccessPermission permission : permissions)
|
||||||
* Add extended security roles implementation
|
|
||||||
*
|
|
||||||
* @param filePlan file plan
|
|
||||||
* @param authorities authorities
|
|
||||||
* @param roleName role name
|
|
||||||
*/
|
|
||||||
private void addExtendedSecurityRolesImpl(NodeRef filePlan, Set<String> authorities, String roleName)
|
|
||||||
{
|
|
||||||
if (authorities != null)
|
|
||||||
{
|
{
|
||||||
for (String authority : authorities)
|
// look for the presence of the reader group
|
||||||
|
if (permission.getAuthority().startsWith(GROUP_PREFIX + READER_GROUP_PREFIX))
|
||||||
{
|
{
|
||||||
if ((!authority.equals(PermissionService.ALL_AUTHORITIES) && !authority.equals(PermissionService.OWNER_AUTHORITY)))
|
iprReaderGroup = permission.getAuthority();
|
||||||
{
|
}
|
||||||
// add the authority to the role
|
// look for the presence of the writer group
|
||||||
filePlanRoleService.assignRoleToAuthority(filePlan, roleName, authority);
|
else if (permission.getAuthority().startsWith(GROUP_PREFIX + WRITER_GROUP_PREFIX))
|
||||||
}
|
{
|
||||||
|
iprWriterGroup = permission.getAuthority();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assuming the are both present then return
|
||||||
|
if (iprReaderGroup != null && iprWriterGroup != null)
|
||||||
|
{
|
||||||
|
result = new Pair<String, String>(iprReaderGroup, iprWriterGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Given a set of readers and writers find or create the appropriate IPR groups.
|
||||||
* @param map
|
* <p>
|
||||||
* @param keys
|
* The IPR groups are named with hashes of the authority lists in order to reduce
|
||||||
|
* the set of groups that require exact match. A further index is used to handle
|
||||||
|
* a situation where there is a hash clash, but a difference in the authority lists.
|
||||||
|
* <p>
|
||||||
|
* When no match is found the groups are created. Once created
|
||||||
|
*
|
||||||
|
* @param filePlan file plan
|
||||||
|
* @param readers authorities with read
|
||||||
|
* @param writers authorities with write
|
||||||
|
* @return Pair<String, String> where first is the full name of the read group and
|
||||||
|
* second is the full name of the write group
|
||||||
|
*/
|
||||||
|
private Pair<String, String> createOrFindIPRGroups(Set<String> readers, Set<String> writers)
|
||||||
|
{
|
||||||
|
return new Pair<String, String>(
|
||||||
|
createOrFindIPRGroup(READER_GROUP_PREFIX, readers),
|
||||||
|
createOrFindIPRGroup(WRITER_GROUP_PREFIX, writers));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create or find an IPR group based on the provided prefix and authorities.
|
||||||
|
*
|
||||||
|
* @param groupPrefix group prefix
|
||||||
|
* @param authorities authorities
|
||||||
|
* @return String full group name
|
||||||
|
*/
|
||||||
|
private String createOrFindIPRGroup(String groupPrefix, Set<String> authorities)
|
||||||
|
{
|
||||||
|
String group = null;
|
||||||
|
|
||||||
|
// find group or determine what the next index is if no group exists or there is a clash
|
||||||
|
Pair<String, Integer> groupResult = findIPRGroup(groupPrefix, authorities);
|
||||||
|
|
||||||
|
if (groupResult.getFirst() == null)
|
||||||
|
{
|
||||||
|
group = createIPRGroup(groupPrefix, authorities, groupResult.getSecond());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
group = groupResult.getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a group name prefix and the authorities, finds the exact match existing group.
|
||||||
|
* <p>
|
||||||
|
* If the group does not exist then the group returned is null and the index shows the next available
|
||||||
|
* group index for creation.
|
||||||
|
*
|
||||||
|
* @param groupPrefix group name prefix
|
||||||
|
* @param authorities authorities
|
||||||
|
* @return Pair<String, Integer> where first is the name of the found group, null if none found and second
|
||||||
|
* if the next available create index
|
||||||
|
*/
|
||||||
|
private Pair<String, Integer> findIPRGroup(String groupPrefix, Set<String> authorities)
|
||||||
|
{
|
||||||
|
String iprGroup = null;
|
||||||
|
int nextGroupIndex = 0;
|
||||||
|
boolean hasMoreItems = true;
|
||||||
|
int pageCount = 0;
|
||||||
|
|
||||||
|
// determine the short name prefix
|
||||||
|
String groupShortNamePrefix = getIPRGroupPrefixShortName(groupPrefix, authorities);
|
||||||
|
|
||||||
|
// iterate over the authorities to find a match
|
||||||
|
while (hasMoreItems == true)
|
||||||
|
{
|
||||||
|
// get matching authorities
|
||||||
|
PagingResults<String> results = authorityService.getAuthorities(AuthorityType.GROUP,
|
||||||
|
RMAuthority.ZONE_APP_RM,
|
||||||
|
groupShortNamePrefix,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
new PagingRequest(MAX_ITEMS*pageCount, MAX_ITEMS));
|
||||||
|
|
||||||
|
// record the total count
|
||||||
|
nextGroupIndex = nextGroupIndex + results.getPage().size();
|
||||||
|
|
||||||
|
// see if any of the matching groups exactly match
|
||||||
|
for (String group : results.getPage())
|
||||||
|
{
|
||||||
|
// if exists and matches we have found our group
|
||||||
|
if (isIPRGroupTrueMatch(group, authorities))
|
||||||
|
{
|
||||||
|
iprGroup = group;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine if there are any more pages to inspect
|
||||||
|
hasMoreItems = results.hasMoreItems();
|
||||||
|
pageCount ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Pair<String, Integer>(iprGroup, nextGroupIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether a group exactly matches a list of authorities.
|
||||||
|
*
|
||||||
|
* @param authorities list of authorities
|
||||||
|
* @param group group
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Map<String, Integer> addToMap(Map<String, Integer> map, Set<String> keys)
|
private boolean isIPRGroupTrueMatch(String group, Set<String> authorities)
|
||||||
|
{
|
||||||
|
Set<String> contained = authorityService.getContainedAuthorities(null, group, true);
|
||||||
|
return contained.equals(authorities);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get IPR group prefix short name.
|
||||||
|
* <p>
|
||||||
|
* 'package' scope to help testing.
|
||||||
|
*
|
||||||
|
* @param prefix prefix
|
||||||
|
* @param authorities authorities
|
||||||
|
* @return String group prefix short name
|
||||||
|
*/
|
||||||
|
/*package*/ String getIPRGroupPrefixShortName(String prefix, Set<String> authorities)
|
||||||
{
|
{
|
||||||
if (map == null)
|
StringBuilder builder = new StringBuilder(128)
|
||||||
|
.append(prefix)
|
||||||
|
.append(getAuthoritySetHashCode(authorities));
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get IPR group short name.
|
||||||
|
* <p>
|
||||||
|
* Note this excludes the "GROUP_" prefix.
|
||||||
|
* <p>
|
||||||
|
* 'package' scope to help testing.
|
||||||
|
*
|
||||||
|
* @param prefix prefix
|
||||||
|
* @param readers read authorities
|
||||||
|
* @param writers write authorities
|
||||||
|
* @param index group index
|
||||||
|
* @return String group short name
|
||||||
|
*/
|
||||||
|
/*package*/ String getIPRGroupShortName(String prefix, Set<String> authorities, int index)
|
||||||
|
{
|
||||||
|
return getIPRGroupShortName(prefix, authorities, Integer.toString(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get IPR group short name.
|
||||||
|
* <p>
|
||||||
|
* Note this excludes the "GROUP_" prefix.
|
||||||
|
*
|
||||||
|
* @param prefix prefix
|
||||||
|
* @param readers read authorities
|
||||||
|
* @param writers write authorities
|
||||||
|
* @param index group index
|
||||||
|
* @return String group short name
|
||||||
|
*/
|
||||||
|
private String getIPRGroupShortName(String prefix, Set<String> authorities, String index)
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder(128)
|
||||||
|
.append(getIPRGroupPrefixShortName(prefix, authorities))
|
||||||
|
.append(index);
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the hashcode value of a set of authorities.
|
||||||
|
*
|
||||||
|
* @param authorities set of authorities
|
||||||
|
* @return int hash code
|
||||||
|
*/
|
||||||
|
private int getAuthoritySetHashCode(Set<String> authorities)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
if (authorities != null && !authorities.isEmpty())
|
||||||
{
|
{
|
||||||
// create map
|
result = StringUtils.join(authorities.toArray(), "").hashCode();
|
||||||
map = new HashMap<String, Integer>(7);
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
for (String key : keys)
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new IPR group.
|
||||||
|
*
|
||||||
|
* @param groupNamePrefix group name prefix
|
||||||
|
* @param children child authorities
|
||||||
|
* @param index group index
|
||||||
|
* @return String full name of created group
|
||||||
|
*/
|
||||||
|
private String createIPRGroup(String groupNamePrefix, Set<String> children, int index)
|
||||||
|
{
|
||||||
|
ParameterCheck.mandatory("groupNamePrefix", groupNamePrefix);
|
||||||
|
|
||||||
|
// get the group name
|
||||||
|
String groupShortName = getIPRGroupShortName(groupNamePrefix, children, index);
|
||||||
|
|
||||||
|
// create group
|
||||||
|
String group = authorityService.createAuthority(AuthorityType.GROUP, groupShortName, groupShortName, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
|
||||||
|
// add root parent
|
||||||
|
authorityService.addAuthority(getRootIRPGroup(), group);
|
||||||
|
|
||||||
|
// add children if provided
|
||||||
|
if (children != null)
|
||||||
{
|
{
|
||||||
if (!key.equals(PermissionService.ALL_AUTHORITIES))
|
for (String child : children)
|
||||||
{
|
{
|
||||||
if (map.containsKey(key))
|
if (authorityService.authorityExists(child) &&
|
||||||
|
!PermissionService.ALL_AUTHORITIES.equals(child))
|
||||||
{
|
{
|
||||||
// increment reference count
|
authorityService.addAuthority(group, child);
|
||||||
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;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
|
* Assign IPR groups to a node reference with the correct permissions.
|
||||||
|
*
|
||||||
|
* @param iprGroups iprGroups, first read and second write
|
||||||
|
* @param nodeRef node reference
|
||||||
|
*/
|
||||||
|
private void assignIPRGroupsToNode(Pair<String, String> iprGroups, NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
permissionService.setPermission(nodeRef, iprGroups.getFirst(), RMPermissionModel.READ_RECORDS, true);
|
||||||
|
permissionService.setPermission(nodeRef, iprGroups.getSecond(), RMPermissionModel.FILING, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#remove(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
public void remove(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
removeExtendedSecurity(nodeRef, readers, writers, true);
|
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||||
}
|
|
||||||
|
Pair<String, String> iprGroups = getIPRGroups(nodeRef);
|
||||||
/**
|
if (iprGroups != null)
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String>writers, boolean applyToParents)
|
|
||||||
{
|
|
||||||
if (hasExtendedSecurity(nodeRef))
|
|
||||||
{
|
{
|
||||||
removeExtendedSecurityImpl(nodeRef, readers, writers);
|
// remove any extended security that might be present
|
||||||
|
clearPermissions(nodeRef, iprGroups);
|
||||||
|
|
||||||
// remove the readers from any renditions of the content
|
// remove the readers from any renditions of the content
|
||||||
if (isRecord(nodeRef))
|
if (isRecord(nodeRef))
|
||||||
{
|
{
|
||||||
@@ -297,110 +562,85 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
for (ChildAssociationRef assoc : assocs)
|
for (ChildAssociationRef assoc : assocs)
|
||||||
{
|
{
|
||||||
NodeRef child = assoc.getChildRef();
|
NodeRef child = assoc.getChildRef();
|
||||||
removeExtendedSecurityImpl(child, readers, writers);
|
clearPermissions(child, iprGroups);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (applyToParents)
|
|
||||||
{
|
|
||||||
// apply the extended readers up the file plan primary hierarchy
|
|
||||||
NodeRef parent = nodeService.getPrimaryParent(nodeRef).getParentRef();
|
|
||||||
if (parent != null &&
|
|
||||||
filePlanService.isFilePlanComponent(parent))
|
|
||||||
{
|
|
||||||
removeExtendedSecurity(parent, readers, null, applyToParents);
|
|
||||||
removeExtendedSecurity(parent, writers, null, applyToParents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a set of readers and writers from a node reference.
|
* Clear the nodes IPR permissions
|
||||||
* <p>
|
*
|
||||||
* Removes the aspect and resets the property to null if all readers and writers are removed.
|
|
||||||
*
|
|
||||||
* @param nodeRef node reference
|
* @param nodeRef node reference
|
||||||
* @param readers {@link Set} of readers
|
|
||||||
* @param writers {@link Set} of writers
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
private void clearPermissions(NodeRef nodeRef, Pair<String, String> iprGroups)
|
||||||
private void removeExtendedSecurityImpl(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
|
||||||
{
|
{
|
||||||
Map<String, Integer> readersMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
|
// remove group permissions from node
|
||||||
nodeService.setProperty(nodeRef, PROP_READERS, (Serializable)removeFromMap(readersMap, readers));
|
permissionService.clearPermission(nodeRef, iprGroups.getFirst());
|
||||||
|
permissionService.clearPermission(nodeRef, iprGroups.getSecond());
|
||||||
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)
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedReaders(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
{
|
*/
|
||||||
// remove the aspect
|
@Override @Deprecated public Set<String> getExtendedReaders(NodeRef nodeRef)
|
||||||
nodeService.removeAspect(nodeRef, ASPECT_EXTENDED_SECURITY);
|
{
|
||||||
}
|
return getReaders(nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedWriters(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
@Override @Deprecated public Set<String> getExtendedWriters(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
return getWriters(nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
|
||||||
|
*/
|
||||||
|
@Override @Deprecated public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
||||||
|
{
|
||||||
|
set(nodeRef, readers, writers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
|
||||||
|
*/
|
||||||
|
@Override @Deprecated public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
|
||||||
|
{
|
||||||
|
set(nodeRef, readers, writers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
@Override @Deprecated public void removeAllExtendedSecurity(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
remove(nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
|
||||||
|
*/
|
||||||
|
@Override @Deprecated public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
||||||
|
{
|
||||||
|
remove(nodeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to remove items from map or reduce reference count
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
|
||||||
*
|
|
||||||
* @param map ref count map
|
|
||||||
* @param keys keys
|
|
||||||
* @return Map<String, Integer> ref count map
|
|
||||||
*/
|
*/
|
||||||
private Map<String, Integer> removeFromMap(Map<String, Integer> map, Set<String> keys)
|
@Override @Deprecated public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String>writers, boolean applyToParents)
|
||||||
{
|
{
|
||||||
if (map != null && keys != null && keys.size() != 0)
|
remove(nodeRef);
|
||||||
{
|
|
||||||
// remove the keys
|
|
||||||
for (String key : keys)
|
|
||||||
{
|
|
||||||
if (!key.equals(PermissionService.ALL_AUTHORITIES))
|
|
||||||
{
|
|
||||||
Integer count = map.get(key);
|
|
||||||
if (count != null)
|
|
||||||
{
|
|
||||||
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 (map != null && map.isEmpty())
|
|
||||||
{
|
|
||||||
map = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, boolean)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override @Deprecated public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents)
|
||||||
public void removeAllExtendedSecurity(NodeRef nodeRef)
|
|
||||||
{
|
{
|
||||||
removeAllExtendedSecurity(nodeRef, true);
|
remove(nodeRef);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, boolean)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents)
|
|
||||||
{
|
|
||||||
if (hasExtendedSecurity(nodeRef))
|
|
||||||
{
|
|
||||||
removeExtendedSecurity(nodeRef, getExtendedReaders(nodeRef), getExtendedWriters(nodeRef));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,8 +27,6 @@
|
|||||||
|
|
||||||
package org.alfresco.module.org_alfresco_module_rm.security;
|
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||||
|
|
||||||
import static org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority.EXTENDED_READER;
|
|
||||||
import static org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority.EXTENDED_WRITER;
|
|
||||||
import static org.alfresco.repo.policy.Behaviour.NotificationFrequency.TRANSACTION_COMMIT;
|
import static org.alfresco.repo.policy.Behaviour.NotificationFrequency.TRANSACTION_COMMIT;
|
||||||
import static org.alfresco.repo.policy.annotation.BehaviourKind.CLASS;
|
import static org.alfresco.repo.policy.annotation.BehaviourKind.CLASS;
|
||||||
import static org.alfresco.repo.security.authentication.AuthenticationUtil.getSystemUserName;
|
import static org.alfresco.repo.security.authentication.AuthenticationUtil.getSystemUserName;
|
||||||
@@ -383,13 +381,29 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
|||||||
boolean inheritanceAllowed = isInheritanceAllowed(nodeRef, isParentNodeFilePlan);
|
boolean inheritanceAllowed = isInheritanceAllowed(nodeRef, isParentNodeFilePlan);
|
||||||
getPermissionService().setInheritParentPermissions(nodeRef, inheritanceAllowed);
|
getPermissionService().setInheritParentPermissions(nodeRef, inheritanceAllowed);
|
||||||
|
|
||||||
// clear all existing permissions
|
Set<AccessPermission> keepPerms = new HashSet<AccessPermission>(5);
|
||||||
|
Set<AccessPermission> origionalPerms= getPermissionService().getAllSetPermissions(nodeRef);
|
||||||
|
|
||||||
|
for (AccessPermission perm : origionalPerms)
|
||||||
|
{
|
||||||
|
if (perm.getAuthority().startsWith(PermissionService.GROUP_PREFIX + ExtendedSecurityService.IPR_GROUP_PREFIX))
|
||||||
|
{
|
||||||
|
// then we can assume this is a permission we want to preserve
|
||||||
|
keepPerms.add(perm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear all existing permissions and start again
|
||||||
getPermissionService().clearPermission(nodeRef, null);
|
getPermissionService().clearPermission(nodeRef, null);
|
||||||
|
|
||||||
|
// re-add keep'er permissions
|
||||||
|
for (AccessPermission keeper : keepPerms)
|
||||||
|
{
|
||||||
|
setPermission(nodeRef, keeper.getAuthority(), keeper.getPermission());
|
||||||
|
}
|
||||||
|
|
||||||
if (!inheritanceAllowed)
|
if (!inheritanceAllowed)
|
||||||
{
|
{
|
||||||
getPermissionService().setPermission(nodeRef, EXTENDED_READER, READ_RECORDS, true);
|
|
||||||
getPermissionService().setPermission(nodeRef, EXTENDED_WRITER, FILING, true);
|
|
||||||
String adminRole = getAdminRole(nodeRef);
|
String adminRole = getAdminRole(nodeRef);
|
||||||
getPermissionService().setPermission(nodeRef, adminRole, RMPermissionModel.FILING, true);
|
getPermissionService().setPermission(nodeRef, adminRole, RMPermissionModel.FILING, true);
|
||||||
}
|
}
|
||||||
@@ -435,9 +449,20 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
|||||||
return authorityService.getName(AuthorityType.GROUP, FilePlanRoleService.ROLE_ADMIN + filePlan.getId());
|
return authorityService.getName(AuthorityType.GROUP, FilePlanRoleService.ROLE_ADMIN + filePlan.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the default behaviour is to inherit permissions or not.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @param isParentNodeFilePlan true if parent node is a file plan, false otherwise
|
||||||
|
* @return boolean true if inheritance true, false otherwise
|
||||||
|
*/
|
||||||
private boolean isInheritanceAllowed(NodeRef nodeRef, Boolean isParentNodeFilePlan)
|
private boolean isInheritanceAllowed(NodeRef nodeRef, Boolean isParentNodeFilePlan)
|
||||||
{
|
{
|
||||||
return !(isFilePlan(nodeRef) || isTransfer(nodeRef) || isHold(nodeRef) || isUnfiledRecordsContainer(nodeRef) || (isRecordCategory(nodeRef) && isTrue(isParentNodeFilePlan)));
|
return !(isFilePlan(nodeRef) ||
|
||||||
|
isTransfer(nodeRef) ||
|
||||||
|
isHold(nodeRef) ||
|
||||||
|
isUnfiledRecordsContainer(nodeRef) ||
|
||||||
|
(isRecordCategory(nodeRef) && isTrue(isParentNodeFilePlan)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -494,20 +519,14 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
|||||||
for (AccessPermission recordPermission : origionalRecordPerms)
|
for (AccessPermission recordPermission : origionalRecordPerms)
|
||||||
{
|
{
|
||||||
String permission = recordPermission.getPermission();
|
String permission = recordPermission.getPermission();
|
||||||
String authority = recordPermission.getAuthority();
|
|
||||||
if ((RMPermissionModel.FILING.equals(permission) || RMPermissionModel.READ_RECORDS.equals(permission)) &&
|
if ((RMPermissionModel.FILING.equals(permission) || RMPermissionModel.READ_RECORDS.equals(permission)) &&
|
||||||
recordPermission.isSetDirectly() &&
|
recordPermission.isSetDirectly())
|
||||||
!ExtendedReaderDynamicAuthority.EXTENDED_READER.equals(authority) &&
|
|
||||||
!ExtendedWriterDynamicAuthority.EXTENDED_WRITER.equals(authority))
|
|
||||||
{
|
{
|
||||||
// then we can assume this is a permission we want to preserve
|
// then we can assume this is a permission we want to preserve
|
||||||
keepPerms.add(recordPermission);
|
keepPerms.add(recordPermission);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear all existing permissions and start again
|
|
||||||
permissionService.deletePermissions(record);
|
|
||||||
|
|
||||||
// re-setup the records permissions
|
// re-setup the records permissions
|
||||||
setupPermissions(destinationAssocRef.getParentRef(), record);
|
setupPermissions(destinationAssocRef.getParentRef(), record);
|
||||||
|
|
||||||
@@ -589,7 +608,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
|||||||
|
|
||||||
private boolean canPerformPermissionAction(NodeRef nodeRef)
|
private boolean canPerformPermissionAction(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
return isFilePlanContainer(nodeRef) || isRecordFolder(nodeRef) || isRecord(nodeRef) || isTransfer(nodeRef);
|
return isFilePlanContainer(nodeRef) || isRecordFolder(nodeRef) || isRecord(nodeRef) || isTransfer(nodeRef) || isHold(nodeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -34,7 +34,6 @@ import java.io.Serializable;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -56,12 +55,12 @@ import org.alfresco.repo.version.VersionModel;
|
|||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
import org.alfresco.service.cmr.security.OwnableService;
|
|
||||||
import org.alfresco.service.cmr.version.ReservedVersionNameException;
|
import org.alfresco.service.cmr.version.ReservedVersionNameException;
|
||||||
import org.alfresco.service.cmr.version.Version;
|
import org.alfresco.service.cmr.version.Version;
|
||||||
import org.alfresco.service.cmr.version.VersionHistory;
|
import org.alfresco.service.cmr.version.VersionHistory;
|
||||||
import org.alfresco.service.cmr.version.VersionType;
|
import org.alfresco.service.cmr.version.VersionType;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
import org.alfresco.util.ParameterCheck;
|
import org.alfresco.util.ParameterCheck;
|
||||||
import org.alfresco.util.PropertyMap;
|
import org.alfresco.util.PropertyMap;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
@@ -129,9 +128,6 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
|
|||||||
|
|
||||||
/** extended security service */
|
/** extended security service */
|
||||||
private ExtendedSecurityService extendedSecurityService;
|
private ExtendedSecurityService extendedSecurityService;
|
||||||
|
|
||||||
/** ownable service */
|
|
||||||
private OwnableService ownableService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param filePlanService file plan service
|
* @param filePlanService file plan service
|
||||||
@@ -196,14 +192,6 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
|
|||||||
{
|
{
|
||||||
this.extendedSecurityService = extendedSecurityService;
|
this.extendedSecurityService = extendedSecurityService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ownableService ownable service
|
|
||||||
*/
|
|
||||||
public void setOwnableService(OwnableService ownableService)
|
|
||||||
{
|
|
||||||
this.ownableService = ownableService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.repo.version.Version2ServiceImpl#createVersion(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, int)
|
* @see org.alfresco.repo.version.Version2ServiceImpl#createVersion(org.alfresco.service.cmr.repository.NodeRef, java.util.Map, int)
|
||||||
@@ -706,13 +694,8 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
|
|||||||
{
|
{
|
||||||
public NodeRef doWork() throws Exception
|
public NodeRef doWork() throws Exception
|
||||||
{
|
{
|
||||||
// get the documents readers
|
// get the documents readers and writers
|
||||||
Long aclId = nodeService.getNodeAclId(nodeRef);
|
Pair<Set<String>, Set<String>> readersAndWriters = extendedPermissionService.getReadersAndWriters(nodeRef);
|
||||||
Set<String> readers = extendedPermissionService.getReaders(aclId);
|
|
||||||
Set<String> writers = extendedPermissionService.getWriters(aclId);
|
|
||||||
|
|
||||||
// add the current owner to the list of extended writers
|
|
||||||
String owner = ownableService.getOwner(nodeRef);
|
|
||||||
|
|
||||||
// grab the frozen state
|
// grab the frozen state
|
||||||
NodeRef currentFrozenState = currentVersion.getFrozenStateNodeRef();
|
NodeRef currentFrozenState = currentVersion.getFrozenStateNodeRef();
|
||||||
@@ -752,13 +735,7 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
|
|||||||
linkToPreviousVersionRecord(nodeRef, record);
|
linkToPreviousVersionRecord(nodeRef, record);
|
||||||
|
|
||||||
// set the extended security
|
// set the extended security
|
||||||
Set<String> combinedWriters = new HashSet<String>(writers);
|
extendedSecurityService.set(record, readersAndWriters);
|
||||||
if (owner != null && !owner.isEmpty() && !owner.equals(OwnableService.NO_OWNER))
|
|
||||||
{
|
|
||||||
combinedWriters.add(owner);
|
|
||||||
}
|
|
||||||
combinedWriters.add(authenticationUtil.getFullyAuthenticatedUser());
|
|
||||||
extendedSecurityService.addExtendedSecurity(record, readers, combinedWriters);
|
|
||||||
|
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,9 @@ package org.alfresco.repo.security.permissions.impl;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.security.PermissionService;
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extended Permission Service Interface used in RM.
|
* Extended Permission Service Interface used in RM.
|
||||||
@@ -46,4 +48,18 @@ public interface ExtendedPermissionService extends PermissionService
|
|||||||
* @return {@link Set}<{@link String}> set of authorities with write access
|
* @return {@link Set}<{@link String}> set of authorities with write access
|
||||||
*/
|
*/
|
||||||
Set<String> getWriters(Long aclId);
|
Set<String> getWriters(Long aclId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the readers and writers for a given node.
|
||||||
|
* <p>
|
||||||
|
* The writers list includes the owner for the node.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @return Pair<Set<String>, Set<String>> first is a set containing all the authorities that have read permission on the
|
||||||
|
* document and second is a set containing all the authorities that have write
|
||||||
|
* permission on the document, including the owner.
|
||||||
|
*
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
Pair<Set<String>, Set<String>> getReadersAndWriters(NodeRef nodeRef);
|
||||||
}
|
}
|
||||||
|
@@ -39,8 +39,6 @@ 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.fileplan.FilePlanService;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
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.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.repo.cache.SimpleCache;
|
import org.alfresco.repo.cache.SimpleCache;
|
||||||
import org.alfresco.repo.security.permissions.AccessControlEntry;
|
import org.alfresco.repo.security.permissions.AccessControlEntry;
|
||||||
import org.alfresco.repo.security.permissions.AccessControlList;
|
import org.alfresco.repo.security.permissions.AccessControlList;
|
||||||
@@ -50,8 +48,11 @@ import org.alfresco.repo.security.permissions.processor.PermissionProcessorRegis
|
|||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.security.AccessStatus;
|
import org.alfresco.service.cmr.security.AccessStatus;
|
||||||
import org.alfresco.service.cmr.security.AuthorityType;
|
import org.alfresco.service.cmr.security.AuthorityType;
|
||||||
|
import org.alfresco.service.cmr.security.OwnableService;
|
||||||
import org.alfresco.service.cmr.security.PermissionService;
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
import org.alfresco.util.PropertyCheck;
|
import org.alfresco.util.PropertyCheck;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.springframework.context.ApplicationEvent;
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -359,13 +360,17 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl
|
|||||||
final String adminRole = getAdminRole(nodeRef);
|
final String adminRole = getAdminRole(nodeRef);
|
||||||
if (nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT) && isNotBlank(adminRole) && !inheritParentPermissions)
|
if (nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT) && isNotBlank(adminRole) && !inheritParentPermissions)
|
||||||
{
|
{
|
||||||
setPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true);
|
setPermission(nodeRef, adminRole, RMPermissionModel.FILING, true);
|
||||||
setPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true);
|
|
||||||
setPermission(nodeRef, adminRole, RMPermissionModel.FILING, true);
|
|
||||||
}
|
}
|
||||||
super.setInheritParentPermissions(nodeRef, inheritParentPermissions);
|
super.setInheritParentPermissions(nodeRef, inheritParentPermissions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to the RM admin role scoped by the correct file plan.
|
||||||
|
*
|
||||||
|
* @param nodeRef node reference
|
||||||
|
* @return String RM admin role
|
||||||
|
*/
|
||||||
private String getAdminRole(NodeRef nodeRef)
|
private String getAdminRole(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
String adminRole = null;
|
String adminRole = null;
|
||||||
@@ -376,4 +381,28 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl
|
|||||||
}
|
}
|
||||||
return adminRole;
|
return adminRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.repo.security.permissions.impl.ExtendedPermissionService#getReadersAndWriters(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Pair<Set<String>, Set<String>> getReadersAndWriters(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
// get the documents readers
|
||||||
|
Long aclId = nodeService.getNodeAclId(nodeRef);
|
||||||
|
Set<String> readers = getReaders(aclId);
|
||||||
|
Set<String> writers = getWriters(aclId);
|
||||||
|
|
||||||
|
// add the current owner to the list of extended writers
|
||||||
|
Set<String> modifiedWrtiers = new HashSet<String>(writers);
|
||||||
|
String owner = ownableService.getOwner(nodeRef);
|
||||||
|
if (StringUtils.isNotBlank(owner) &&
|
||||||
|
!owner.equals(OwnableService.NO_OWNER) &&
|
||||||
|
authorityService.authorityExists(owner))
|
||||||
|
{
|
||||||
|
modifiedWrtiers.add(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Pair<Set<String>, Set<String>> (readers, modifiedWrtiers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,267 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* 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/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2014 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.web.scripts.roles;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
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.ExtendedSecurityService;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
|
||||||
|
import org.alfresco.repo.domain.node.NodeDAO;
|
||||||
|
import org.alfresco.repo.domain.patch.PatchDAO;
|
||||||
|
import org.alfresco.repo.domain.qname.QNameDAO;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
|
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||||
|
import org.springframework.extensions.webscripts.Status;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Webscript used for removing dynamic authorities from the records.
|
||||||
|
*
|
||||||
|
* @author Silviu Dinuta
|
||||||
|
* @since 2.3.0.7
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public class DynamicAuthoritiesGet extends DeclarativeWebScript implements RecordsManagementModel
|
||||||
|
{
|
||||||
|
private static final String MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO = "Parameter batchsize should be a number greater than 0.";
|
||||||
|
private static final String MESSAGE_PROCESSING_BEGIN = "Processing - BEGIN";
|
||||||
|
private static final String MESSAGE_PROCESSING_END = "Processing - END";
|
||||||
|
private static final String MESSAGE_PROCESSING_RECORD_END_TEMPLATE = "Processing record {0} - END";
|
||||||
|
private static final String MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE = "Processing record {0} - BEGIN";
|
||||||
|
private static final String MESSAGE_BATCHSIZE_IS_INVALID = "Parameter batchsize is invalid.";
|
||||||
|
private static final String MESSAGE_BATCHSIZE_IS_MANDATORY = "Parameter batchsize is mandatory";
|
||||||
|
private static final String SUCCESS_STATUS = "success";
|
||||||
|
private static final String FAILED_STATUS = "failed";
|
||||||
|
/**
|
||||||
|
* The logger
|
||||||
|
*/
|
||||||
|
private static Log logger = LogFactory.getLog(DynamicAuthoritiesGet.class);
|
||||||
|
private static final String BATCH_SIZE = "batchsize";
|
||||||
|
private static final String TOTAL_NUMBER_TO_PROCESS = "maxProcessedRecords";
|
||||||
|
private static final String MODEL_STATUS = "responsestatus";
|
||||||
|
private static final String MODEL_MESSAGE = "message";
|
||||||
|
private static final String MESSAGE_ALL_TEMPLATE = "Processed {0} records.";
|
||||||
|
private static final String MESSAGE_PARTIAL_TEMPLATE = "Processed first {0} records.";
|
||||||
|
private static final String MESSAGE_NO_RECORDS_TO_PROCESS = "There where no records to be processed.";
|
||||||
|
|
||||||
|
|
||||||
|
/** services */
|
||||||
|
private PatchDAO patchDAO;
|
||||||
|
private NodeDAO nodeDAO;
|
||||||
|
private QNameDAO qnameDAO;
|
||||||
|
private NodeService nodeService;
|
||||||
|
private PermissionService permissionService;
|
||||||
|
private ExtendedSecurityService extendedSecurityService;
|
||||||
|
private TransactionService transactionService;
|
||||||
|
|
||||||
|
/** service setters */
|
||||||
|
public void setPatchDAO(PatchDAO patchDAO) { this.patchDAO = patchDAO; }
|
||||||
|
public void setNodeDAO(NodeDAO nodeDAO) { this.nodeDAO = nodeDAO; }
|
||||||
|
public void setQnameDAO(QNameDAO qnameDAO) { this.qnameDAO = qnameDAO; }
|
||||||
|
public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; }
|
||||||
|
public void setPermissionService(PermissionService permissionService) { this.permissionService = permissionService; }
|
||||||
|
public void setExtendedSecurityService(ExtendedSecurityService extendedSecurityService) { this.extendedSecurityService = extendedSecurityService; }
|
||||||
|
public void setTransactionService(TransactionService transactionService) { this.transactionService = transactionService; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||||
|
{
|
||||||
|
Map<String, Object> model = new HashMap<String, Object>();
|
||||||
|
String batchSizeStr = req.getParameter(BATCH_SIZE);
|
||||||
|
String totalToBeProcessedRecordsStr = req.getParameter(TOTAL_NUMBER_TO_PROCESS);
|
||||||
|
|
||||||
|
Long size = 0L;
|
||||||
|
if (StringUtils.isBlank(batchSizeStr))
|
||||||
|
{
|
||||||
|
model.put(MODEL_STATUS, FAILED_STATUS);
|
||||||
|
model.put(MODEL_MESSAGE, MESSAGE_BATCHSIZE_IS_MANDATORY);
|
||||||
|
logger.info(MESSAGE_BATCHSIZE_IS_MANDATORY);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
size = Long.parseLong(batchSizeStr);
|
||||||
|
if(size <= 0)
|
||||||
|
{
|
||||||
|
model.put(MODEL_STATUS, FAILED_STATUS);
|
||||||
|
model.put(MODEL_MESSAGE, MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO);
|
||||||
|
logger.info(MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(NumberFormatException ex)
|
||||||
|
{
|
||||||
|
model.put(MODEL_STATUS, FAILED_STATUS);
|
||||||
|
model.put(MODEL_MESSAGE, MESSAGE_BATCHSIZE_IS_INVALID);
|
||||||
|
logger.info(MESSAGE_BATCHSIZE_IS_INVALID);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
final Long batchSize = size;
|
||||||
|
// get the max node id and the extended security aspect
|
||||||
|
Long maxNodeId = patchDAO.getMaxAdmNodeID();
|
||||||
|
final Pair<Long, QName> recordAspectPair = qnameDAO.getQName(ASPECT_EXTENDED_SECURITY);
|
||||||
|
if(recordAspectPair == null)
|
||||||
|
{
|
||||||
|
model.put(MODEL_STATUS, SUCCESS_STATUS);
|
||||||
|
model.put(MODEL_MESSAGE, MESSAGE_NO_RECORDS_TO_PROCESS);
|
||||||
|
logger.info(MESSAGE_NO_RECORDS_TO_PROCESS);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
//default total number of records to be processed to batch size value
|
||||||
|
Long totalNumberOfRecordsToProcess = batchSize;
|
||||||
|
if (StringUtils.isNotBlank(totalToBeProcessedRecordsStr))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
totalNumberOfRecordsToProcess = Long.parseLong(totalToBeProcessedRecordsStr);
|
||||||
|
}
|
||||||
|
catch(NumberFormatException ex)
|
||||||
|
{
|
||||||
|
//do nothing here, the value will remain 0L in this case
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Long maxRecordsToProcess = totalNumberOfRecordsToProcess;
|
||||||
|
final List<NodeRef> processedNodes = new ArrayList<NodeRef>();
|
||||||
|
logger.info(MESSAGE_PROCESSING_BEGIN);
|
||||||
|
// by batch size
|
||||||
|
for (Long i = 0L; i < maxNodeId; i+=batchSize)
|
||||||
|
{
|
||||||
|
if(maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
final Long currentIndex = i;
|
||||||
|
|
||||||
|
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
// get the nodes with the extended security aspect applied
|
||||||
|
List<Long> nodeIds = patchDAO.getNodesByAspectQNameId(recordAspectPair.getFirst(), currentIndex, currentIndex + batchSize);
|
||||||
|
|
||||||
|
// process each one
|
||||||
|
for (Long nodeId : nodeIds)
|
||||||
|
{
|
||||||
|
if(maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
NodeRef record = nodeDAO.getNodePair(nodeId).getSecond();
|
||||||
|
String recordName = (String) nodeService.getProperty(record, ContentModel.PROP_NAME);
|
||||||
|
logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE, recordName));
|
||||||
|
processNode(record);
|
||||||
|
logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_END_TEMPLATE, recordName));
|
||||||
|
processedNodes.add(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false, // read only
|
||||||
|
true); // requires new
|
||||||
|
}
|
||||||
|
logger.info(MESSAGE_PROCESSING_END);
|
||||||
|
int processedNodesSize = processedNodes.size();
|
||||||
|
String message = "";
|
||||||
|
if(totalNumberOfRecordsToProcess == 0 || (totalNumberOfRecordsToProcess > 0 && processedNodesSize < totalNumberOfRecordsToProcess))
|
||||||
|
{
|
||||||
|
message = MessageFormat.format(MESSAGE_ALL_TEMPLATE, processedNodesSize);
|
||||||
|
}
|
||||||
|
if (totalNumberOfRecordsToProcess > 0 && totalNumberOfRecordsToProcess == processedNodesSize)
|
||||||
|
{
|
||||||
|
message = MessageFormat.format(MESSAGE_PARTIAL_TEMPLATE, totalNumberOfRecordsToProcess);
|
||||||
|
}
|
||||||
|
model.put(MODEL_STATUS, SUCCESS_STATUS);
|
||||||
|
model.put(MODEL_MESSAGE, message);
|
||||||
|
logger.info(message);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process each node
|
||||||
|
*
|
||||||
|
* @param nodeRef
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({ "unchecked"})
|
||||||
|
private void processNode(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
// get the reader/writer data
|
||||||
|
Map<String, Integer> readers = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
|
||||||
|
Map<String, Integer> writers = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_WRITERS);
|
||||||
|
|
||||||
|
// remove extended security aspect
|
||||||
|
nodeService.removeAspect(nodeRef, ASPECT_EXTENDED_SECURITY);
|
||||||
|
|
||||||
|
// remove dynamic authority permissions
|
||||||
|
permissionService.clearPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER);
|
||||||
|
permissionService.clearPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER);
|
||||||
|
|
||||||
|
// if record then ...
|
||||||
|
if (nodeService.hasAspect(nodeRef, ASPECT_RECORD))
|
||||||
|
{
|
||||||
|
// re-set extended security via API
|
||||||
|
extendedSecurityService.set(nodeRef, readers.keySet(), writers.keySet());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -44,14 +44,14 @@ public class RM1429Test extends DeleteHoldTest
|
|||||||
{
|
{
|
||||||
public void testDeleteHoldWithoutPermissionsOnChildren()
|
public void testDeleteHoldWithoutPermissionsOnChildren()
|
||||||
{
|
{
|
||||||
// Create the test hold
|
final NodeRef hold = doTestInTransaction(new Test<NodeRef>()
|
||||||
final NodeRef hold = createAndCheckHold();
|
|
||||||
|
|
||||||
doTestInTransaction(new Test<Void>()
|
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Void run()
|
public NodeRef run()
|
||||||
{
|
{
|
||||||
|
// Create the test hold
|
||||||
|
NodeRef hold = createAndCheckHold();
|
||||||
|
|
||||||
// Add the user to the RM Manager role
|
// Add the user to the RM Manager role
|
||||||
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
|
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ public class RM1429Test extends DeleteHoldTest
|
|||||||
// Add record folder to the hold
|
// Add record folder to the hold
|
||||||
holdService.addToHold(hold, rmFolder);
|
holdService.addToHold(hold, rmFolder);
|
||||||
|
|
||||||
return null;
|
return hold;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -44,14 +44,14 @@ public class RM1463Test extends DeleteHoldTest
|
|||||||
{
|
{
|
||||||
public void testAddRecordFolderToHoldWithoutFilingPermissionOnRecordFolder()
|
public void testAddRecordFolderToHoldWithoutFilingPermissionOnRecordFolder()
|
||||||
{
|
{
|
||||||
// Create hold
|
final NodeRef hold = doTestInTransaction(new Test<NodeRef>()
|
||||||
final NodeRef hold = createAndCheckHold();
|
|
||||||
|
|
||||||
doTestInTransaction(new Test<Void>()
|
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Void run()
|
public NodeRef run()
|
||||||
{
|
{
|
||||||
|
// Create hold
|
||||||
|
NodeRef hold = createAndCheckHold();
|
||||||
|
|
||||||
// Add the user to the RM Manager role
|
// Add the user to the RM Manager role
|
||||||
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
|
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ public class RM1463Test extends DeleteHoldTest
|
|||||||
// Give the user only read permissions on the record folder
|
// Give the user only read permissions on the record folder
|
||||||
permissionService.setPermission(rmFolder, userName, RMPermissionModel.READ_RECORDS, true);
|
permissionService.setPermission(rmFolder, userName, RMPermissionModel.READ_RECORDS, true);
|
||||||
|
|
||||||
return null;
|
return hold;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -44,14 +44,14 @@ public class RM1464Test extends DeleteHoldTest
|
|||||||
{
|
{
|
||||||
public void testAddRecordFolderToHoldWithoutFilingPermissionOnHold()
|
public void testAddRecordFolderToHoldWithoutFilingPermissionOnHold()
|
||||||
{
|
{
|
||||||
// Create hold
|
final NodeRef hold = doTestInTransaction(new Test<NodeRef>()
|
||||||
final NodeRef hold = createAndCheckHold();
|
|
||||||
|
|
||||||
doTestInTransaction(new Test<Void>()
|
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Void run()
|
public NodeRef run()
|
||||||
{
|
{
|
||||||
|
// Create hold
|
||||||
|
NodeRef hold = createAndCheckHold();
|
||||||
|
|
||||||
// Add the user to the RM Manager role
|
// Add the user to the RM Manager role
|
||||||
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
|
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ public class RM1464Test extends DeleteHoldTest
|
|||||||
// Give the user filing permissions on the record folder
|
// Give the user filing permissions on the record folder
|
||||||
permissionService.setPermission(rmFolder, userName, RMPermissionModel.FILING, true);
|
permissionService.setPermission(rmFolder, userName, RMPermissionModel.FILING, true);
|
||||||
|
|
||||||
return null;
|
return hold;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* 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/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2014 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.test.integration.issue;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
|
import org.alfresco.service.cmr.action.Action;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.rule.Rule;
|
||||||
|
import org.alfresco.service.cmr.rule.RuleService;
|
||||||
|
import org.alfresco.service.cmr.rule.RuleType;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System test for RM-3993: Exceptions thrown when concurrently creating identical folder structure
|
||||||
|
*
|
||||||
|
* @author Silviu Dinuta
|
||||||
|
* @since 2.3.0.7
|
||||||
|
*/
|
||||||
|
public class RM3993Test extends BaseRMTestCase
|
||||||
|
{
|
||||||
|
private static final int NUMBER_OF_BATCHES = 4;
|
||||||
|
private static final int NUMBER_IN_BATCH = 500;
|
||||||
|
|
||||||
|
private RuleService ruleService;
|
||||||
|
private NodeRef ruleFolder;
|
||||||
|
private NodeRef nodeRefCategory1;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initServices()
|
||||||
|
{
|
||||||
|
super.initServices();
|
||||||
|
|
||||||
|
ruleService = (RuleService) applicationContext.getBean("RuleService");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isCollaborationSiteTest()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isRecordTest()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that I have auto declare configured And that I have auto file configured to a path where only the record
|
||||||
|
* folder needs to be created When I add lots of documents in the same transaction Then the rules should fire And
|
||||||
|
* the documents should be filed in the new record folder
|
||||||
|
*/
|
||||||
|
public void testAutoDeclareAutoFileCreateRecordFolderOnly() throws Exception
|
||||||
|
{
|
||||||
|
doTestInTransaction(new Test<Void>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Void run()
|
||||||
|
{
|
||||||
|
// create the folder
|
||||||
|
ruleFolder = fileFolderService.create(documentLibrary, "mytestfolder", ContentModel.TYPE_FOLDER)
|
||||||
|
.getNodeRef();
|
||||||
|
|
||||||
|
// create record category
|
||||||
|
nodeRefCategory1 = filePlanService.createRecordCategory(filePlan, "category1");
|
||||||
|
|
||||||
|
Action action = actionService.createAction(CreateRecordAction.NAME);
|
||||||
|
action.setParameterValue(CreateRecordAction.PARAM_FILE_PLAN, filePlan);
|
||||||
|
|
||||||
|
Rule rule = new Rule();
|
||||||
|
rule.setRuleType(RuleType.INBOUND);
|
||||||
|
rule.setTitle("my rule");
|
||||||
|
rule.setAction(action);
|
||||||
|
rule.setExecuteAsynchronously(true);
|
||||||
|
ruleService.saveRule(ruleFolder, rule);
|
||||||
|
|
||||||
|
Action fileAction = actionService.createAction(FileToAction.NAME);
|
||||||
|
fileAction.setParameterValue(FileToAction.PARAM_PATH,
|
||||||
|
"/category1/{node.cm:description}");
|
||||||
|
fileAction.setParameterValue(FileToAction.PARAM_CREATE_RECORD_PATH, true);
|
||||||
|
|
||||||
|
Rule fileRule = new Rule();
|
||||||
|
fileRule.setRuleType(RuleType.INBOUND);
|
||||||
|
fileRule.setTitle("my rule");
|
||||||
|
fileRule.setAction(fileAction);
|
||||||
|
fileRule.setExecuteAsynchronously(true);
|
||||||
|
ruleService.saveRule(filePlanService.getUnfiledContainer(filePlan), fileRule);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void test(Void result) throws Exception
|
||||||
|
{
|
||||||
|
assertFalse(ruleService.getRules(ruleFolder).isEmpty());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
List<NodeRef> records = new ArrayList<NodeRef>(NUMBER_OF_BATCHES * NUMBER_IN_BATCH);
|
||||||
|
|
||||||
|
for (int i = 0; i < NUMBER_OF_BATCHES; i++)
|
||||||
|
{
|
||||||
|
final int finali = i;
|
||||||
|
records.addAll(doTestInTransaction(new Test<List<NodeRef>>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public List<NodeRef> run() throws Exception
|
||||||
|
{
|
||||||
|
List<NodeRef> records = new ArrayList<NodeRef>(NUMBER_IN_BATCH);
|
||||||
|
for (int j = 0; j < NUMBER_IN_BATCH; j++)
|
||||||
|
{
|
||||||
|
int count = (finali)* NUMBER_IN_BATCH + (j + 1);
|
||||||
|
String name = "content" + count + ".txt";
|
||||||
|
System.out.println(name + " - creating");
|
||||||
|
|
||||||
|
Random rand = new Random();
|
||||||
|
int descInt = rand.nextInt(2)+1;
|
||||||
|
NodeRef record = createFile(ruleFolder, name, Integer.toString(descInt), ContentModel.TYPE_CONTENT);
|
||||||
|
records.add(record);
|
||||||
|
}
|
||||||
|
return records;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!records.isEmpty())
|
||||||
|
{
|
||||||
|
Thread.sleep(1000);
|
||||||
|
|
||||||
|
final Iterator<NodeRef> temp = records.iterator();
|
||||||
|
doTestInTransaction(new Test<Void>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Void run() throws Exception
|
||||||
|
{
|
||||||
|
while (temp.hasNext())
|
||||||
|
{
|
||||||
|
NodeRef record = temp.next();
|
||||||
|
if (nodeService.hasAspect(record, ASPECT_RECORD) && recordService.isFiled(record))
|
||||||
|
{
|
||||||
|
String name = (String) nodeService.getProperty(record, ContentModel.PROP_NAME);
|
||||||
|
System.out.println(name + " - complete");
|
||||||
|
temp.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
exception.printStackTrace();
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer numberOfRecords = AuthenticationUtil.runAsSystem(new RunAsWork<Integer>()
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer doWork() throws Exception
|
||||||
|
{
|
||||||
|
List<NodeRef> containedRecordFolders = filePlanService.getContainedRecordFolders(nodeRefCategory1);
|
||||||
|
int numberOfRecords = 0;
|
||||||
|
for(NodeRef recordFolder : containedRecordFolders)
|
||||||
|
{
|
||||||
|
numberOfRecords = numberOfRecords + fileFolderService.list(recordFolder).size();
|
||||||
|
}
|
||||||
|
return numberOfRecords;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertTrue(numberOfRecords == NUMBER_OF_BATCHES * NUMBER_IN_BATCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeRef createFile(NodeRef parentNodeRef, String name, String descrption, QName typeQName)
|
||||||
|
{
|
||||||
|
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(11);
|
||||||
|
properties.put(ContentModel.PROP_NAME, (Serializable) name);
|
||||||
|
properties.put(ContentModel.PROP_DESCRIPTION, (Serializable) descrption);
|
||||||
|
QName assocQName = QName.createQName(
|
||||||
|
NamespaceService.CONTENT_MODEL_1_0_URI,
|
||||||
|
QName.createValidLocalName(name));
|
||||||
|
ChildAssociationRef assocRef = nodeService.createNode(
|
||||||
|
parentNodeRef,
|
||||||
|
ContentModel.ASSOC_CONTAINS,
|
||||||
|
assocQName,
|
||||||
|
typeQName,
|
||||||
|
properties);
|
||||||
|
NodeRef nodeRef = assocRef.getChildRef();
|
||||||
|
return nodeRef;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* 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/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.module.org_alfresco_module_rm.test.integration.record;
|
||||||
|
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
|
import org.alfresco.service.cmr.model.FileExistsException;
|
||||||
|
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||||
|
import org.alfresco.service.cmr.security.AccessStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create Inplace Record Test
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
*/
|
||||||
|
public class CreateInplaceRecordTest extends BaseRMTestCase
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected boolean isCollaborationSiteTest()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a document in a collaboration site
|
||||||
|
* When the document is declared by a site collaborator
|
||||||
|
* Then the document becomes a record
|
||||||
|
* And the site users have the appropriate in-place permissions on the record
|
||||||
|
*/
|
||||||
|
public void testCreateInplaceRecordFromCollabSite()
|
||||||
|
{
|
||||||
|
doBehaviourDrivenTest(new BehaviourDrivenTest()
|
||||||
|
{
|
||||||
|
public void given()
|
||||||
|
{
|
||||||
|
// Check that the document is not a record
|
||||||
|
assertFalse("The document should not be a record", recordService.isRecord(dmDocument));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void when()
|
||||||
|
{
|
||||||
|
// Declare the document as a record
|
||||||
|
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||||||
|
{
|
||||||
|
public Void doWork() throws Exception
|
||||||
|
{
|
||||||
|
// Declare record
|
||||||
|
recordService.createRecord(filePlan, dmDocument);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, dmCollaborator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void then()
|
||||||
|
{
|
||||||
|
// Check that the document is a record now
|
||||||
|
assertTrue("The document should now be a record", recordService.isRecord(dmDocument));
|
||||||
|
|
||||||
|
// Check that the record is in the unfiled container
|
||||||
|
|
||||||
|
// Check that the record is still a child of the collaboration folder
|
||||||
|
|
||||||
|
// Check that the collaborator has filling permissions on the record
|
||||||
|
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||||||
|
{
|
||||||
|
public Void doWork() throws Exception
|
||||||
|
{
|
||||||
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(dmDocument, RMPermissionModel.FILING));
|
||||||
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(dmDocument, RMPermissionModel.READ_RECORDS));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, dmCollaborator);
|
||||||
|
|
||||||
|
|
||||||
|
// Check that the consumer has read permissions on the record
|
||||||
|
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||||||
|
{
|
||||||
|
public Void doWork() throws Exception
|
||||||
|
{
|
||||||
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(dmDocument, RMPermissionModel.FILING));
|
||||||
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(dmDocument, RMPermissionModel.READ_RECORDS));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, dmConsumer);
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFileInplaceRecordFromCollabSite()
|
||||||
|
{
|
||||||
|
doBehaviourDrivenTest(new BehaviourDrivenTest()
|
||||||
|
{
|
||||||
|
public void given()
|
||||||
|
{
|
||||||
|
// Check that the document is not a record
|
||||||
|
assertFalse("The document should not be a record", recordService.isRecord(dmDocument));
|
||||||
|
|
||||||
|
// Declare the document as a record
|
||||||
|
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||||||
|
{
|
||||||
|
public Void doWork() throws Exception
|
||||||
|
{
|
||||||
|
// Declare record
|
||||||
|
recordService.createRecord(filePlan, dmDocument);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, dmCollaborator);
|
||||||
|
|
||||||
|
// Check that the document is a record
|
||||||
|
assertTrue("The document should be a record", recordService.isRecord(dmDocument));
|
||||||
|
assertFalse("The record should not be filed", recordService.isFiled(dmDocument));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void when() throws FileExistsException, FileNotFoundException
|
||||||
|
{
|
||||||
|
// file the document to a location in the file plan
|
||||||
|
fileFolderService.move(dmDocument, rmFolder, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void then()
|
||||||
|
{
|
||||||
|
// Check that the document is a record now
|
||||||
|
assertTrue("The document should be a record", recordService.isRecord(dmDocument));
|
||||||
|
assertTrue("The record hsould be filed", recordService.isFiled(dmDocument));
|
||||||
|
|
||||||
|
// Check that the record is in the unfiled container
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
// Check that the record is still a child of the collaboration folder
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
// Check that the collaborator has filling permissions on the record
|
||||||
|
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||||||
|
{
|
||||||
|
public Void doWork() throws Exception
|
||||||
|
{
|
||||||
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(dmDocument, RMPermissionModel.FILING));
|
||||||
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(dmDocument, RMPermissionModel.READ_RECORDS));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, dmCollaborator);
|
||||||
|
|
||||||
|
|
||||||
|
// Check that the consumer has read permissions on the record
|
||||||
|
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||||||
|
{
|
||||||
|
public Void doWork() throws Exception
|
||||||
|
{
|
||||||
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(dmDocument, RMPermissionModel.FILING));
|
||||||
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(dmDocument, RMPermissionModel.READ_RECORDS));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, dmConsumer);
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,951 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* 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/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.module.org_alfresco_module_rm.test.integration.record;
|
||||||
|
|
||||||
|
import static org.alfresco.module.org_alfresco_module_rm.test.util.bdt.BehaviourTest.test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.action.impl.CutOffAction;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.action.impl.DeclareRecordAction;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.action.impl.DestroyAction;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.CommonRMTestUtils;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.bdt.BehaviourTest;
|
||||||
|
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||||
|
import org.alfresco.repo.site.SiteModel;
|
||||||
|
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.PermissionService;
|
||||||
|
import org.alfresco.util.GUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In-place record permission integration test.
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
public class InplaceRecordPermissionTest extends BaseRMTestCase
|
||||||
|
{
|
||||||
|
/** capability list */
|
||||||
|
private static final List<String> CAPABILITIES = Stream
|
||||||
|
.of(RMPermissionModel.VIEW_RECORDS,
|
||||||
|
RMPermissionModel.EDIT_NON_RECORD_METADATA,
|
||||||
|
RMPermissionModel.EDIT_RECORD_METADATA)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
/** test data */
|
||||||
|
private NodeRef contribDoc;
|
||||||
|
private NodeRef deleteUserDoc;
|
||||||
|
private NodeRef copiedDoc;
|
||||||
|
private NodeRef copyDoc;
|
||||||
|
private String deletedUser;
|
||||||
|
|
||||||
|
/** services */
|
||||||
|
private NodeService dbNodeService;
|
||||||
|
|
||||||
|
/** capabilities */
|
||||||
|
private Capability viewRecordsCapability;
|
||||||
|
private Capability editNonRecordMetadataCapability;
|
||||||
|
private Capability editRecordMetadataCapability;
|
||||||
|
|
||||||
|
/** test characteristics */
|
||||||
|
@Override protected boolean isCollaborationSiteTest() { return true; }
|
||||||
|
@Override protected boolean isUserTest() { return true; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase#initServices()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void initServices()
|
||||||
|
{
|
||||||
|
super.initServices();
|
||||||
|
|
||||||
|
// initialise behaviour tests
|
||||||
|
BehaviourTest.initBehaviourTests(retryingTransactionHelper);
|
||||||
|
|
||||||
|
// get services
|
||||||
|
dbNodeService = (NodeService)applicationContext.getBean("dbNodeService");
|
||||||
|
|
||||||
|
// get capability references
|
||||||
|
viewRecordsCapability = capabilityService.getCapability(RMPermissionModel.VIEW_RECORDS);
|
||||||
|
editNonRecordMetadataCapability = capabilityService.getCapability(RMPermissionModel.EDIT_NON_RECORD_METADATA);
|
||||||
|
editRecordMetadataCapability = capabilityService.getCapability(RMPermissionModel.EDIT_RECORD_METADATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a document in a collaboration site
|
||||||
|
* When a user without write permissions on the document tries to declare it as a record
|
||||||
|
* Then the declaration fails
|
||||||
|
* And the document does not become a record
|
||||||
|
*/
|
||||||
|
public void testUserWithOutWriteCantDeclareInPlaceRecord()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given()
|
||||||
|
|
||||||
|
// Given a document in a collaboration site that is not a record
|
||||||
|
.expect(false)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("The document is not a record.")
|
||||||
|
|
||||||
|
// And a user with no write permission on the document
|
||||||
|
.as(userName)
|
||||||
|
.expect(AccessStatus.DENIED.toString())
|
||||||
|
.from(() -> permissionService.hasPermission(dmDocument, PermissionService.WRITE).toString())
|
||||||
|
.because("User does not have write access to document.")
|
||||||
|
|
||||||
|
// When the user tries to declare the record
|
||||||
|
// Then we expect this to fail
|
||||||
|
.when()
|
||||||
|
.as(userName)
|
||||||
|
.expectException(AccessDeniedException.class)
|
||||||
|
.from(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
.because("The user does not have write permission on the document.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a document in a collaboration site that is not a record
|
||||||
|
* And a contributor the didn't create the document
|
||||||
|
* When the contributor tries to declare the document as a record
|
||||||
|
* Then the document does not become a record
|
||||||
|
*/
|
||||||
|
public void testContributorThatIsntOwnerDeclareInPlaceRecord()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given()
|
||||||
|
|
||||||
|
// Given a document in a collaboration site that is not a record
|
||||||
|
.expect(false)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("The document is not a record.")
|
||||||
|
|
||||||
|
// And a contributor the didn't create the document
|
||||||
|
.as(dmContributor)
|
||||||
|
.expect(AccessStatus.DENIED.toString())
|
||||||
|
.from(() -> permissionService.hasPermission(dmDocument, PermissionService.WRITE).toString())
|
||||||
|
.because("Contributor does not have write access to document.")
|
||||||
|
|
||||||
|
// When the user tries to declare the record
|
||||||
|
// When the contributor tries to declare the document as a record
|
||||||
|
.when()
|
||||||
|
.as(dmContributor)
|
||||||
|
.expectException(AccessDeniedException.class)
|
||||||
|
.from(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
.because("The contributor does not have write permission on the document.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a document in a collaboration site is not a record
|
||||||
|
* When the document is declared by a site collaborator
|
||||||
|
* Then the document becomes a record
|
||||||
|
* And the site users have the appropriate in-place permissions on the record
|
||||||
|
*/
|
||||||
|
public void testCreateInplaceRecordFromCollabSite()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
|
||||||
|
// Given that a document in a collaboration site is not a record
|
||||||
|
.given()
|
||||||
|
.asAdmin()
|
||||||
|
.expect(false)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("The document is not a record")
|
||||||
|
|
||||||
|
// When it is declared as an inplace record
|
||||||
|
.when()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
|
||||||
|
.then()
|
||||||
|
.asAdmin()
|
||||||
|
// Then it becomes a record
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("The document is a record")
|
||||||
|
|
||||||
|
// And it isn't filed
|
||||||
|
.expect(false)
|
||||||
|
.from(() -> recordService.isFiled(dmDocument))
|
||||||
|
.because("The record is not filed")
|
||||||
|
|
||||||
|
// And a site collaborator has filling permissions and filling capability on the record
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.ALLOWED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.ALLOWED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a site contributor has read and view
|
||||||
|
.as(dmContributor)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a site consumer has read permissions and view record capability on the record
|
||||||
|
.as(dmConsumer)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a user that is not a member of the site has no access to the inplace record
|
||||||
|
.as(userName)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)); // edit record metadata capability
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to check in place access for a user on a record.
|
||||||
|
*/
|
||||||
|
private void checkInPlaceAccess(NodeRef nodeRef, AccessStatus ... accessStatus)
|
||||||
|
{
|
||||||
|
// check permission access
|
||||||
|
assertEquals("Incorrect read record permission access.", accessStatus[0], permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS));
|
||||||
|
assertEquals("Incorrect filling permission access.", accessStatus[1], permissionService.hasPermission(nodeRef, RMPermissionModel.FILING));
|
||||||
|
|
||||||
|
// check capability access
|
||||||
|
Map<Capability, AccessStatus> access = capabilityService.getCapabilitiesAccessState(nodeRef, CAPABILITIES);
|
||||||
|
assertEquals("Incorrect view records capability access", accessStatus[2], access.get(viewRecordsCapability));
|
||||||
|
assertEquals("Incorrect edit non record metadata capability access", accessStatus[3], access.get(editNonRecordMetadataCapability));
|
||||||
|
assertEquals("Incorrect edit record metadata capability access", accessStatus[4], access.get(editRecordMetadataCapability));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that a document is created by contributor
|
||||||
|
* When it is declared as an inplace record
|
||||||
|
* Then it becomes a record
|
||||||
|
* And it isn't filed
|
||||||
|
* And a site collaborator has filling permissions and filling capability on the record
|
||||||
|
* And a site contributor has filling capability and permissions
|
||||||
|
* And a site consumer has read permissions and view record capability on the record
|
||||||
|
* And a user that is not a member of the site has no access to the inplace record
|
||||||
|
*/
|
||||||
|
public void testCreateInplaceRecordFromCollabSiteWhenContribIsCreatorOfDocument()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
|
||||||
|
// Given that a document is created by contributor
|
||||||
|
.given()
|
||||||
|
.as(dmContributor)
|
||||||
|
.perform(() ->
|
||||||
|
{
|
||||||
|
contribDoc = fileFolderService.create(dmFolder, "contrib.txt" , ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
|
dbNodeService.addAspect(contribDoc, ContentModel.ASPECT_AUDITABLE, null);
|
||||||
|
})
|
||||||
|
.expect(false)
|
||||||
|
.from(() -> recordService.isRecord(contribDoc))
|
||||||
|
.because("It is not a record.")
|
||||||
|
.asAdmin()
|
||||||
|
.expect(dmContributor)
|
||||||
|
.from(() -> ownableService.getOwner(contribDoc))
|
||||||
|
.because("As the creator of the document the contributor is also the owner")
|
||||||
|
.as(dmContributor)
|
||||||
|
.expect(AccessStatus.ALLOWED.toString())
|
||||||
|
.from(() -> permissionService.hasPermission(contribDoc, PermissionService.WRITE).toString())
|
||||||
|
.because("Contrib user has write permissions on created document as the owner.")
|
||||||
|
|
||||||
|
// When it is declared as an inplace record
|
||||||
|
.when()
|
||||||
|
.as(dmContributor)
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, contribDoc))
|
||||||
|
|
||||||
|
.then()
|
||||||
|
.asAdmin()
|
||||||
|
// Then it becomes a record
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isRecord(contribDoc))
|
||||||
|
.because("The document is a record")
|
||||||
|
|
||||||
|
// And it isn't filed
|
||||||
|
.expect(false)
|
||||||
|
.from(() -> recordService.isFiled(contribDoc))
|
||||||
|
.because("The record is not filed")
|
||||||
|
|
||||||
|
// And a site collaborator has filling permissions and filling capability on the record
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(contribDoc,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.ALLOWED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.ALLOWED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a site contributor has filling capability and permissions
|
||||||
|
.as(dmContributor)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(contribDoc,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.ALLOWED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.ALLOWED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a site consumer has read permissions and view record capability on the record
|
||||||
|
.as(dmConsumer)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(contribDoc,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a user that is not a member of the site has no access to the inplace record
|
||||||
|
.as(userName)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(contribDoc,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)); // edit record metadata capability
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an unfiled in-place record
|
||||||
|
* When the record is moved to the file plan (ie filed)
|
||||||
|
* Then the site users still have the appropriate in-place permissions on the record
|
||||||
|
*/
|
||||||
|
public void testFileInplaceRecordFromCollabSite() throws Exception
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
|
||||||
|
// Given an unfiled inplace record
|
||||||
|
.given()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("The document is a record.")
|
||||||
|
.expect(false)
|
||||||
|
.from(() -> recordService.isFiled(dmDocument))
|
||||||
|
.because("The record is not filed")
|
||||||
|
|
||||||
|
// When the record is filed
|
||||||
|
.when()
|
||||||
|
.asAdmin()
|
||||||
|
.perform(() -> fileFolderService.move(dmDocument, rmFolder, null))
|
||||||
|
|
||||||
|
.then()
|
||||||
|
|
||||||
|
// Then the record is filed
|
||||||
|
.asAdmin()
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isFiled(dmDocument))
|
||||||
|
.because("The record is filed.")
|
||||||
|
|
||||||
|
// And the collaborator has filling permissions and filling capability on the record
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.ALLOWED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.ALLOWED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a site contributor has read and view
|
||||||
|
.as(dmContributor)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And the consumer has read permissions and view record capability on the record
|
||||||
|
.as(dmConsumer)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a user that is not in the site has no permissions on the record
|
||||||
|
.as(userName)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)); // edit record metadata capability
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an incomplete inplace record
|
||||||
|
* When it is completed
|
||||||
|
* Then the inplace users still have access to the record
|
||||||
|
* And can't edit the records meta-data
|
||||||
|
*/
|
||||||
|
public void testCompletedInPlaceRecord()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
|
||||||
|
// Given an incomplete record
|
||||||
|
.given()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
.expect(false)
|
||||||
|
.from(() -> recordService.isDeclared(dmDocument))
|
||||||
|
.because("Record is not complete.")
|
||||||
|
|
||||||
|
// When it is completed
|
||||||
|
.when()
|
||||||
|
.asAdmin()
|
||||||
|
.perform(() -> rmActionService.executeRecordsManagementAction(dmDocument, DeclareRecordAction.NAME))
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isDeclared(dmDocument))
|
||||||
|
.because("Record is complete.")
|
||||||
|
|
||||||
|
.then()
|
||||||
|
|
||||||
|
// Then the collaborator has filling permissions, view record capability, but not edit non-record metadata
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.ALLOWED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a site contributor has read and view
|
||||||
|
.as(dmContributor)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And the consumer has read permissions and view record capability on the record
|
||||||
|
.as(dmConsumer)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a user that is not in the site has no permissions on the record
|
||||||
|
.as(userName)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)); // edit record metadata capability
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an inplace record ready for destruction
|
||||||
|
* When it is destroyed
|
||||||
|
* And it's metadata is maintained
|
||||||
|
* Then the inplace users will no longer see the record
|
||||||
|
*/
|
||||||
|
public void testDestroyedRecordInplacePermissions()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given()
|
||||||
|
|
||||||
|
// Given that a record is declared by a collaborator
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("Document is a record.")
|
||||||
|
|
||||||
|
// And it is filed into the file plan
|
||||||
|
// And eligible for destruction
|
||||||
|
.asAdmin()
|
||||||
|
.perform(() ->
|
||||||
|
{
|
||||||
|
// create record category and disposition schedule
|
||||||
|
NodeRef recordCategory = filePlanService.createRecordCategory(filePlan, GUID.generate());
|
||||||
|
utils.createBasicDispositionSchedule(recordCategory, GUID.generate(), GUID.generate(), true, true);
|
||||||
|
|
||||||
|
// create record folder and file record
|
||||||
|
NodeRef recordFolder = recordFolderService.createRecordFolder(recordCategory, GUID.generate());
|
||||||
|
fileFolderService.move(dmDocument, recordFolder, null);
|
||||||
|
|
||||||
|
// cut off record
|
||||||
|
rmActionService.executeRecordsManagementAction(dmDocument, DeclareRecordAction.NAME);
|
||||||
|
utils.completeEvent(dmDocument, CommonRMTestUtils.DEFAULT_EVENT_NAME);
|
||||||
|
rmActionService.executeRecordsManagementAction(dmDocument, CutOffAction.NAME);
|
||||||
|
})
|
||||||
|
.expect("destroy")
|
||||||
|
.from(() -> dispositionService.getNextDispositionAction(dmDocument).getName())
|
||||||
|
.because("The next action is destroy.")
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> dispositionService.isNextDispositionActionEligible(dmDocument))
|
||||||
|
.because("The next action is eligible.")
|
||||||
|
|
||||||
|
// When the record is destroyed
|
||||||
|
.when(() -> rmActionService.executeRecordsManagementAction(dmDocument, DestroyAction.NAME))
|
||||||
|
|
||||||
|
.then()
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isMetadataStub(dmDocument))
|
||||||
|
.because("The record has been destroyed and the meta-stub remains.")
|
||||||
|
|
||||||
|
// Then the collaborator has no permissions or capabilities
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a site contributor has no permissions or capabilities
|
||||||
|
.as(dmContributor)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And the consumer has no permissions or capabilities
|
||||||
|
.as(dmConsumer)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a user that is not in the site has no permissions or capabilities
|
||||||
|
.as(userName)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)); // edit record metadata capability
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an inplace record
|
||||||
|
* And the collaborator has view and edit non-record capability
|
||||||
|
* And doesn't have edit record capability
|
||||||
|
* When we add edit record metadata capability to the extended writer role
|
||||||
|
* Then the collaborator now has edit record metadata capability
|
||||||
|
*/
|
||||||
|
public void testAddUserToRole()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
|
||||||
|
// Given an inplace record
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("Document is a record.")
|
||||||
|
|
||||||
|
// And the collaborator has view and edit non-record capability
|
||||||
|
// And doesn't have edit record capability
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.ALLOWED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.ALLOWED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
.when()
|
||||||
|
.asAdmin()
|
||||||
|
|
||||||
|
// When we add edit record metadata capability to the extended writer role
|
||||||
|
.perform(() -> filePlanRoleService.updateRole(filePlan,
|
||||||
|
FilePlanRoleService.ROLE_EXTENDED_WRITERS,
|
||||||
|
"",
|
||||||
|
Stream
|
||||||
|
.of(viewRecordsCapability, editNonRecordMetadataCapability, editRecordMetadataCapability)
|
||||||
|
.collect(Collectors.toSet())))
|
||||||
|
|
||||||
|
.then()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
|
||||||
|
// Then the collaborator now has edit record metadata capability
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.ALLOWED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.ALLOWED, // edit non record metadata capability
|
||||||
|
AccessStatus.ALLOWED)) // edit record metadata capability
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an inplace record
|
||||||
|
* When the record is hidden
|
||||||
|
* Then the collaborator has no access to the record
|
||||||
|
* And the consumer has no access to the record
|
||||||
|
* And a user that is not in the site has no permissions or capabilities
|
||||||
|
*/
|
||||||
|
public void testNoPermissionsAfterHide()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
|
||||||
|
// Given an inplace record
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("Document is a record.")
|
||||||
|
.when()
|
||||||
|
.asAdmin()
|
||||||
|
|
||||||
|
// When the record is hidden
|
||||||
|
.perform(() -> inplaceRecordService.hideRecord(dmDocument))
|
||||||
|
|
||||||
|
.then()
|
||||||
|
|
||||||
|
// Then the collaborator has no access to the record
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a site contributor has read and view
|
||||||
|
.as(dmContributor)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And the consumer has no access to the record
|
||||||
|
.as(dmConsumer)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a user that is not in the site has no permissions or capabilities
|
||||||
|
.as(userName)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)); // edit record metadata capability
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an inplace record
|
||||||
|
* When the record is rejected
|
||||||
|
* Then the collaborator has no access to the record
|
||||||
|
* And the consumer has no access to the record
|
||||||
|
* And a user that is not in the site has no permissions or capabilities
|
||||||
|
*/
|
||||||
|
public void testNoPermissionsAfterReject()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
|
||||||
|
// Given an inplace record
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, dmDocument))
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isRecord(dmDocument))
|
||||||
|
.because("Document is a record.")
|
||||||
|
.when()
|
||||||
|
.asAdmin()
|
||||||
|
|
||||||
|
// When the record is rejected
|
||||||
|
.perform(() -> recordService.rejectRecord(dmDocument, GUID.generate()))
|
||||||
|
|
||||||
|
.then()
|
||||||
|
|
||||||
|
// Then the collaborator has no access to the record
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a site contributor has read and view
|
||||||
|
.as(dmContributor)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And the consumer has no access to the record
|
||||||
|
.as(dmConsumer)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a user that is not in the site has no permissions or capabilities
|
||||||
|
.as(userName)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(dmDocument,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)); // edit record metadata capability
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a user is the cm:creator of a document
|
||||||
|
* And the user is deleted
|
||||||
|
* When the document is declared as a record by a manager
|
||||||
|
* Then it successfully becomes a record
|
||||||
|
*/
|
||||||
|
public void testCmCreatorDeletedBeforeRecordDeclaration()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given()
|
||||||
|
.asAdmin()
|
||||||
|
.perform(() ->
|
||||||
|
{
|
||||||
|
deletedUser = GUID.generate();
|
||||||
|
createPerson(deletedUser);
|
||||||
|
siteService.setMembership(collabSiteId, deletedUser, SiteModel.SITE_CONTRIBUTOR);
|
||||||
|
})
|
||||||
|
.as(deletedUser)
|
||||||
|
.perform(() ->
|
||||||
|
{
|
||||||
|
deleteUserDoc = fileFolderService.create(dmFolder, "deleteUserDoc.txt" , ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
|
dbNodeService.addAspect(deleteUserDoc, ContentModel.ASPECT_AUDITABLE, null);
|
||||||
|
})
|
||||||
|
.asAdmin()
|
||||||
|
.perform(() -> personService.deletePerson(deletedUser))
|
||||||
|
.when()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() -> recordService.createRecord(filePlan, deleteUserDoc))
|
||||||
|
.then()
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> recordService.isRecord(deleteUserDoc))
|
||||||
|
.because("The document is now a record.")
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a document created by the collaborator
|
||||||
|
* And declared as a record by the collaborator
|
||||||
|
* And filed by the records manager
|
||||||
|
* When the records manager copies the record
|
||||||
|
* Then the collaborator has no access to the record copy
|
||||||
|
* And a site contributor has no access to the record copy
|
||||||
|
* And the consumer has no access to the record copy
|
||||||
|
* And a user that is not in the site has no access to the record copy
|
||||||
|
*/
|
||||||
|
public void testNoPermissionsOnCopy()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
{
|
||||||
|
// Given a document created by the collaborator
|
||||||
|
copiedDoc = fileFolderService.create(dmFolder, "copiedDoc.txt" , ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
|
dbNodeService.addAspect(copiedDoc, ContentModel.ASPECT_AUDITABLE, null);
|
||||||
|
|
||||||
|
// And declared as a record by the collaborator
|
||||||
|
recordService.createRecord(filePlan, copiedDoc);
|
||||||
|
})
|
||||||
|
.asAdmin()
|
||||||
|
|
||||||
|
// And filed by the records manager
|
||||||
|
.perform(() -> fileFolderService.move(copiedDoc, rmFolder, null))
|
||||||
|
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(copiedDoc,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.ALLOWED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.ALLOWED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
.when()
|
||||||
|
.asAdmin()
|
||||||
|
|
||||||
|
// When the records manager copies the record
|
||||||
|
.perform(() -> copyDoc = fileFolderService.copy(copiedDoc, rmFolder, "newRecord.txt").getNodeRef())
|
||||||
|
|
||||||
|
.then()
|
||||||
|
|
||||||
|
// Then the collaborator has no access to the record copy
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(copyDoc,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(copiedDoc,
|
||||||
|
AccessStatus.ALLOWED, // read record permission
|
||||||
|
AccessStatus.ALLOWED, // filing permission
|
||||||
|
AccessStatus.ALLOWED, // view record capability
|
||||||
|
AccessStatus.ALLOWED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a site contributor has no access to the record copy
|
||||||
|
.as(dmContributor)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(copyDoc,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And the consumer has no access to the record copy
|
||||||
|
.as(dmConsumer)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(copyDoc,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)) // edit record metadata capability
|
||||||
|
|
||||||
|
// And a user that is not in the site has no access to the record copy
|
||||||
|
.as(userName)
|
||||||
|
.perform(() ->
|
||||||
|
checkInPlaceAccess(copyDoc,
|
||||||
|
AccessStatus.DENIED, // read record permission
|
||||||
|
AccessStatus.DENIED, // filing permission
|
||||||
|
AccessStatus.DENIED, // view record capability
|
||||||
|
AccessStatus.DENIED, // edit non record metadata capability
|
||||||
|
AccessStatus.DENIED)); // edit record metadata capability
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test group reuse
|
||||||
|
*/
|
||||||
|
public void testGroupReuse()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.when()
|
||||||
|
.as(dmCollaborator)
|
||||||
|
.perform(50, () ->
|
||||||
|
{
|
||||||
|
NodeRef newDocument = fileFolderService.create(dmFolder, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
|
recordService.createRecord(filePlan, newDocument);
|
||||||
|
})
|
||||||
|
.as(dmContributor)
|
||||||
|
.perform(50, () ->
|
||||||
|
{
|
||||||
|
NodeRef newDocument = fileFolderService.create(dmFolder, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
|
recordService.createRecord(filePlan, newDocument);
|
||||||
|
})
|
||||||
|
.then()
|
||||||
|
.asAdmin()
|
||||||
|
.expect(101)
|
||||||
|
.from(() -> nodeService.getChildAssocs(dmFolder).size())
|
||||||
|
.because("One hundred inplace records have been created.")
|
||||||
|
.expect(3)
|
||||||
|
.from(() -> authorityService.getContainedAuthorities(null, "GROUP_INPLACE_RECORD_MANAGEMENT", true).size())
|
||||||
|
.because("The read and write groups are reused.");
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test tear down
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void tearDownImpl()
|
||||||
|
{
|
||||||
|
super.tearDownImpl();
|
||||||
|
|
||||||
|
// clear up groups
|
||||||
|
authorityService.getContainedAuthorities(null, "GROUP_INPLACE_RECORD_MANAGEMENT", true)
|
||||||
|
.stream()
|
||||||
|
.forEach((group) -> authorityService.deleteAuthority(group));
|
||||||
|
}
|
||||||
|
}
|
@@ -69,6 +69,9 @@ public class MoveInplaceRecordTest extends BaseRMTestCase
|
|||||||
// Extended Readers/Writers
|
// Extended Readers/Writers
|
||||||
private Set<String> extendedReadersBeforeMove;
|
private Set<String> extendedReadersBeforeMove;
|
||||||
private Set<String> extendedWritersBeforeMove;
|
private Set<String> extendedWritersBeforeMove;
|
||||||
|
|
||||||
|
// primary parent of record
|
||||||
|
private NodeRef primaryParentBeforeMove;
|
||||||
|
|
||||||
public void given()
|
public void given()
|
||||||
{
|
{
|
||||||
@@ -93,8 +96,14 @@ public class MoveInplaceRecordTest extends BaseRMTestCase
|
|||||||
// Check that the document is a record now
|
// Check that the document is a record now
|
||||||
assertTrue(recordService.isRecord(dmDocument));
|
assertTrue(recordService.isRecord(dmDocument));
|
||||||
|
|
||||||
extendedReadersBeforeMove = extendedSecurityService.getExtendedReaders(dmDocument);
|
extendedReadersBeforeMove = extendedSecurityService.getReaders(dmDocument);
|
||||||
extendedWritersBeforeMove = extendedSecurityService.getExtendedWriters(dmDocument);
|
extendedWritersBeforeMove = extendedSecurityService.getWriters(dmDocument);
|
||||||
|
|
||||||
|
// get the primary parent and assert that it's a record management artifact
|
||||||
|
primaryParentBeforeMove = nodeService.getPrimaryParent(dmDocument).getParentRef();
|
||||||
|
assertTrue("Primary parent of newly created should be a records management artifact.",
|
||||||
|
filePlanService.isFilePlanComponent(primaryParentBeforeMove));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void when()
|
public void when()
|
||||||
@@ -114,15 +123,27 @@ public class MoveInplaceRecordTest extends BaseRMTestCase
|
|||||||
|
|
||||||
public void then()
|
public void then()
|
||||||
{
|
{
|
||||||
|
// assert that the document is still a record
|
||||||
|
assertTrue("After move the document should still be a record.",
|
||||||
|
recordService.isRecord(dmDocument));
|
||||||
|
|
||||||
// Check that the source folder is empty now and the destination folder has the document
|
// Check that the source folder is empty now and the destination folder has the document
|
||||||
assertEquals(0, nodeService.getChildAssocs(dmFolder).size());
|
assertEquals(0, nodeService.getChildAssocs(dmFolder).size());
|
||||||
List<ChildAssociationRef> destinationFolderChildAssocs = nodeService.getChildAssocs(destinationDmFolder);
|
List<ChildAssociationRef> destinationFolderChildAssocs = nodeService.getChildAssocs(destinationDmFolder);
|
||||||
assertEquals(1, destinationFolderChildAssocs.size());
|
assertEquals(1, destinationFolderChildAssocs.size());
|
||||||
assertEquals(dmDocument, destinationFolderChildAssocs.get(0).getChildRef());
|
assertEquals(dmDocument, destinationFolderChildAssocs.get(0).getChildRef());
|
||||||
|
|
||||||
|
// Check that the primary parent of the record has remained unchanged
|
||||||
|
NodeRef primaryParentAfterMove = nodeService.getPrimaryParent(dmDocument).getParentRef();
|
||||||
|
assertTrue("Primary parent of record after inplace move should be a records management artifact.",
|
||||||
|
filePlanService.isFilePlanComponent(primaryParentAfterMove));
|
||||||
|
assertEquals("Primary parent of record after inplace move should remain the same.",
|
||||||
|
primaryParentBeforeMove,
|
||||||
|
primaryParentAfterMove);
|
||||||
|
|
||||||
// Check extended readers/writers
|
// Check extended readers/writers
|
||||||
Set<String> extendedReadersAfterMove = extendedSecurityService.getExtendedReaders(dmDocument);
|
Set<String> extendedReadersAfterMove = extendedSecurityService.getReaders(dmDocument);
|
||||||
Set<String> extendedWritersAfterMove = extendedSecurityService.getExtendedWriters(dmDocument);
|
Set<String> extendedWritersAfterMove = extendedSecurityService.getWriters(dmDocument);
|
||||||
|
|
||||||
assertEquals(extendedReadersBeforeMove.size(), extendedReadersAfterMove.size());
|
assertEquals(extendedReadersBeforeMove.size(), extendedReadersAfterMove.size());
|
||||||
assertEquals(extendedWritersBeforeMove.size(), extendedWritersAfterMove.size());
|
assertEquals(extendedWritersBeforeMove.size(), extendedWritersAfterMove.size());
|
||||||
|
@@ -30,6 +30,7 @@ package org.alfresco.module.org_alfresco_module_rm.test.legacy.action;
|
|||||||
import org.alfresco.module.org_alfresco_module_rm.action.impl.FileReportAction;
|
import org.alfresco.module.org_alfresco_module_rm.action.impl.FileReportAction;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.service.cmr.action.Action;
|
import org.alfresco.service.cmr.action.Action;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
@@ -62,6 +63,8 @@ public class FileReportActionTest extends BaseRMTestCase
|
|||||||
|
|
||||||
private void fileReport(final String mimeType)
|
private void fileReport(final String mimeType)
|
||||||
{
|
{
|
||||||
|
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||||
|
|
||||||
// create record folder
|
// create record folder
|
||||||
final NodeRef recordFolder = recordFolderService.createRecordFolder(rmContainer, GUID.generate());
|
final NodeRef recordFolder = recordFolderService.createRecordFolder(rmContainer, GUID.generate());
|
||||||
|
|
||||||
|
@@ -119,24 +119,27 @@ public class FileToActionTest extends BaseRMTestCase
|
|||||||
// create record from document
|
// create record from document
|
||||||
recordService.createRecord(filePlan, dmDocument);
|
recordService.createRecord(filePlan, dmDocument);
|
||||||
|
|
||||||
// check things have gone according to plan
|
|
||||||
assertTrue(recordService.isRecord(dmDocument));
|
|
||||||
assertFalse(recordService.isFiled(dmDocument));
|
|
||||||
|
|
||||||
AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork<Void>()
|
|
||||||
{
|
|
||||||
public Void doWork() throws Exception
|
|
||||||
{
|
|
||||||
// is the unfiled container the primary parent of the filed record
|
|
||||||
NodeRef parent = nodeService.getPrimaryParent(dmDocument).getParentRef();
|
|
||||||
assertEquals(filePlanService.getUnfiledContainer(filePlan), parent);
|
|
||||||
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}});
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void test(Void result) throws Exception
|
||||||
|
{
|
||||||
|
AuthenticationUtil.runAs(() ->
|
||||||
|
{
|
||||||
|
// check things have gone according to plan
|
||||||
|
assertTrue(recordService.isRecord(dmDocument));
|
||||||
|
assertFalse(recordService.isFiled(dmDocument));
|
||||||
|
|
||||||
|
// is the unfiled container the primary parent of the filed record
|
||||||
|
NodeRef parent = nodeService.getPrimaryParent(dmDocument).getParentRef();
|
||||||
|
assertEquals(filePlanService.getUnfiledContainer(filePlan), parent);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
AuthenticationUtil.getAdminUserName());
|
||||||
|
}
|
||||||
|
|
||||||
}, dmCollaborator);
|
}, dmCollaborator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -113,7 +113,8 @@ public class RejectActionTest extends BaseRMTestCase
|
|||||||
assertTrue(nodeService.getParentAssocs(dmDocument).size() == 1);
|
assertTrue(nodeService.getParentAssocs(dmDocument).size() == 1);
|
||||||
|
|
||||||
// The extended reader information should be removed
|
// The extended reader information should be removed
|
||||||
assertNull(extendedSecurityService.getExtendedReaders(dmDocument));
|
assertFalse(extendedSecurityService.hasExtendedSecurity(dmDocument));
|
||||||
|
assertTrue(extendedSecurityService.getReaders(dmDocument).isEmpty());
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -27,9 +27,7 @@
|
|||||||
|
|
||||||
package org.alfresco.module.org_alfresco_module_rm.test.legacy.service;
|
package org.alfresco.module.org_alfresco_module_rm.test.legacy.service;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
@@ -101,64 +99,29 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
|||||||
assertFalse(extendedSecurityService.hasExtendedSecurity(rmFolder));
|
assertFalse(extendedSecurityService.hasExtendedSecurity(rmFolder));
|
||||||
assertFalse(extendedSecurityService.hasExtendedSecurity(record));
|
assertFalse(extendedSecurityService.hasExtendedSecurity(record));
|
||||||
|
|
||||||
assertNull(extendedSecurityService.getExtendedReaders(record));
|
assertTrue(extendedSecurityService.getReaders(record).isEmpty());
|
||||||
assertNull(extendedSecurityService.getExtendedWriters(record));
|
assertTrue(extendedSecurityService.getWriters(record).isEmpty());
|
||||||
|
|
||||||
Set<String> extendedReaders = new HashSet<String>(2);
|
Set<String> extendedReaders = new HashSet<String>(2);
|
||||||
extendedReaders.add(monkey);
|
extendedReaders.add(monkey);
|
||||||
extendedReaders.add(elephant);
|
extendedReaders.add(elephant);
|
||||||
|
|
||||||
extendedSecurityService.addExtendedSecurity(record, extendedReaders, null);
|
extendedSecurityService.set(record, extendedReaders, null);
|
||||||
|
checkExtendedReaders(record, extendedReaders);
|
||||||
Map<String, Integer> testMap = new HashMap<String, Integer>(2);
|
|
||||||
testMap.put(monkey, Integer.valueOf(1));
|
|
||||||
testMap.put(elephant, Integer.valueOf(1));
|
|
||||||
|
|
||||||
checkExtendedReaders(record, testMap);
|
|
||||||
|
|
||||||
Set<String> extendedReadersToo = new HashSet<String>(2);
|
Set<String> extendedReadersToo = new HashSet<String>(2);
|
||||||
extendedReadersToo.add(monkey);
|
extendedReadersToo.add(monkey);
|
||||||
extendedReadersToo.add(snake);
|
extendedReadersToo.add(snake);
|
||||||
|
|
||||||
extendedSecurityService.addExtendedSecurity(recordToo, extendedReadersToo, null);
|
extendedSecurityService.set(recordToo, extendedReadersToo, null);
|
||||||
|
checkExtendedReaders(recordToo, extendedReadersToo);
|
||||||
|
|
||||||
Map<String, Integer> testMapToo = new HashMap<String, Integer>(2);
|
// test remove
|
||||||
testMapToo.put(monkey, Integer.valueOf(1));
|
extendedSecurityService.remove(recordToo);
|
||||||
testMapToo.put(snake, Integer.valueOf(1));
|
|
||||||
|
assertFalse(extendedSecurityService.hasExtendedSecurity(recordToo));
|
||||||
Map<String, Integer> testMapThree = new HashMap<String, Integer>(3);
|
assertTrue(extendedSecurityService.getReaders(recordToo).isEmpty());
|
||||||
testMapThree.put(monkey, Integer.valueOf(2));
|
assertTrue(extendedSecurityService.getWriters(recordToo).isEmpty());
|
||||||
testMapThree.put(elephant, Integer.valueOf(1));
|
|
||||||
testMapThree.put(snake, Integer.valueOf(1));
|
|
||||||
|
|
||||||
checkExtendedReaders(recordToo, testMapToo);
|
|
||||||
|
|
||||||
// test remove (with no parent inheritance)
|
|
||||||
|
|
||||||
Set<String> removeMap1 = new HashSet<String>(2);
|
|
||||||
removeMap1.add(elephant);
|
|
||||||
removeMap1.add(monkey);
|
|
||||||
|
|
||||||
extendedSecurityService.removeExtendedSecurity(rmFolder, removeMap1, null, false);
|
|
||||||
|
|
||||||
Map<String, Integer> testMapFour = new HashMap<String, Integer>(2);
|
|
||||||
testMapFour.put(monkey, Integer.valueOf(1));
|
|
||||||
testMapFour.put(snake, Integer.valueOf(1));
|
|
||||||
|
|
||||||
checkExtendedReaders(recordToo, testMapToo);
|
|
||||||
|
|
||||||
// test remove (apply to parents)
|
|
||||||
|
|
||||||
Set<String> removeMap2 = new HashSet<String>(1);
|
|
||||||
removeMap2.add(snake);
|
|
||||||
|
|
||||||
extendedSecurityService.removeExtendedSecurity(recordToo, removeMap2, null, true);
|
|
||||||
|
|
||||||
testMapThree.remove(snake);
|
|
||||||
testMapFour.remove(snake);
|
|
||||||
testMapToo.remove(snake);
|
|
||||||
|
|
||||||
checkExtendedReaders(recordToo, testMapToo);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -172,12 +135,12 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
|||||||
|
|
||||||
doTestInTransaction(new Test<Void>()
|
doTestInTransaction(new Test<Void>()
|
||||||
{
|
{
|
||||||
Map<String, Integer> testMap = new HashMap<String, Integer>(2);
|
Set<String> extendedReaders = new HashSet<String>(2);;
|
||||||
|
|
||||||
public Void run() throws Exception
|
public Void run() throws Exception
|
||||||
{
|
{
|
||||||
testMap.put(monkey, Integer.valueOf(1));
|
extendedReaders.add(monkey);
|
||||||
testMap.put(elephant, Integer.valueOf(1));
|
extendedReaders.add(elephant);
|
||||||
|
|
||||||
assertFalse(extendedSecurityService.hasExtendedSecurity(filePlan));
|
assertFalse(extendedSecurityService.hasExtendedSecurity(filePlan));
|
||||||
assertFalse(extendedSecurityService.hasExtendedSecurity(rmContainer));
|
assertFalse(extendedSecurityService.hasExtendedSecurity(rmContainer));
|
||||||
@@ -186,15 +149,12 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
|||||||
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordCategory));
|
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordCategory));
|
||||||
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordFolder));
|
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordFolder));
|
||||||
|
|
||||||
assertNull(extendedSecurityService.getExtendedReaders(record));
|
assertTrue(extendedSecurityService.getReaders(record).isEmpty());
|
||||||
|
|
||||||
Set<String> extendedReaders = new HashSet<String>(2);
|
extendedSecurityService.set(record, extendedReaders, null);
|
||||||
extendedReaders.add(monkey);
|
|
||||||
extendedReaders.add(elephant);
|
|
||||||
|
|
||||||
extendedSecurityService.addExtendedSecurity(record, extendedReaders, null);
|
checkExtendedReaders(record, extendedReaders);
|
||||||
|
|
||||||
checkExtendedReaders(record, testMap);
|
|
||||||
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordCategory));
|
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordCategory));
|
||||||
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordFolder));
|
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordFolder));
|
||||||
|
|
||||||
@@ -206,31 +166,21 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
|||||||
@Override
|
@Override
|
||||||
public void test(Void result) throws Exception
|
public void test(Void result) throws Exception
|
||||||
{
|
{
|
||||||
checkExtendedReaders(record, testMap);
|
checkExtendedReaders(record, extendedReaders);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
@SuppressWarnings("unchecked")
|
* Check extended readers helper method
|
||||||
private void checkExtendedReaders(NodeRef nodeRef, Map<String, Integer> testMap)
|
*/
|
||||||
|
private void checkExtendedReaders(NodeRef nodeRef, Set<String> testReaders)
|
||||||
{
|
{
|
||||||
assertTrue(extendedSecurityService.hasExtendedSecurity(nodeRef));
|
assertTrue(extendedSecurityService.hasExtendedSecurity(nodeRef));
|
||||||
|
|
||||||
Map<String, Integer> readersMap = (Map<String,Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
|
Set<String> readers = extendedSecurityService.getReaders(nodeRef);
|
||||||
assertNotNull(readersMap);
|
|
||||||
assertEquals(testMap.size(), readersMap.size());
|
|
||||||
|
|
||||||
for (Map.Entry<String, Integer> entry: testMap.entrySet())
|
|
||||||
{
|
|
||||||
assertTrue(readersMap.containsKey(entry.getKey()));
|
|
||||||
assertEquals(entry.getKey(), entry.getValue(), readersMap.get(entry.getKey()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<String> readers = extendedSecurityService.getExtendedReaders(nodeRef);
|
|
||||||
assertNotNull(readers);
|
assertNotNull(readers);
|
||||||
assertEquals(testMap.size(), readers.size());
|
assertEquals(testReaders, readers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDifferentUsersDifferentPermissions()
|
public void testDifferentUsersDifferentPermissions()
|
||||||
|
@@ -33,8 +33,6 @@ import java.util.Set;
|
|||||||
|
|
||||||
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.role.FilePlanRoleService;
|
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.test.util.BaseRMTestCase;
|
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
@@ -1241,10 +1239,6 @@ public class FilePlanPermissionServiceImplTest extends BaseRMTestCase
|
|||||||
accessPermissions.put(permission.getAuthority(), permission.getPermission());
|
accessPermissions.put(permission.getAuthority(), permission.getPermission());
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(accessPermissions.containsKey(ExtendedReaderDynamicAuthority.EXTENDED_READER));
|
|
||||||
assertEquals(RMPermissionModel.READ_RECORDS, accessPermissions.get(ExtendedReaderDynamicAuthority.EXTENDED_READER));
|
|
||||||
assertTrue(accessPermissions.containsKey(ExtendedWriterDynamicAuthority.EXTENDED_WRITER));
|
|
||||||
assertEquals(RMPermissionModel.FILING, accessPermissions.get(ExtendedWriterDynamicAuthority.EXTENDED_WRITER));
|
|
||||||
String adminRole = authorityService.getName(AuthorityType.GROUP, FilePlanRoleService.ROLE_ADMIN + filePlan.getId());
|
String adminRole = authorityService.getName(AuthorityType.GROUP, FilePlanRoleService.ROLE_ADMIN + filePlan.getId());
|
||||||
assertTrue(accessPermissions.containsKey(adminRole));
|
assertTrue(accessPermissions.containsKey(adminRole));
|
||||||
assertEquals(RMPermissionModel.FILING, accessPermissions.get(adminRole));
|
assertEquals(RMPermissionModel.FILING, accessPermissions.get(adminRole));
|
||||||
|
@@ -38,8 +38,6 @@ 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.model.RecordsManagementModel;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
|
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.role.Role;
|
import org.alfresco.module.org_alfresco_module_rm.role.Role;
|
||||||
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.test.util.BaseRMTestCase;
|
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
@@ -181,22 +179,13 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
|||||||
|
|
||||||
public void testExtendedWriters() throws Exception
|
public void testExtendedWriters() throws Exception
|
||||||
{
|
{
|
||||||
final ExtendedReaderDynamicAuthority readerDy = (ExtendedReaderDynamicAuthority)applicationContext.getBean("extendedReaderDynamicAuthority");
|
|
||||||
final ExtendedWriterDynamicAuthority writerDy = (ExtendedWriterDynamicAuthority)applicationContext.getBean("extendedWriterDynamicAuthority");
|
|
||||||
|
|
||||||
doTestInTransaction(new Test<Void>()
|
doTestInTransaction(new Test<Void>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Void run()
|
public Void run()
|
||||||
{
|
{
|
||||||
assertNull(extendedSecurityService.getExtendedReaders(recordOne));
|
assertTrue(extendedSecurityService.getReaders(recordOne).isEmpty());
|
||||||
assertNull(extendedSecurityService.getExtendedWriters(recordOne));
|
assertTrue(extendedSecurityService.getWriters(recordOne).isEmpty());
|
||||||
|
|
||||||
assertFalse(readerDy.hasAuthority(recordOne, dmCollaborator));
|
|
||||||
assertFalse(writerDy.hasAuthority(recordOne, dmCollaborator));
|
|
||||||
|
|
||||||
assertFalse(readerDy.hasAuthority(filePlan, dmCollaborator));
|
|
||||||
assertFalse(writerDy.hasAuthority(filePlan, dmCollaborator));
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -209,16 +198,9 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
|||||||
{
|
{
|
||||||
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(recordOne, RMPermissionModel.READ_RECORDS));
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(recordOne, RMPermissionModel.READ_RECORDS));
|
||||||
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(recordOne, RMPermissionModel.FILING));
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(recordOne, RMPermissionModel.FILING));
|
||||||
|
|
||||||
assertFalse(readerDy.hasAuthority(recordOne, dmCollaborator));
|
|
||||||
assertFalse(writerDy.hasAuthority(recordOne, dmCollaborator));
|
|
||||||
|
|
||||||
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS));
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS));
|
||||||
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(filePlan, RMPermissionModel.EDIT_NON_RECORD_METADATA));
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(filePlan, RMPermissionModel.EDIT_NON_RECORD_METADATA));
|
||||||
|
|
||||||
assertFalse(readerDy.hasAuthority(filePlan, dmCollaborator));
|
|
||||||
assertFalse(writerDy.hasAuthority(filePlan, dmCollaborator));
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}, dmCollaborator);
|
}, dmCollaborator);
|
||||||
@@ -230,10 +212,10 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
|||||||
{
|
{
|
||||||
Set<String> writers = new HashSet<String>(1);
|
Set<String> writers = new HashSet<String>(1);
|
||||||
writers.add(dmCollaborator);
|
writers.add(dmCollaborator);
|
||||||
extendedSecurityService.addExtendedSecurity(recordOne, null, writers);
|
extendedSecurityService.set(recordOne, null, writers);
|
||||||
|
|
||||||
assertNull(extendedSecurityService.getExtendedReaders(recordOne));
|
assertTrue(extendedSecurityService.getReaders(recordOne).isEmpty());
|
||||||
assertFalse(extendedSecurityService.getExtendedWriters(recordOne).isEmpty());
|
assertFalse(extendedSecurityService.getWriters(recordOne).isEmpty());
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -247,9 +229,7 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
|||||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(recordOne, RMPermissionModel.READ_RECORDS));
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(recordOne, RMPermissionModel.READ_RECORDS));
|
||||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(recordOne, RMPermissionModel.FILING));
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(recordOne, RMPermissionModel.FILING));
|
||||||
|
|
||||||
assertFalse(readerDy.hasAuthority(recordOne, dmCollaborator));
|
// ALLOWED, becuase users have been added to the in-place roles
|
||||||
assertTrue(writerDy.hasAuthority(recordOne, dmCollaborator));
|
|
||||||
|
|
||||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS));
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS));
|
||||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(filePlan, RMPermissionModel.EDIT_NON_RECORD_METADATA));
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(filePlan, RMPermissionModel.EDIT_NON_RECORD_METADATA));
|
||||||
|
|
||||||
@@ -311,7 +291,8 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
|||||||
|
|
||||||
public void test(Void result)
|
public void test(Void result)
|
||||||
{
|
{
|
||||||
checkPermissions(READ_RECORDS, AccessStatus.DENIED, // file plan
|
checkPermissions(READ_RECORDS,
|
||||||
|
AccessStatus.DENIED, // file plan
|
||||||
AccessStatus.DENIED, // unfiled container
|
AccessStatus.DENIED, // unfiled container
|
||||||
AccessStatus.DENIED, // record category
|
AccessStatus.DENIED, // record category
|
||||||
AccessStatus.DENIED, // record folder
|
AccessStatus.DENIED, // record folder
|
||||||
@@ -320,7 +301,8 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
|||||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(filePlan,
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(filePlan,
|
||||||
RMPermissionModel.VIEW_RECORDS));
|
RMPermissionModel.VIEW_RECORDS));
|
||||||
|
|
||||||
checkPermissions(FILING, AccessStatus.DENIED, // file plan
|
checkPermissions(FILING,
|
||||||
|
AccessStatus.DENIED, // file plan
|
||||||
AccessStatus.DENIED, // unfiled container
|
AccessStatus.DENIED, // unfiled container
|
||||||
AccessStatus.DENIED, // record category
|
AccessStatus.DENIED, // record category
|
||||||
AccessStatus.DENIED, // record folder
|
AccessStatus.DENIED, // record folder
|
||||||
|
@@ -423,11 +423,12 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
|
|||||||
@Override
|
@Override
|
||||||
public Object execute() throws Throwable
|
public Object execute() throws Throwable
|
||||||
{
|
{
|
||||||
// As system user
|
|
||||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
|
||||||
|
|
||||||
// Do the tear down
|
// Do the tear down
|
||||||
tearDownImpl();
|
AuthenticationUtil.runAsSystem(() ->
|
||||||
|
{
|
||||||
|
tearDownImpl();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -602,16 +603,21 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
|
|||||||
|
|
||||||
protected void setupTestUsers(final NodeRef filePlan)
|
protected void setupTestUsers(final NodeRef filePlan)
|
||||||
{
|
{
|
||||||
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
AuthenticationUtil.runAs(() ->
|
||||||
{
|
{
|
||||||
@Override
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
||||||
public Object execute() throws Throwable
|
|
||||||
{
|
{
|
||||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
|
@Override
|
||||||
setupTestUsersImpl(filePlan);
|
public Object execute() throws Throwable
|
||||||
return null;
|
{
|
||||||
}
|
setupTestUsersImpl(filePlan);
|
||||||
});
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
AuthenticationUtil.getAdminUserName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -687,20 +693,16 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
|
|||||||
*/
|
*/
|
||||||
protected void setupMultiHierarchyTestData()
|
protected void setupMultiHierarchyTestData()
|
||||||
{
|
{
|
||||||
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
AuthenticationUtil.runAsSystem(() ->
|
||||||
{
|
{
|
||||||
@Override
|
return retryingTransactionHelper.doInTransaction(() ->
|
||||||
public Object execute() throws Throwable
|
{
|
||||||
{
|
// Do setup
|
||||||
// As system user
|
setupMultiHierarchyTestDataImpl();
|
||||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
|
||||||
|
return null;
|
||||||
// Do setup
|
});
|
||||||
setupMultiHierarchyTestDataImpl();
|
});
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -0,0 +1,276 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* 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/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.module.org_alfresco_module_rm.test.util.bdt;
|
||||||
|
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class that provides an simple way to write behaviour integration tests.
|
||||||
|
* <p>
|
||||||
|
* Note that initBehaviourTest() must be called before given() is called.
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
public class BehaviourTest
|
||||||
|
{
|
||||||
|
/** retrying transaction helper */
|
||||||
|
private static RetryingTransactionHelper retryingTransactionHelper;
|
||||||
|
|
||||||
|
/** current execution user */
|
||||||
|
private String asUser = AuthenticationUtil.getAdminUserName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise behaviour tests for execution with retrying transaction helper
|
||||||
|
*
|
||||||
|
* @param retryingTransactionHelper retrying transaction helper
|
||||||
|
*/
|
||||||
|
public static void initBehaviourTests(RetryingTransactionHelper retryingTransactionHelper)
|
||||||
|
{
|
||||||
|
BehaviourTest.retryingTransactionHelper = retryingTransactionHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a test
|
||||||
|
*
|
||||||
|
* @return BehaviourTest new test instance
|
||||||
|
*/
|
||||||
|
public static BehaviourTest test()
|
||||||
|
{
|
||||||
|
return new BehaviourTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to get the retrying transaction helper
|
||||||
|
*
|
||||||
|
* @return RetryingTransactionHelper retrying transaction helper
|
||||||
|
*/
|
||||||
|
/*package*/ RetryingTransactionHelper getRetryingTransactionHelper()
|
||||||
|
{
|
||||||
|
return retryingTransactionHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to get the execution user
|
||||||
|
*
|
||||||
|
* @return String execution user
|
||||||
|
*/
|
||||||
|
/* package*/ String getAsUser()
|
||||||
|
{
|
||||||
|
return asUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to switch the current execution user to admin.
|
||||||
|
*
|
||||||
|
* @return BehaviourTest test instance
|
||||||
|
*/
|
||||||
|
public BehaviourTest asAdmin()
|
||||||
|
{
|
||||||
|
return as(AuthenticationUtil.getAdminUserName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set execution user
|
||||||
|
*
|
||||||
|
* @param asUser execution user
|
||||||
|
* @return BehaviourTest test instance
|
||||||
|
*/
|
||||||
|
public BehaviourTest as(String asUser)
|
||||||
|
{
|
||||||
|
this.asUser = asUser;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given.
|
||||||
|
* <p>
|
||||||
|
* Used to group together given conditions.
|
||||||
|
*
|
||||||
|
* @return BehaviourTest test instance
|
||||||
|
*/
|
||||||
|
public BehaviourTest given()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given.
|
||||||
|
* <p>
|
||||||
|
* Performs work.
|
||||||
|
*
|
||||||
|
* @param given work to do
|
||||||
|
* @return BehaviourTest test instance
|
||||||
|
*/
|
||||||
|
public BehaviourTest given(Work given)
|
||||||
|
{
|
||||||
|
return perform(given);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When.
|
||||||
|
* <p>
|
||||||
|
* Used to group together when actions.
|
||||||
|
*
|
||||||
|
* @return BehaviourTest test instance
|
||||||
|
*/
|
||||||
|
public BehaviourTest when()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When.
|
||||||
|
* <p>
|
||||||
|
* Performs work.
|
||||||
|
*
|
||||||
|
* @param when work to do
|
||||||
|
* @return BehaviourTest test instance
|
||||||
|
*/
|
||||||
|
public BehaviourTest when(Work when)
|
||||||
|
{
|
||||||
|
return perform(when);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Then.
|
||||||
|
* <p>
|
||||||
|
* Used to group together then actions.
|
||||||
|
*
|
||||||
|
* @return BehaviourTest test instance
|
||||||
|
*/
|
||||||
|
public BehaviourTest then()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Then.
|
||||||
|
* <p>
|
||||||
|
* Performs work.
|
||||||
|
*
|
||||||
|
* @param then work to do
|
||||||
|
* @return BehaviourTest test instance
|
||||||
|
*/
|
||||||
|
public BehaviourTest then(Work then)
|
||||||
|
{
|
||||||
|
return perform(then);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expect a value.
|
||||||
|
*
|
||||||
|
* @param value value
|
||||||
|
* @return ExpectedValue expected value evaluator
|
||||||
|
*/
|
||||||
|
public ExpectedValue<Boolean> expect(boolean value)
|
||||||
|
{
|
||||||
|
return new ExpectedValue<Boolean>(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expect a value.
|
||||||
|
*
|
||||||
|
* @param value value
|
||||||
|
* @return ExpectedValue expected value evaluator
|
||||||
|
*/
|
||||||
|
public ExpectedValue<String> expect(String value)
|
||||||
|
{
|
||||||
|
return new ExpectedValue<String>(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expect a value.
|
||||||
|
*
|
||||||
|
* @param value value
|
||||||
|
* @return ExpectedValue expected value evaluator
|
||||||
|
*/
|
||||||
|
public ExpectedValue<Object> expect(Object value)
|
||||||
|
{
|
||||||
|
return new ExpectedValue<Object>(this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expect a failure.
|
||||||
|
*
|
||||||
|
* @param exceptionClass expected exception
|
||||||
|
* @return ExpectedFailure expected failure evaluator
|
||||||
|
*/
|
||||||
|
public ExpectedFailure expectException(Class<? extends Exception> exceptionClass)
|
||||||
|
{
|
||||||
|
return new ExpectedFailure(this, exceptionClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform work a number of times
|
||||||
|
*
|
||||||
|
* @param count number of times to perform the work
|
||||||
|
* @param work work to perform
|
||||||
|
* @return BehaviourTest test instance
|
||||||
|
*/
|
||||||
|
public BehaviourTest perform(int count, Work work)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
perform(work);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform work
|
||||||
|
*
|
||||||
|
* @param work work to perform
|
||||||
|
* @return BehaviourTest test instance
|
||||||
|
*/
|
||||||
|
public BehaviourTest perform(Work work)
|
||||||
|
{
|
||||||
|
return AuthenticationUtil.runAs(() ->
|
||||||
|
{
|
||||||
|
return retryingTransactionHelper.doInTransaction(() ->
|
||||||
|
{
|
||||||
|
work.doIt();
|
||||||
|
return this;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
this.asUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Work Interface
|
||||||
|
*/
|
||||||
|
public interface Work
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Do the work.
|
||||||
|
*/
|
||||||
|
void doIt() throws Exception;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* 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/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.module.org_alfresco_module_rm.test.util.bdt;
|
||||||
|
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.bdt.BehaviourTest.Work;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected failure.
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
public class ExpectedFailure
|
||||||
|
{
|
||||||
|
private static final String MESSAGE = "Expected failure \"{0}\" was not observed.";
|
||||||
|
|
||||||
|
private BehaviourTest test;
|
||||||
|
private Set<Class<? extends Exception>> exceptionClasses;
|
||||||
|
private Work work;
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public ExpectedFailure(BehaviourTest test, Class<? extends Exception> ...exceptionClasses)
|
||||||
|
{
|
||||||
|
this.test = test;
|
||||||
|
this.exceptionClasses = Arrays.stream(exceptionClasses).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExpectedFailure from(Work work)
|
||||||
|
{
|
||||||
|
this.work = work;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BehaviourTest because(String message)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
test.perform(work);
|
||||||
|
}
|
||||||
|
catch(Exception actualException)
|
||||||
|
{
|
||||||
|
boolean found = false;
|
||||||
|
|
||||||
|
for (Class<? extends Exception> exceptionClass : exceptionClasses)
|
||||||
|
{
|
||||||
|
if (exceptionClass.isAssignableFrom(actualException.getClass()))
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
fail(MessageFormat.format(MESSAGE, message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* 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/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.module.org_alfresco_module_rm.test.util.bdt;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected value.
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
public class ExpectedValue<T>
|
||||||
|
{
|
||||||
|
private static final String MESSAGE = "Expected value outcome \"{0}\" was not observed.";
|
||||||
|
|
||||||
|
private T expectedValue;
|
||||||
|
private Evaluation<T> evaluation;
|
||||||
|
private BehaviourTest test;
|
||||||
|
|
||||||
|
public ExpectedValue(BehaviourTest test, T value)
|
||||||
|
{
|
||||||
|
this.expectedValue = value;
|
||||||
|
this.test = test;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExpectedValue<T> from(Evaluation<T> evaluation)
|
||||||
|
{
|
||||||
|
this.evaluation = evaluation;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BehaviourTest because(String message)
|
||||||
|
{
|
||||||
|
T actualValue = (T)AuthenticationUtil.runAs(() ->
|
||||||
|
{
|
||||||
|
return test.getRetryingTransactionHelper().doInTransaction(() ->
|
||||||
|
{
|
||||||
|
return evaluation.eval();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
test.getAsUser());
|
||||||
|
|
||||||
|
if (message != null)
|
||||||
|
{
|
||||||
|
message = MessageFormat.format(MESSAGE, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(message, expectedValue, actualValue);
|
||||||
|
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Evaluation<T>
|
||||||
|
{
|
||||||
|
T eval() throws Exception;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,928 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* 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/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||||
|
|
||||||
|
import static org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityServiceImpl.READER_GROUP_PREFIX;
|
||||||
|
import static org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityServiceImpl.ROOT_IPR_GROUP;
|
||||||
|
import static org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityServiceImpl.WRITER_GROUP_PREFIX;
|
||||||
|
import static org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock.generateText;
|
||||||
|
import static org.alfresco.service.cmr.security.PermissionService.GROUP_PREFIX;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anySet;
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.alfresco.model.RenditionModel;
|
||||||
|
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.role.FilePlanRoleService;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock;
|
||||||
|
import org.alfresco.query.PagingRequest;
|
||||||
|
import org.alfresco.query.PagingResults;
|
||||||
|
import org.alfresco.repo.security.authority.RMAuthority;
|
||||||
|
import org.alfresco.repo.security.permissions.impl.AccessPermissionImpl;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
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.AccessPermission;
|
||||||
|
import org.alfresco.service.cmr.security.AccessStatus;
|
||||||
|
import org.alfresco.service.cmr.security.AuthorityService;
|
||||||
|
import org.alfresco.service.cmr.security.AuthorityType;
|
||||||
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
|
import org.mockito.stubbing.Answer;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extended security service implementation unit test.
|
||||||
|
*
|
||||||
|
* @author Roy Wetherall
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
public class ExtendedSecurityServiceImplUnitTest
|
||||||
|
{
|
||||||
|
/** service mocks*/
|
||||||
|
@Mock private FilePlanService mockedFilePlanService;
|
||||||
|
@Mock private FilePlanRoleService mockedFilePlanRoleService;
|
||||||
|
@Mock private AuthorityService mockedAuthorityService;
|
||||||
|
@Mock private PermissionService mockedPermissionService;
|
||||||
|
@Mock private TransactionService mockedTransactionService;
|
||||||
|
@Mock private RetryingTransactionHelper mockedRetryingTransactionHelper;
|
||||||
|
@Mock private NodeService mockedNodeService;
|
||||||
|
@Mock private PagingResults<String> mockedReadPagingResults;
|
||||||
|
@Mock private PagingResults<String> mockedWritePagingResults;
|
||||||
|
@Mock private ApplicationContext mockedApplicationContext;
|
||||||
|
@Mock private ChildAssociationRef mockedChildAssociationRef;
|
||||||
|
|
||||||
|
/** test component */
|
||||||
|
@InjectMocks private ExtendedSecurityServiceImpl extendedSecurityService;
|
||||||
|
|
||||||
|
/** read/write group full names */
|
||||||
|
private static final String READER_GROUP_FULL_PREFIX = GROUP_PREFIX + READER_GROUP_PREFIX;
|
||||||
|
private static final String WRITER_GROUP_FULL_PREFIX = GROUP_PREFIX + WRITER_GROUP_PREFIX;
|
||||||
|
|
||||||
|
/** test authorities */
|
||||||
|
private static final String USER = "USER";
|
||||||
|
private static final String GROUP = GROUP_PREFIX + "GROUP";
|
||||||
|
private static final String USER_W = "USER_W";
|
||||||
|
private static final String GROUP_W = GROUP_PREFIX + "GROUP_W";
|
||||||
|
private static final Set<String> READERS = Stream.of(USER, GROUP).collect(Collectors.toSet());
|
||||||
|
private static final Set<String> WRITERS = Stream.of(USER_W, GROUP_W).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
/** has extended security permission set */
|
||||||
|
private static final Set<AccessPermission> HAS_EXTENDED_SECURITY = Stream
|
||||||
|
.of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, READER_GROUP_FULL_PREFIX, 0),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 1),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, WRITER_GROUP_FULL_PREFIX, 2))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
/** has no extended security permission set */
|
||||||
|
private static final Set<AccessPermission> HAS_NO_EXTENDED_SECURITY = Stream
|
||||||
|
.of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 0),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 1),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 2))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
/** test data */
|
||||||
|
private NodeRef nodeRef;
|
||||||
|
private NodeRef filePlan;
|
||||||
|
private String readGroupPrefix;
|
||||||
|
private String writeGroupPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Before tests
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Before public void before()
|
||||||
|
{
|
||||||
|
// initialise mocks
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
|
// setup node
|
||||||
|
nodeRef = AlfMock.generateNodeRef(mockedNodeService);
|
||||||
|
|
||||||
|
// setup file plan
|
||||||
|
filePlan = AlfMock.generateNodeRef(mockedNodeService);
|
||||||
|
when(mockedFilePlanService.getFilePlan(any(NodeRef.class)))
|
||||||
|
.thenReturn(filePlan);
|
||||||
|
|
||||||
|
// set-up application context
|
||||||
|
when(mockedApplicationContext.getBean("dbNodeService"))
|
||||||
|
.thenReturn(mockedNodeService);
|
||||||
|
|
||||||
|
// setup retrying transaction helper
|
||||||
|
Answer<Object> doInTransactionAnswer = new Answer<Object>()
|
||||||
|
{
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Override
|
||||||
|
public Object answer(InvocationOnMock invocation) throws Throwable
|
||||||
|
{
|
||||||
|
RetryingTransactionCallback callback = (RetryingTransactionCallback)invocation.getArguments()[0];
|
||||||
|
return callback.execute();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
doAnswer(doInTransactionAnswer)
|
||||||
|
.when(mockedRetryingTransactionHelper)
|
||||||
|
.<Object>doInTransaction(any(RetryingTransactionCallback.class));
|
||||||
|
when(mockedTransactionService.getRetryingTransactionHelper())
|
||||||
|
.thenReturn(mockedRetryingTransactionHelper);
|
||||||
|
|
||||||
|
// setup create authority
|
||||||
|
Answer<String> createAuthorityAnswer = new Answer<String>()
|
||||||
|
{
|
||||||
|
public String answer(InvocationOnMock invocation) throws Throwable
|
||||||
|
{
|
||||||
|
return PermissionService.GROUP_PREFIX + (String)invocation.getArguments()[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
when(mockedAuthorityService.createAuthority(any(AuthorityType.class), anyString(), anyString(), anySet()))
|
||||||
|
.thenAnswer(createAuthorityAnswer);
|
||||||
|
|
||||||
|
// setup group prefixes
|
||||||
|
readGroupPrefix = extendedSecurityService.getIPRGroupPrefixShortName(READER_GROUP_PREFIX, READERS);
|
||||||
|
writeGroupPrefix = extendedSecurityService.getIPRGroupPrefixShortName(WRITER_GROUP_PREFIX, WRITERS);
|
||||||
|
|
||||||
|
// make sure the users and groups exist
|
||||||
|
Stream
|
||||||
|
.of(USER, USER_W, GROUP, GROUP_W)
|
||||||
|
.forEach((a) ->
|
||||||
|
when(mockedAuthorityService.authorityExists(a))
|
||||||
|
.thenReturn(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that the root authority does not exist
|
||||||
|
* When the application context is refreshed
|
||||||
|
* Then the root authority is created
|
||||||
|
*/
|
||||||
|
@Test public void rootAuthorityDoesNotExist()
|
||||||
|
{
|
||||||
|
// group doesn't exist
|
||||||
|
when(mockedAuthorityService.authorityExists(GROUP_PREFIX + ExtendedSecurityServiceImpl.ROOT_IPR_GROUP))
|
||||||
|
.thenReturn(false);
|
||||||
|
|
||||||
|
// refresh context
|
||||||
|
extendedSecurityService.onApplicationEvent(mock(ContextRefreshedEvent.class));
|
||||||
|
|
||||||
|
// verify group is created
|
||||||
|
verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, ROOT_IPR_GROUP, ROOT_IPR_GROUP, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that the root authority exists
|
||||||
|
* When the application context is refreshed
|
||||||
|
* Then nothing happens
|
||||||
|
*/
|
||||||
|
@Test public void rootAuthorityDoesExist()
|
||||||
|
{
|
||||||
|
// group doesn't exist
|
||||||
|
when(mockedAuthorityService.authorityExists(GROUP_PREFIX + ROOT_IPR_GROUP))
|
||||||
|
.thenReturn(true);
|
||||||
|
|
||||||
|
// refresh context
|
||||||
|
extendedSecurityService.onApplicationEvent(mock(ContextRefreshedEvent.class));
|
||||||
|
|
||||||
|
// verify group is created
|
||||||
|
verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, ROOT_IPR_GROUP, ROOT_IPR_GROUP, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that an IPR read group has read on a node
|
||||||
|
* And that an IPR write group has filling on a node
|
||||||
|
* When checking for the existence of extended permissions on that node
|
||||||
|
* Then it will be confirmed
|
||||||
|
*/
|
||||||
|
@Test public void hasExtendedSecurityWithReadAndWriteGroups()
|
||||||
|
{
|
||||||
|
// setup permissions
|
||||||
|
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||||
|
.thenReturn(HAS_EXTENDED_SECURITY);
|
||||||
|
|
||||||
|
// has extended security
|
||||||
|
assertTrue(extendedSecurityService.hasExtendedSecurity(nodeRef));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that there is no IPR read group has read on a node
|
||||||
|
* When checking for the existence of extended permissions on that node
|
||||||
|
* Then it will be denied
|
||||||
|
*/
|
||||||
|
@Test public void hasExtendedSecurityWithNoReadGroup()
|
||||||
|
{
|
||||||
|
// setup permissions
|
||||||
|
Set<AccessPermission> permissions = Stream
|
||||||
|
.of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 0),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 1),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, GROUP_PREFIX + WRITER_GROUP_PREFIX, 2))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||||
|
.thenReturn(permissions);
|
||||||
|
|
||||||
|
// has extended security
|
||||||
|
assertFalse(extendedSecurityService.hasExtendedSecurity(nodeRef));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that there is no IPR write group has read on a node
|
||||||
|
* When checking for the existence of extended permissions on that node
|
||||||
|
* Then it will be denied
|
||||||
|
*/
|
||||||
|
@Test public void hasExtendedSecurityWithNoWriteGroup()
|
||||||
|
{
|
||||||
|
// setup permissions
|
||||||
|
Set<AccessPermission> permissions = Stream
|
||||||
|
.of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, GROUP_PREFIX + READER_GROUP_PREFIX, 0),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 1),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 2))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||||
|
.thenReturn(permissions);
|
||||||
|
|
||||||
|
// has extended security
|
||||||
|
assertFalse(extendedSecurityService.hasExtendedSecurity(nodeRef));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that an IPR read group has no groups assigned permission
|
||||||
|
* When checking for the existence of extended permissions on that node
|
||||||
|
* Then it will be denied
|
||||||
|
*/
|
||||||
|
@Test public void hasExtendedSecurityWithNoAssignedGroups()
|
||||||
|
{
|
||||||
|
// setup permissions
|
||||||
|
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||||
|
.thenReturn(HAS_NO_EXTENDED_SECURITY);
|
||||||
|
|
||||||
|
// has extended security
|
||||||
|
assertFalse(extendedSecurityService.hasExtendedSecurity(nodeRef));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that there are no IPR groups assigned
|
||||||
|
* When I try and get the extended readers
|
||||||
|
* The I will get an empty set
|
||||||
|
*/
|
||||||
|
@Test public void getExtendedReadersNoIPRGroupsAssigned()
|
||||||
|
{
|
||||||
|
// setup permissions
|
||||||
|
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||||
|
.thenReturn(HAS_NO_EXTENDED_SECURITY);
|
||||||
|
|
||||||
|
// get extended readers
|
||||||
|
assertTrue(extendedSecurityService.getReaders(nodeRef).isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that there are IPR groups assigned
|
||||||
|
* When I try and get the extended readers
|
||||||
|
* The I will get the set of readers
|
||||||
|
*/
|
||||||
|
@Test public void getExtendedReaders()
|
||||||
|
{
|
||||||
|
// setup permissions
|
||||||
|
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||||
|
.thenReturn(HAS_EXTENDED_SECURITY);
|
||||||
|
|
||||||
|
when(mockedAuthorityService.getContainedAuthorities(null, READER_GROUP_FULL_PREFIX, true))
|
||||||
|
.thenReturn(Stream
|
||||||
|
.of(USER, GROUP)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
|
||||||
|
// get extended readers
|
||||||
|
Set<String> extendedReaders = extendedSecurityService.getReaders(nodeRef);
|
||||||
|
assertEquals(Stream
|
||||||
|
.of(USER, GROUP)
|
||||||
|
.collect(Collectors.toSet()),
|
||||||
|
extendedReaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that there are no IPR groups assigned
|
||||||
|
* When I try and get the extended writers
|
||||||
|
* The I will get an empty set
|
||||||
|
*/
|
||||||
|
@Test public void getExtendedWritersNoIPRGroupsAssigned()
|
||||||
|
{
|
||||||
|
// setup permissions
|
||||||
|
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||||
|
.thenReturn(HAS_NO_EXTENDED_SECURITY);
|
||||||
|
|
||||||
|
// get extended writers
|
||||||
|
assertTrue(extendedSecurityService.getWriters(nodeRef).isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that there are IPR groups assigned
|
||||||
|
* When I try and get the extended writers
|
||||||
|
* The I will get the set of writers
|
||||||
|
*/
|
||||||
|
@Test public void getExtendedWriters()
|
||||||
|
{
|
||||||
|
// setup permissions
|
||||||
|
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||||
|
.thenReturn(HAS_EXTENDED_SECURITY);
|
||||||
|
|
||||||
|
when(mockedAuthorityService.getContainedAuthorities(null, WRITER_GROUP_FULL_PREFIX, true))
|
||||||
|
.thenReturn(Stream
|
||||||
|
.of(USER, GROUP)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
|
||||||
|
// get extended writers
|
||||||
|
Set<String> extendedWriters = extendedSecurityService.getWriters(nodeRef);
|
||||||
|
assertEquals(Stream
|
||||||
|
.of(USER, GROUP)
|
||||||
|
.collect(Collectors.toSet()),
|
||||||
|
extendedWriters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a node with no previous IPR groups assigned
|
||||||
|
* And no IPR group matching authorities
|
||||||
|
* When I add some read and write authorities
|
||||||
|
* Then new IPR groups are created
|
||||||
|
* And they are assigned to the node
|
||||||
|
* And they are added to the RM roles
|
||||||
|
*/
|
||||||
|
@Test public void addExtendedSecurityForTheFirstTimeAndCreateGroups()
|
||||||
|
{
|
||||||
|
// group names
|
||||||
|
String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_PREFIX, READERS, 0);
|
||||||
|
String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_PREFIX, WRITERS, 0);
|
||||||
|
|
||||||
|
// setup query results
|
||||||
|
when(mockedReadPagingResults.getPage())
|
||||||
|
.thenReturn(Collections.emptyList());
|
||||||
|
when(mockedAuthorityService.getAuthorities(
|
||||||
|
eq(AuthorityType.GROUP),
|
||||||
|
eq(RMAuthority.ZONE_APP_RM),
|
||||||
|
any(String.class),
|
||||||
|
eq(false),
|
||||||
|
eq(false),
|
||||||
|
any(PagingRequest.class)))
|
||||||
|
.thenReturn(mockedReadPagingResults);
|
||||||
|
|
||||||
|
// add extended security
|
||||||
|
extendedSecurityService.set(nodeRef, READERS, WRITERS);
|
||||||
|
|
||||||
|
// verify no old permissions needing to be cleared
|
||||||
|
verify(mockedPermissionService, never()).clearPermission(eq(nodeRef), anyString());
|
||||||
|
|
||||||
|
// verify read group created correctly
|
||||||
|
verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, readGroup, readGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
readGroup = GROUP_PREFIX + readGroup;
|
||||||
|
verify(mockedAuthorityService).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, readGroup);
|
||||||
|
verify(mockedAuthorityService).addAuthority(readGroup, USER);
|
||||||
|
verify(mockedAuthorityService).addAuthority(readGroup, GROUP);
|
||||||
|
|
||||||
|
// verify write group created correctly
|
||||||
|
verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, writeGroup, writeGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
writeGroup = GROUP_PREFIX + writeGroup;
|
||||||
|
verify(mockedAuthorityService).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, writeGroup);
|
||||||
|
verify(mockedAuthorityService).addAuthority(writeGroup, USER_W);
|
||||||
|
verify(mockedAuthorityService).addAuthority(writeGroup, GROUP_W);
|
||||||
|
|
||||||
|
// verify groups assigned to RM roles
|
||||||
|
verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, readGroup);
|
||||||
|
verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, writeGroup);
|
||||||
|
|
||||||
|
// verify permissions are assigned to node
|
||||||
|
verify(mockedPermissionService).setPermission(nodeRef, readGroup, RMPermissionModel.READ_RECORDS, true);
|
||||||
|
verify(mockedPermissionService).setPermission(nodeRef, writeGroup, RMPermissionModel.FILING, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a node with no previous IPR groups assigned
|
||||||
|
* And existing IPR groups matching
|
||||||
|
* When I add some read and write authorities
|
||||||
|
* Then the existing IPR groups are used
|
||||||
|
* And they are assigned to the node
|
||||||
|
* And do not not need to be re-added to the RM roles
|
||||||
|
*/
|
||||||
|
@Test public void addExtendedSecurityForTheFirstTimeAndReuseGroups()
|
||||||
|
{
|
||||||
|
// group names
|
||||||
|
String readGroup = readGroupPrefix + "0";
|
||||||
|
String writeGroup = writeGroupPrefix + "0";
|
||||||
|
|
||||||
|
// setup query results
|
||||||
|
when(mockedReadPagingResults.getPage())
|
||||||
|
.thenReturn(Stream.of(GROUP_PREFIX + readGroup).collect(Collectors.toList()));
|
||||||
|
when(mockedAuthorityService.getAuthorities(
|
||||||
|
eq(AuthorityType.GROUP),
|
||||||
|
eq(RMAuthority.ZONE_APP_RM),
|
||||||
|
eq(readGroupPrefix),
|
||||||
|
eq(false),
|
||||||
|
eq(false),
|
||||||
|
any(PagingRequest.class)))
|
||||||
|
.thenReturn(mockedReadPagingResults);
|
||||||
|
|
||||||
|
when(mockedWritePagingResults.getPage())
|
||||||
|
.thenReturn(Stream.of(GROUP_PREFIX + writeGroup).collect(Collectors.toList()));
|
||||||
|
when(mockedAuthorityService.getAuthorities(
|
||||||
|
eq(AuthorityType.GROUP),
|
||||||
|
eq(RMAuthority.ZONE_APP_RM),
|
||||||
|
eq(writeGroupPrefix),
|
||||||
|
eq(false),
|
||||||
|
eq(false),
|
||||||
|
any(PagingRequest.class)))
|
||||||
|
.thenReturn(mockedWritePagingResults);
|
||||||
|
|
||||||
|
// setup exact match
|
||||||
|
when(mockedAuthorityService.authorityExists(GROUP_PREFIX + writeGroup))
|
||||||
|
.thenReturn(true);
|
||||||
|
when(mockedAuthorityService.getContainedAuthorities(null, GROUP_PREFIX + readGroup, true))
|
||||||
|
.thenReturn(Stream
|
||||||
|
.of(USER, GROUP)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
when(mockedAuthorityService.getContainedAuthorities(null, GROUP_PREFIX + writeGroup, true))
|
||||||
|
.thenReturn(Stream
|
||||||
|
.of(USER_W, GROUP_W)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
|
||||||
|
// add extended security
|
||||||
|
extendedSecurityService.set(nodeRef, READERS, WRITERS);
|
||||||
|
|
||||||
|
// verify no old permissions needing to be cleared
|
||||||
|
verify(mockedPermissionService, never()).clearPermission(eq(nodeRef), anyString());
|
||||||
|
|
||||||
|
// verify read group is not recreated
|
||||||
|
verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, readGroup, readGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
readGroup = GROUP_PREFIX + readGroup;
|
||||||
|
verify(mockedAuthorityService, never()).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, readGroup);
|
||||||
|
verify(mockedAuthorityService, never()).addAuthority(readGroup, USER);
|
||||||
|
verify(mockedAuthorityService, never()).addAuthority(readGroup, GROUP);
|
||||||
|
|
||||||
|
// verify write group is not recreated
|
||||||
|
verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, writeGroup, writeGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
writeGroup = GROUP_PREFIX + writeGroup;
|
||||||
|
verify(mockedAuthorityService, never()).addAuthority(readGroup, writeGroup);
|
||||||
|
verify(mockedAuthorityService, never()).addAuthority(writeGroup, USER_W);
|
||||||
|
verify(mockedAuthorityService, never()).addAuthority(writeGroup, GROUP_W);
|
||||||
|
|
||||||
|
// verify groups assigned to RM roles
|
||||||
|
verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, readGroup);
|
||||||
|
verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, writeGroup);
|
||||||
|
|
||||||
|
// verify permissions are assigned to node
|
||||||
|
verify(mockedPermissionService).setPermission(nodeRef, readGroup, RMPermissionModel.READ_RECORDS, true);
|
||||||
|
verify(mockedPermissionService).setPermission(nodeRef, writeGroup, RMPermissionModel.FILING, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a node with no previous IPR groups assigned
|
||||||
|
* And existing IPR groups matches existing has, but not exact match
|
||||||
|
* When I add some read and write authorities
|
||||||
|
* Then new groups are created
|
||||||
|
* And they are assigned to the node
|
||||||
|
* And added to the RM roles
|
||||||
|
*/
|
||||||
|
@Test public void addExtendedSecurityForTheFirstTimeAndCreateGroupsAfterClash()
|
||||||
|
{
|
||||||
|
// group names
|
||||||
|
String readGroup = readGroupPrefix + "0";
|
||||||
|
String writeGroup = writeGroupPrefix + "0";
|
||||||
|
|
||||||
|
// setup query results
|
||||||
|
when(mockedReadPagingResults.getPage())
|
||||||
|
.thenReturn(Stream.of(GROUP_PREFIX + readGroup).collect(Collectors.toList()));
|
||||||
|
when(mockedAuthorityService.getAuthorities(
|
||||||
|
eq(AuthorityType.GROUP),
|
||||||
|
eq(RMAuthority.ZONE_APP_RM),
|
||||||
|
eq(readGroupPrefix),
|
||||||
|
eq(false),
|
||||||
|
eq(false),
|
||||||
|
any(PagingRequest.class)))
|
||||||
|
.thenReturn(mockedReadPagingResults);
|
||||||
|
|
||||||
|
when(mockedWritePagingResults.getPage())
|
||||||
|
.thenReturn(Stream.of(GROUP_PREFIX + writeGroup).collect(Collectors.toList()));
|
||||||
|
when(mockedAuthorityService.getAuthorities(
|
||||||
|
eq(AuthorityType.GROUP),
|
||||||
|
eq(RMAuthority.ZONE_APP_RM),
|
||||||
|
eq(writeGroupPrefix),
|
||||||
|
eq(false),
|
||||||
|
eq(false),
|
||||||
|
any(PagingRequest.class)))
|
||||||
|
.thenReturn(mockedWritePagingResults);
|
||||||
|
|
||||||
|
// setup exact match
|
||||||
|
when(mockedAuthorityService.authorityExists(GROUP_PREFIX + writeGroup))
|
||||||
|
.thenReturn(true);
|
||||||
|
when(mockedAuthorityService.getContainedAuthorities(null, GROUP_PREFIX + readGroup, true))
|
||||||
|
.thenReturn(Stream
|
||||||
|
.of(USER, GROUP, AlfMock.generateText())
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
when(mockedAuthorityService.getContainedAuthorities(null, GROUP_PREFIX + writeGroup, true))
|
||||||
|
.thenReturn(Stream
|
||||||
|
.of(USER_W, AlfMock.generateText())
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
|
||||||
|
// add extended security
|
||||||
|
extendedSecurityService.set(nodeRef, READERS, WRITERS);
|
||||||
|
|
||||||
|
// verify no old permissions needing to be cleared
|
||||||
|
verify(mockedPermissionService, never()).clearPermission(eq(nodeRef), anyString());
|
||||||
|
|
||||||
|
// new group names
|
||||||
|
readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_PREFIX, READERS, 1);
|
||||||
|
writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_PREFIX, WRITERS, 1);
|
||||||
|
|
||||||
|
// verify read group created correctly
|
||||||
|
verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, readGroup, readGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
readGroup = GROUP_PREFIX + readGroup;
|
||||||
|
verify(mockedAuthorityService).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, readGroup);
|
||||||
|
verify(mockedAuthorityService).addAuthority(readGroup, USER);
|
||||||
|
verify(mockedAuthorityService).addAuthority(readGroup, GROUP);
|
||||||
|
|
||||||
|
// verify write group created correctly
|
||||||
|
verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, writeGroup, writeGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
writeGroup = GROUP_PREFIX + writeGroup;
|
||||||
|
verify(mockedAuthorityService).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, writeGroup);
|
||||||
|
verify(mockedAuthorityService).addAuthority(writeGroup, USER_W);
|
||||||
|
verify(mockedAuthorityService).addAuthority(writeGroup, GROUP_W);
|
||||||
|
|
||||||
|
// verify groups assigned to RM roles
|
||||||
|
verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, readGroup);
|
||||||
|
verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, writeGroup);
|
||||||
|
|
||||||
|
// verify permissions are assigned to node
|
||||||
|
verify(mockedPermissionService).setPermission(nodeRef, readGroup, RMPermissionModel.READ_RECORDS, true);
|
||||||
|
verify(mockedPermissionService).setPermission(nodeRef, writeGroup, RMPermissionModel.FILING, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a node with no previous IPR groups assigned
|
||||||
|
* And existing IPR groups matching, but found on second page of find results
|
||||||
|
* When I add some read and write authorities
|
||||||
|
* Then the existing IPR groups are used
|
||||||
|
* And they are assigned to the node
|
||||||
|
* And do not not need to be re-added to the RM roles
|
||||||
|
*/
|
||||||
|
@Test public void addExtendedSecurityWithResultPaging()
|
||||||
|
{
|
||||||
|
// group names
|
||||||
|
String readGroup = readGroupPrefix + "0";
|
||||||
|
String writeGroup = writeGroupPrefix + "0";
|
||||||
|
|
||||||
|
// create fity results
|
||||||
|
List<String> fiftyResults = new ArrayList<String>(50);
|
||||||
|
for (int i = 0; i < 50; i++)
|
||||||
|
{
|
||||||
|
fiftyResults.add(AlfMock.generateText());
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup query results
|
||||||
|
when(mockedReadPagingResults.getPage())
|
||||||
|
.thenReturn(fiftyResults)
|
||||||
|
.thenReturn(Stream.of(GROUP_PREFIX + readGroup).collect(Collectors.toList()));
|
||||||
|
when(mockedAuthorityService.getAuthorities(
|
||||||
|
eq(AuthorityType.GROUP),
|
||||||
|
eq(RMAuthority.ZONE_APP_RM),
|
||||||
|
eq(readGroupPrefix),
|
||||||
|
eq(false),
|
||||||
|
eq(false),
|
||||||
|
any(PagingRequest.class)))
|
||||||
|
.thenReturn(mockedReadPagingResults);
|
||||||
|
|
||||||
|
when(mockedWritePagingResults.getPage())
|
||||||
|
.thenReturn(fiftyResults)
|
||||||
|
.thenReturn(Stream.of(GROUP_PREFIX + writeGroup).collect(Collectors.toList()));
|
||||||
|
when(mockedAuthorityService.getAuthorities(
|
||||||
|
eq(AuthorityType.GROUP),
|
||||||
|
eq(RMAuthority.ZONE_APP_RM),
|
||||||
|
eq(writeGroupPrefix),
|
||||||
|
eq(false),
|
||||||
|
eq(false),
|
||||||
|
any(PagingRequest.class)))
|
||||||
|
.thenReturn(mockedWritePagingResults);
|
||||||
|
|
||||||
|
// setup exact match
|
||||||
|
when(mockedAuthorityService.authorityExists(GROUP_PREFIX + writeGroup))
|
||||||
|
.thenReturn(true);
|
||||||
|
when(mockedAuthorityService.getContainedAuthorities(null, GROUP_PREFIX + readGroup, true))
|
||||||
|
.thenReturn(Stream
|
||||||
|
.of(USER, GROUP)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
when(mockedAuthorityService.getContainedAuthorities(null, GROUP_PREFIX + writeGroup, true))
|
||||||
|
.thenReturn(Stream
|
||||||
|
.of(USER_W, GROUP_W)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
|
||||||
|
// add extended security
|
||||||
|
extendedSecurityService.set(nodeRef, READERS, WRITERS);
|
||||||
|
|
||||||
|
// verify no old permissions needing to be cleared
|
||||||
|
verify(mockedPermissionService, never()).clearPermission(eq(nodeRef), anyString());
|
||||||
|
|
||||||
|
// verify read group is not recreated
|
||||||
|
verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, readGroup, readGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
readGroup = GROUP_PREFIX + readGroup;
|
||||||
|
verify(mockedAuthorityService, never()).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, readGroup);
|
||||||
|
verify(mockedAuthorityService, never()).addAuthority(readGroup, USER);
|
||||||
|
verify(mockedAuthorityService, never()).addAuthority(readGroup, GROUP);
|
||||||
|
|
||||||
|
// verify write group is not recreated
|
||||||
|
verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, writeGroup, writeGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
writeGroup = GROUP_PREFIX + writeGroup;
|
||||||
|
verify(mockedAuthorityService, never()).addAuthority(readGroup, writeGroup);
|
||||||
|
verify(mockedAuthorityService, never()).addAuthority(writeGroup, USER_W);
|
||||||
|
verify(mockedAuthorityService, never()).addAuthority(writeGroup, GROUP_W);
|
||||||
|
|
||||||
|
// verify groups assigned to RM roles
|
||||||
|
verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, readGroup);
|
||||||
|
verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, writeGroup);
|
||||||
|
|
||||||
|
// verify permissions are assigned to node
|
||||||
|
verify(mockedPermissionService).setPermission(nodeRef, readGroup, RMPermissionModel.READ_RECORDS, true);
|
||||||
|
verify(mockedPermissionService).setPermission(nodeRef, writeGroup, RMPermissionModel.FILING, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that a node already has extended security
|
||||||
|
* When I add extended security
|
||||||
|
* Then the existing extended security is replaced with the new extended security
|
||||||
|
*/
|
||||||
|
@Test public void addExtendedSecurityToNodeWithExtendedSecurity()
|
||||||
|
{
|
||||||
|
// group names
|
||||||
|
String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_FULL_PREFIX, READERS, 0);
|
||||||
|
String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_FULL_PREFIX, WRITERS, 0);
|
||||||
|
|
||||||
|
// setup permissions
|
||||||
|
Set<AccessPermission> permissions = Stream
|
||||||
|
.of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, readGroup, 0),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 1),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, writeGroup, 2))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||||
|
.thenReturn(permissions);
|
||||||
|
|
||||||
|
// set revised reader and writers
|
||||||
|
String user = generateText();
|
||||||
|
String group = generateText();
|
||||||
|
String userW = generateText();
|
||||||
|
String groupW = generateText();
|
||||||
|
Set<String> newReaders = Stream.of(user, group).collect(Collectors.toSet());
|
||||||
|
Set<String> newWriters = Stream.of(userW, groupW).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
// new group names
|
||||||
|
String newReadGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_PREFIX, newReaders, 0);
|
||||||
|
String newWriteGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_PREFIX, newWriters, 0);
|
||||||
|
|
||||||
|
// make sure users and groups exist
|
||||||
|
Stream
|
||||||
|
.of(user, group, userW, groupW)
|
||||||
|
.forEach((a) ->
|
||||||
|
when(mockedAuthorityService.authorityExists(a))
|
||||||
|
.thenReturn(true));
|
||||||
|
|
||||||
|
// setup query results for no group matches
|
||||||
|
when(mockedReadPagingResults.getPage())
|
||||||
|
.thenReturn(Collections.emptyList());
|
||||||
|
when(mockedAuthorityService.getAuthorities(
|
||||||
|
eq(AuthorityType.GROUP),
|
||||||
|
eq(RMAuthority.ZONE_APP_RM),
|
||||||
|
any(String.class),
|
||||||
|
eq(false),
|
||||||
|
eq(false),
|
||||||
|
any(PagingRequest.class)))
|
||||||
|
.thenReturn(mockedReadPagingResults);
|
||||||
|
|
||||||
|
// set extended security
|
||||||
|
extendedSecurityService.set(nodeRef, newReaders, newWriters);
|
||||||
|
|
||||||
|
// verify that the old permissions are cleared
|
||||||
|
verify(mockedPermissionService).clearPermission(nodeRef, readGroup);
|
||||||
|
verify(mockedPermissionService).clearPermission(nodeRef, writeGroup);
|
||||||
|
|
||||||
|
// verify read group created correctly
|
||||||
|
verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, newReadGroup, newReadGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
newReadGroup = GROUP_PREFIX + newReadGroup;
|
||||||
|
verify(mockedAuthorityService).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, newReadGroup);
|
||||||
|
verify(mockedAuthorityService).addAuthority(newReadGroup, user);
|
||||||
|
verify(mockedAuthorityService).addAuthority(newReadGroup, group);
|
||||||
|
|
||||||
|
// verify write group created correctly
|
||||||
|
verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, newWriteGroup, newWriteGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
newWriteGroup = GROUP_PREFIX + newWriteGroup;
|
||||||
|
verify(mockedAuthorityService).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, newWriteGroup);
|
||||||
|
verify(mockedAuthorityService).addAuthority(newWriteGroup, userW);
|
||||||
|
verify(mockedAuthorityService).addAuthority(newWriteGroup, groupW);
|
||||||
|
|
||||||
|
// verify groups assigned to RM roles
|
||||||
|
verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, newReadGroup);
|
||||||
|
verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, newWriteGroup);
|
||||||
|
|
||||||
|
// verify permissions are assigned to node
|
||||||
|
verify(mockedPermissionService).setPermission(nodeRef, newReadGroup, RMPermissionModel.READ_RECORDS, true);
|
||||||
|
verify(mockedPermissionService).setPermission(nodeRef, newWriteGroup, RMPermissionModel.FILING, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that a node has renditions
|
||||||
|
* When I add extended security
|
||||||
|
* Then they are applied to the renditions
|
||||||
|
*/
|
||||||
|
@Test public void extendedSecurityAddedToRenditions()
|
||||||
|
{
|
||||||
|
// group names
|
||||||
|
String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_PREFIX, READERS, 0);
|
||||||
|
String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_PREFIX, WRITERS, 0);
|
||||||
|
|
||||||
|
// setup query results
|
||||||
|
when(mockedReadPagingResults.getPage())
|
||||||
|
.thenReturn(Collections.emptyList());
|
||||||
|
when(mockedAuthorityService.getAuthorities(
|
||||||
|
eq(AuthorityType.GROUP),
|
||||||
|
eq(RMAuthority.ZONE_APP_RM),
|
||||||
|
any(String.class),
|
||||||
|
eq(false),
|
||||||
|
eq(false),
|
||||||
|
any(PagingRequest.class)))
|
||||||
|
.thenReturn(mockedReadPagingResults);
|
||||||
|
|
||||||
|
// setup renditions
|
||||||
|
NodeRef renditionNodeRef = AlfMock.generateNodeRef(mockedNodeService);
|
||||||
|
when(mockedNodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_RECORD))
|
||||||
|
.thenReturn(true);
|
||||||
|
when(mockedChildAssociationRef.getChildRef())
|
||||||
|
.thenReturn(renditionNodeRef);
|
||||||
|
when(mockedNodeService.getChildAssocs(nodeRef, RenditionModel.ASSOC_RENDITION, RegexQNamePattern.MATCH_ALL))
|
||||||
|
.thenReturn(Collections.singletonList(mockedChildAssociationRef));
|
||||||
|
|
||||||
|
// add extended security
|
||||||
|
extendedSecurityService.set(nodeRef, READERS, WRITERS);
|
||||||
|
|
||||||
|
// verify no old permissions needing to be cleared
|
||||||
|
verify(mockedPermissionService, never()).clearPermission(eq(nodeRef), anyString());
|
||||||
|
|
||||||
|
// verify read group created correctly
|
||||||
|
verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, readGroup, readGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
readGroup = GROUP_PREFIX + readGroup;
|
||||||
|
verify(mockedAuthorityService).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, readGroup);
|
||||||
|
verify(mockedAuthorityService).addAuthority(readGroup, USER);
|
||||||
|
verify(mockedAuthorityService).addAuthority(readGroup, GROUP);
|
||||||
|
|
||||||
|
// verify write group created correctly
|
||||||
|
verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, writeGroup, writeGroup, Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
|
writeGroup = GROUP_PREFIX + writeGroup;
|
||||||
|
verify(mockedAuthorityService).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, writeGroup);
|
||||||
|
verify(mockedAuthorityService).addAuthority(writeGroup, USER_W);
|
||||||
|
verify(mockedAuthorityService).addAuthority(writeGroup, GROUP_W);
|
||||||
|
|
||||||
|
// verify groups assigned to RM roles
|
||||||
|
verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, readGroup);
|
||||||
|
verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, writeGroup);
|
||||||
|
|
||||||
|
// verify permissions are assigned to node
|
||||||
|
verify(mockedPermissionService).setPermission(nodeRef, readGroup, RMPermissionModel.READ_RECORDS, true);
|
||||||
|
verify(mockedPermissionService).setPermission(nodeRef, writeGroup, RMPermissionModel.FILING, true);
|
||||||
|
|
||||||
|
// verify permissions are assigned to the rendition
|
||||||
|
verify(mockedPermissionService).setPermission(renditionNodeRef, readGroup, RMPermissionModel.READ_RECORDS, true);
|
||||||
|
verify(mockedPermissionService).setPermission(renditionNodeRef, writeGroup, RMPermissionModel.FILING, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that a node has extended security
|
||||||
|
* When I remove the extended security
|
||||||
|
* Then the inplace groups permissions are removed
|
||||||
|
*/
|
||||||
|
@Test public void removeAllExtendedSecurity()
|
||||||
|
{
|
||||||
|
// group names
|
||||||
|
String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_FULL_PREFIX, READERS, 0);
|
||||||
|
String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_FULL_PREFIX, WRITERS, 0);
|
||||||
|
|
||||||
|
// setup permissions
|
||||||
|
Set<AccessPermission> permissions = Stream
|
||||||
|
.of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, readGroup, 0),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 1),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, writeGroup, 2))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||||
|
.thenReturn(permissions);
|
||||||
|
|
||||||
|
// remove extended security
|
||||||
|
extendedSecurityService.remove(nodeRef);
|
||||||
|
|
||||||
|
// verify that the groups permissions have been removed
|
||||||
|
verify(mockedPermissionService).clearPermission(nodeRef, readGroup);
|
||||||
|
verify(mockedPermissionService).clearPermission(nodeRef, writeGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that a node has no extended security
|
||||||
|
* When I remove the extended security
|
||||||
|
* Then nothing happens
|
||||||
|
*/
|
||||||
|
@Test public void noExtendedSecurityToRemove()
|
||||||
|
{
|
||||||
|
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||||
|
.thenReturn(HAS_NO_EXTENDED_SECURITY);
|
||||||
|
|
||||||
|
// remove extended security
|
||||||
|
extendedSecurityService.remove(nodeRef);
|
||||||
|
|
||||||
|
// verify that the groups permissions have been removed
|
||||||
|
verify(mockedPermissionService, never()).clearPermission(eq(nodeRef), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that node has renditions
|
||||||
|
* When I remove the extended security for a node
|
||||||
|
* Then the extended security is also removed from the renditions
|
||||||
|
*/
|
||||||
|
@Test public void removeExtendedSecurityFromRenditions()
|
||||||
|
{
|
||||||
|
// group names
|
||||||
|
String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_FULL_PREFIX, READERS, 0);
|
||||||
|
String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_FULL_PREFIX, WRITERS, 0);
|
||||||
|
|
||||||
|
// setup renditions
|
||||||
|
NodeRef renditionNodeRef = AlfMock.generateNodeRef(mockedNodeService);
|
||||||
|
when(mockedNodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_RECORD))
|
||||||
|
.thenReturn(true);
|
||||||
|
when(mockedChildAssociationRef.getChildRef())
|
||||||
|
.thenReturn(renditionNodeRef);
|
||||||
|
when(mockedNodeService.getChildAssocs(nodeRef, RenditionModel.ASSOC_RENDITION, RegexQNamePattern.MATCH_ALL))
|
||||||
|
.thenReturn(Collections.singletonList(mockedChildAssociationRef));
|
||||||
|
|
||||||
|
// setup permissions
|
||||||
|
Set<AccessPermission> permissions = Stream
|
||||||
|
.of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, readGroup, 0),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 1),
|
||||||
|
new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, writeGroup, 2))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
when(mockedPermissionService.getAllSetPermissions(nodeRef))
|
||||||
|
.thenReturn(permissions);
|
||||||
|
|
||||||
|
// remove extended security
|
||||||
|
extendedSecurityService.remove(nodeRef);
|
||||||
|
|
||||||
|
// verify that the groups permissions have been removed
|
||||||
|
verify(mockedPermissionService).clearPermission(nodeRef, readGroup);
|
||||||
|
verify(mockedPermissionService).clearPermission(nodeRef, writeGroup);
|
||||||
|
|
||||||
|
// verify that the groups permissions have been removed from the rendition
|
||||||
|
verify(mockedPermissionService).clearPermission(renditionNodeRef, readGroup);
|
||||||
|
verify(mockedPermissionService).clearPermission(renditionNodeRef, writeGroup);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -27,13 +27,10 @@
|
|||||||
|
|
||||||
package org.alfresco.module.org_alfresco_module_rm.security;
|
package org.alfresco.module.org_alfresco_module_rm.security;
|
||||||
|
|
||||||
import static org.mockito.Matchers.anyString;
|
|
||||||
import static org.mockito.Matchers.eq;
|
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -172,16 +169,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setPermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.READ_RECORDS);
|
filePlanPermissionService.setPermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.READ_RECORDS);
|
||||||
|
|
||||||
// verify permission set on target node
|
// verify permission set on target node
|
||||||
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
||||||
|
|
||||||
// verify READ permission set up hierarchy
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordContainer, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(filePlan, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
|
|
||||||
// verify READ permission set down hierarchy
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordFolderChild, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(unfiledRecord, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -194,15 +182,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setPermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.FILING);
|
filePlanPermissionService.setPermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.FILING);
|
||||||
|
|
||||||
// verify permission set on target node
|
// verify permission set on target node
|
||||||
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.FILING, true);
|
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.FILING, true);
|
||||||
|
|
||||||
// verify READ permission set up hierarchy
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordContainer, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(filePlan, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
|
|
||||||
// verify FILING permission set down hierarchy
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(unfiledRecordFolderChild, AUTHORITY, RMPermissionModel.FILING, true);
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(unfiledRecord, AUTHORITY, RMPermissionModel.FILING, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -216,14 +196,6 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
|
|
||||||
// verify permission deleted on target node
|
// verify permission deleted on target node
|
||||||
verify(mockedPermissionService, times(1)).deletePermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.READ_RECORDS);
|
verify(mockedPermissionService, times(1)).deletePermission(unfiledRecordFolder, AUTHORITY, RMPermissionModel.READ_RECORDS);
|
||||||
|
|
||||||
// verify no permissions deleted up the hierarchy
|
|
||||||
verify(mockedPermissionService, never()).deletePermission(eq(unfiledRecordContainer), eq(AUTHORITY), anyString());
|
|
||||||
verify(mockedPermissionService, never()).deletePermission(eq(filePlan), eq(AUTHORITY), anyString());
|
|
||||||
|
|
||||||
// verify READ permission removed down hierarchy
|
|
||||||
verify(mockedPermissionService, times(1)).deletePermission(unfiledRecordFolderChild, AUTHORITY, RMPermissionModel.READ_RECORDS);
|
|
||||||
verify(mockedPermissionService, times(1)).deletePermission(unfiledRecord, AUTHORITY, RMPermissionModel.READ_RECORDS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -237,16 +209,6 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
|
|
||||||
// verify permission set on target node
|
// verify permission set on target node
|
||||||
verify(mockedPermissionService, times(1)).setPermission(holdContainer, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
verify(mockedPermissionService, times(1)).setPermission(holdContainer, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
||||||
|
|
||||||
// verify READ permission set up hierarchy
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(filePlan, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
|
|
||||||
// verify READ permission set on hold
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(hold, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
|
|
||||||
// verify permission not set on child of hold
|
|
||||||
verify(mockedPermissionService, never()).setPermission(eq(heldRecord), eq(AUTHORITY), anyString(), eq(true));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -259,17 +221,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setPermission(holdContainer, AUTHORITY, RMPermissionModel.FILING);
|
filePlanPermissionService.setPermission(holdContainer, AUTHORITY, RMPermissionModel.FILING);
|
||||||
|
|
||||||
// verify permission set on target node
|
// verify permission set on target node
|
||||||
verify(mockedPermissionService, times(1)).setPermission(holdContainer, AUTHORITY, RMPermissionModel.FILING, true);
|
verify(mockedPermissionService, times(1)).setPermission(holdContainer, AUTHORITY, RMPermissionModel.FILING, true);
|
||||||
|
|
||||||
// verify READ permission set up hierarchy
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(filePlan, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
|
|
||||||
// verify FILING permission set on hold
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(hold, AUTHORITY, RMPermissionModel.FILING, true);
|
|
||||||
|
|
||||||
// verify permission not set on child of hold
|
|
||||||
verify(mockedPermissionService, never()).setPermission(eq(heldRecord), eq(AUTHORITY), anyString(), eq(true));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -283,13 +235,6 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
|
|
||||||
// verify permission set on target node
|
// verify permission set on target node
|
||||||
verify(mockedPermissionService, times(1)).setPermission(hold, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
verify(mockedPermissionService, times(1)).setPermission(hold, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
||||||
|
|
||||||
// verify READ permission set up hierarchy
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(holdContainer, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(filePlan, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
|
|
||||||
// verify permission not set on child of hold
|
|
||||||
verify(mockedPermissionService, never()).setPermission(eq(heldRecord), eq(AUTHORITY), anyString(), eq(true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -302,14 +247,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setPermission(hold, AUTHORITY, RMPermissionModel.FILING);
|
filePlanPermissionService.setPermission(hold, AUTHORITY, RMPermissionModel.FILING);
|
||||||
|
|
||||||
// verify permission set on target node
|
// verify permission set on target node
|
||||||
verify(mockedPermissionService, times(1)).setPermission(hold, AUTHORITY, RMPermissionModel.FILING, true);
|
verify(mockedPermissionService, times(1)).setPermission(hold, AUTHORITY, RMPermissionModel.FILING, true);
|
||||||
|
|
||||||
// verify READ permission set up hierarchy
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(holdContainer, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
verify(mockedPermissionService, times(1)).setPermission(filePlan, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
|
|
||||||
// verify permission not set on child of hold
|
|
||||||
verify(mockedPermissionService, never()).setPermission(eq(heldRecord), eq(AUTHORITY), anyString(), eq(true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -322,10 +260,6 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
// setup basic file and read for authorities
|
// setup basic file and read for authorities
|
||||||
perms.add(new AccessPermissionImpl(RMPermissionModel.READ_RECORDS, AccessStatus.ALLOWED, AUTHORITY, 0));
|
perms.add(new AccessPermissionImpl(RMPermissionModel.READ_RECORDS, AccessStatus.ALLOWED, AUTHORITY, 0));
|
||||||
perms.add(new AccessPermissionImpl(RMPermissionModel.FILING, AccessStatus.ALLOWED, AUTHORITY2, 1));
|
perms.add(new AccessPermissionImpl(RMPermissionModel.FILING, AccessStatus.ALLOWED, AUTHORITY2, 1));
|
||||||
|
|
||||||
// setup in-place readers and writers
|
|
||||||
perms.add(new AccessPermissionImpl(RMPermissionModel.READ_RECORDS, AccessStatus.ALLOWED, ExtendedReaderDynamicAuthority.EXTENDED_READER, 2));
|
|
||||||
perms.add(new AccessPermissionImpl(RMPermissionModel.FILING, AccessStatus.ALLOWED, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, 3));
|
|
||||||
|
|
||||||
doReturn(perms).when(mockedPermissionService).getAllSetPermissions(nodeRef);
|
doReturn(perms).when(mockedPermissionService).getAllSetPermissions(nodeRef);
|
||||||
}
|
}
|
||||||
@@ -333,13 +267,12 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
/**
|
/**
|
||||||
* Helper to verify the core permissions have been initialized correctly
|
* Helper to verify the core permissions have been initialized correctly
|
||||||
*/
|
*/
|
||||||
private void verifyInitPermissions(NodeRef nodeRef)
|
private void verifyInitPermissions(NodeRef nodeRef, boolean isInherited)
|
||||||
{
|
{
|
||||||
verify(mockedPermissionService, times(1)).setInheritParentPermissions(nodeRef, false);
|
verify(mockedPermissionService).getAllSetPermissions(nodeRef);
|
||||||
verify(mockedPermissionService, times(1)).clearPermission(nodeRef, null);
|
verify(mockedPermissionService).setInheritParentPermissions(nodeRef, isInherited);
|
||||||
verify(mockedPermissionService, times(1)).setPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true);
|
verify(mockedPermissionService).clearPermission(nodeRef, null);
|
||||||
verify(mockedPermissionService, times(1)).setPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true);
|
verify(mockedOwnableService).setOwner(nodeRef, OwnableService.NO_OWNER);
|
||||||
verify(mockedOwnableService, times(1)).setOwner(nodeRef, OwnableService.NO_OWNER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -350,21 +283,20 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
* @param read verification mode relating to setting read on the child
|
* @param read verification mode relating to setting read on the child
|
||||||
* @param filling verification mode relating to setting filling on the child
|
* @param filling verification mode relating to setting filling on the child
|
||||||
*/
|
*/
|
||||||
private void verifyInitPermissions(NodeRef parent, NodeRef child, VerificationMode read, VerificationMode filling)
|
private void verifyInitPermissions(NodeRef parent, NodeRef child, VerificationMode read, VerificationMode filling, boolean isParentFilePlan, boolean isInherited)
|
||||||
{
|
{
|
||||||
// verify the core permissions are set-up correctly
|
// verify the core permissions are set-up correctly
|
||||||
verifyInitPermissions(child);
|
verifyInitPermissions(child, isInherited);
|
||||||
|
|
||||||
// verify the permissions came from the correct parent
|
|
||||||
verify(mockedPermissionService).getAllSetPermissions(parent);
|
|
||||||
|
|
||||||
// verify all the inherited permissions are set correctly (note read are not inherited from fileplan)
|
|
||||||
verify(mockedPermissionService, filling).setPermission(child, AUTHORITY2, RMPermissionModel.FILING, true);
|
|
||||||
verify(mockedPermissionService, read).setPermission(child, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
|
||||||
|
|
||||||
// verify that there are no unaccounted for interactions with the permission service
|
|
||||||
verifyNoMoreInteractions(mockedPermissionService);
|
|
||||||
|
|
||||||
|
if (isParentFilePlan)
|
||||||
|
{
|
||||||
|
// verify the permissions came from the correct parent
|
||||||
|
verify(mockedPermissionService).getAllSetPermissions(parent);
|
||||||
|
|
||||||
|
// verify all the inherited permissions are set correctly (note read are not inherited from fileplan)
|
||||||
|
verify(mockedPermissionService, filling).setPermission(child, AUTHORITY2, RMPermissionModel.FILING, true);
|
||||||
|
verify(mockedPermissionService, read).setPermission(child, AUTHORITY, RMPermissionModel.READ_RECORDS, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -380,7 +312,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setupRecordCategoryPermissions(rootRecordCategory);
|
filePlanPermissionService.setupRecordCategoryPermissions(rootRecordCategory);
|
||||||
|
|
||||||
// verify permission init
|
// verify permission init
|
||||||
verifyInitPermissions(filePlan, rootRecordCategory, never(), times(1));
|
verifyInitPermissions(filePlan, rootRecordCategory, never(), times(1), true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -396,7 +328,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setupRecordCategoryPermissions(recordCategory);
|
filePlanPermissionService.setupRecordCategoryPermissions(recordCategory);
|
||||||
|
|
||||||
// verify permission init
|
// verify permission init
|
||||||
verifyInitPermissions(rootRecordCategory, recordCategory, times(1), times(1));
|
verifyInitPermissions(rootRecordCategory, recordCategory, times(1), times(1), false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -412,7 +344,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setupPermissions(recordCategory, newRecordFolder);
|
filePlanPermissionService.setupPermissions(recordCategory, newRecordFolder);
|
||||||
|
|
||||||
// verify permission init
|
// verify permission init
|
||||||
verifyInitPermissions(recordCategory, newRecordFolder, times(1), times(1));
|
verifyInitPermissions(recordCategory, newRecordFolder, times(1), times(1), false, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,7 +361,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setupPermissions(newRecordFolder, newRecord);
|
filePlanPermissionService.setupPermissions(newRecordFolder, newRecord);
|
||||||
|
|
||||||
// verify permission init
|
// verify permission init
|
||||||
verifyInitPermissions(newRecordFolder, newRecord, times(1), times(1));
|
verifyInitPermissions(newRecordFolder, newRecord, times(1), times(1), false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -445,7 +377,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setupPermissions(filePlan, holdContainer);
|
filePlanPermissionService.setupPermissions(filePlan, holdContainer);
|
||||||
|
|
||||||
// verify permissions are set-up correctly
|
// verify permissions are set-up correctly
|
||||||
verifyInitPermissions(filePlan, holdContainer, times(1), times(1));
|
verifyInitPermissions(filePlan, holdContainer, times(1), times(1), false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -461,7 +393,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setupPermissions(holdContainer, hold);
|
filePlanPermissionService.setupPermissions(holdContainer, hold);
|
||||||
|
|
||||||
// verify permissions are set-up correctly
|
// verify permissions are set-up correctly
|
||||||
verifyInitPermissions(holdContainer, hold, never(), times(1));
|
verifyInitPermissions(holdContainer, hold, never(), times(1), false, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,7 +410,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setupPermissions(filePlan, unfiledRecordContainer);
|
filePlanPermissionService.setupPermissions(filePlan, unfiledRecordContainer);
|
||||||
|
|
||||||
// verify permissions are set-up correctly
|
// verify permissions are set-up correctly
|
||||||
verifyInitPermissions(filePlan, unfiledRecordContainer, times(1), times(1));
|
verifyInitPermissions(filePlan, unfiledRecordContainer, times(1), times(1), false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -494,7 +426,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setupPermissions(unfiledRecordContainer, unfiledRecordFolder);
|
filePlanPermissionService.setupPermissions(unfiledRecordContainer, unfiledRecordFolder);
|
||||||
|
|
||||||
// verify permissions are set-up correctly
|
// verify permissions are set-up correctly
|
||||||
verifyInitPermissions(unfiledRecordContainer, unfiledRecordFolder, never(), times(1));
|
verifyInitPermissions(unfiledRecordContainer, unfiledRecordFolder, never(), times(1), false, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,7 +443,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
|||||||
filePlanPermissionService.setupPermissions(unfiledRecordFolder, unfiledRecord);
|
filePlanPermissionService.setupPermissions(unfiledRecordFolder, unfiledRecord);
|
||||||
|
|
||||||
// verify permission init
|
// verify permission init
|
||||||
verifyInitPermissions(unfiledRecordFolder, unfiledRecord, times(1), times(1));
|
verifyInitPermissions(unfiledRecordFolder, unfiledRecord, times(1), times(1), false, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,418 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* -
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
* -
|
||||||
|
* 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/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2014 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.web.scripts.roles;
|
||||||
|
|
||||||
|
import static java.util.Collections.emptyMap;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyBoolean;
|
||||||
|
import static org.mockito.Matchers.anyLong;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
|
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.ExtendedSecurityService;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest;
|
||||||
|
import org.alfresco.repo.domain.node.NodeDAO;
|
||||||
|
import org.alfresco.repo.domain.patch.PatchDAO;
|
||||||
|
import org.alfresco.repo.domain.qname.QNameDAO;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
|
import org.mockito.stubbing.Answer;
|
||||||
|
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DynamicAuthoritiesGet Unit Test
|
||||||
|
*
|
||||||
|
* @author Silviu Dinuta
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest implements RecordsManagementModel
|
||||||
|
{
|
||||||
|
/** test data */
|
||||||
|
private static final Long ASPECT_ID = 123l;
|
||||||
|
private static final QName ASPECT = AlfMock.generateQName();
|
||||||
|
|
||||||
|
/** mocks */
|
||||||
|
@Mock
|
||||||
|
private PatchDAO mockedPatchDAO;
|
||||||
|
@Mock
|
||||||
|
private NodeDAO mockedNodeDAO;
|
||||||
|
@Mock
|
||||||
|
private QNameDAO mockedQnameDAO;
|
||||||
|
@Mock
|
||||||
|
private NodeService mockedNodeService;
|
||||||
|
@Mock
|
||||||
|
private PermissionService mockedPermissionService;
|
||||||
|
@Mock
|
||||||
|
private ExtendedSecurityService mockedExtendedSecurityService;
|
||||||
|
@Mock
|
||||||
|
private TransactionService mockedTransactionService;
|
||||||
|
@Mock
|
||||||
|
private RetryingTransactionHelper mockedRetryingTransactionHelper;
|
||||||
|
|
||||||
|
/** test component */
|
||||||
|
@InjectMocks
|
||||||
|
private DynamicAuthoritiesGet webScript;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DeclarativeWebScript getWebScript()
|
||||||
|
{
|
||||||
|
return webScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getWebScriptTemplate()
|
||||||
|
{
|
||||||
|
return "alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.json.ftl";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Before test
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Before
|
||||||
|
public void before()
|
||||||
|
{
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
webScript.setNodeService(mockedNodeService);
|
||||||
|
webScript.setPermissionService(mockedPermissionService);
|
||||||
|
webScript.setExtendedSecurityService(mockedExtendedSecurityService);
|
||||||
|
// setup retrying transaction helper
|
||||||
|
Answer<Object> doInTransactionAnswer = new Answer<Object>()
|
||||||
|
{
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Override
|
||||||
|
public Object answer(InvocationOnMock invocation) throws Throwable
|
||||||
|
{
|
||||||
|
RetryingTransactionCallback callback = (RetryingTransactionCallback) invocation.getArguments()[0];
|
||||||
|
return callback.execute();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
doAnswer(doInTransactionAnswer).when(mockedRetryingTransactionHelper)
|
||||||
|
.<Object> doInTransaction(any(RetryingTransactionCallback.class), anyBoolean(), anyBoolean());
|
||||||
|
|
||||||
|
when(mockedTransactionService.getRetryingTransactionHelper()).thenReturn(mockedRetryingTransactionHelper);
|
||||||
|
|
||||||
|
// max node id
|
||||||
|
when(mockedPatchDAO.getMaxAdmNodeID()).thenReturn(500000L);
|
||||||
|
|
||||||
|
// aspect
|
||||||
|
when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(new Pair<Long, QName>(ASPECT_ID, ASPECT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that there are no nodes with the extended security aspect When the action is executed Nothing happens
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({ "unchecked" })
|
||||||
|
@Test
|
||||||
|
public void noNodesWithExtendedSecurity() throws Exception
|
||||||
|
{
|
||||||
|
when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong()))
|
||||||
|
.thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
// Set up parameters.
|
||||||
|
Map<String, String> parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "3");
|
||||||
|
JSONObject json = executeJSONWebScript(parameters);
|
||||||
|
assertNotNull(json);
|
||||||
|
String actualJSONString = json.toString();
|
||||||
|
|
||||||
|
// Check the JSON result using Jackson to allow easy equality testing.
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 0 records.\"}";
|
||||||
|
assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString));
|
||||||
|
|
||||||
|
|
||||||
|
verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_READERS));
|
||||||
|
verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_WRITERS));
|
||||||
|
verify(mockedNodeService, never()).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY));
|
||||||
|
verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class),
|
||||||
|
eq(ExtendedReaderDynamicAuthority.EXTENDED_READER));
|
||||||
|
verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class),
|
||||||
|
eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER));
|
||||||
|
verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that there are records with the extended security aspect When the action is executed Then the aspect is
|
||||||
|
* removed And the dynamic authorities permissions are cleared And extended security is set via the updated API
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test
|
||||||
|
public void recordsWithExtendedSecurityAspect() throws Exception
|
||||||
|
{
|
||||||
|
List<Long> ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList());
|
||||||
|
|
||||||
|
when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong()))
|
||||||
|
.thenReturn(ids)
|
||||||
|
.thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
ids.stream().forEach((i) -> {
|
||||||
|
NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService);
|
||||||
|
when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair<Long, NodeRef>(i, nodeRef));
|
||||||
|
when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true);
|
||||||
|
when(mockedNodeService.getProperty(nodeRef, PROP_READERS))
|
||||||
|
.thenReturn((Serializable) Collections.emptyMap());
|
||||||
|
when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS))
|
||||||
|
.thenReturn((Serializable) Collections.emptyMap());
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up parameters.
|
||||||
|
Map<String, String> parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4");
|
||||||
|
JSONObject json = executeJSONWebScript(parameters);
|
||||||
|
assertNotNull(json);
|
||||||
|
String actualJSONString = json.toString();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}";
|
||||||
|
assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString));
|
||||||
|
|
||||||
|
|
||||||
|
verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS));
|
||||||
|
verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS));
|
||||||
|
verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY));
|
||||||
|
verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class),
|
||||||
|
eq(ExtendedReaderDynamicAuthority.EXTENDED_READER));
|
||||||
|
verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class),
|
||||||
|
eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER));
|
||||||
|
verify(mockedExtendedSecurityService, times(3)).set(any(NodeRef.class), any(Set.class), any(Set.class));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given that there are non-records with the extended security aspect When the web script is executed Then the aspect is
|
||||||
|
* removed And the dynamic authorities permissions are cleared
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test
|
||||||
|
public void nonRecordsWithExtendedSecurityAspect() throws Exception
|
||||||
|
{
|
||||||
|
List<Long> ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList());
|
||||||
|
|
||||||
|
when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong()))
|
||||||
|
.thenReturn(ids)
|
||||||
|
.thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
ids.stream().forEach((i) -> {
|
||||||
|
NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService);
|
||||||
|
when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair<Long, NodeRef>(i, nodeRef));
|
||||||
|
when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false);
|
||||||
|
when(mockedNodeService.getProperty(nodeRef, PROP_READERS))
|
||||||
|
.thenReturn((Serializable) Collections.emptyMap());
|
||||||
|
when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS))
|
||||||
|
.thenReturn((Serializable) Collections.emptyMap());
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up parameters.
|
||||||
|
Map<String, String> parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4");
|
||||||
|
JSONObject json = executeJSONWebScript(parameters);
|
||||||
|
assertNotNull(json);
|
||||||
|
String actualJSONString = json.toString();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}";
|
||||||
|
assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString));
|
||||||
|
|
||||||
|
|
||||||
|
verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS));
|
||||||
|
verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS));
|
||||||
|
verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY));
|
||||||
|
verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class),
|
||||||
|
eq(ExtendedReaderDynamicAuthority.EXTENDED_READER));
|
||||||
|
verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class),
|
||||||
|
eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER));
|
||||||
|
verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void missingBatchSizeParameter() throws Exception
|
||||||
|
{
|
||||||
|
JSONObject json = executeJSONWebScript(emptyMap());
|
||||||
|
assertNotNull(json);
|
||||||
|
String actualJSONString = json.toString();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
String expectedJSONString = "{\"responsestatus\":\"failed\",\"message\":\"Parameter batchsize is mandatory\"}";
|
||||||
|
assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidBatchSizeParameter() throws Exception
|
||||||
|
{
|
||||||
|
// Set up parameters.
|
||||||
|
Map<String, String> parameters = ImmutableMap.of("batchsize", "dd");
|
||||||
|
JSONObject json = executeJSONWebScript(parameters);
|
||||||
|
assertNotNull(json);
|
||||||
|
String actualJSONString = json.toString();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
String expectedJSONString = "{\"responsestatus\":\"failed\",\"message\":\"Parameter batchsize is invalid.\"}";
|
||||||
|
assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void batchSizeShouldBeGraterThanZero() throws Exception
|
||||||
|
{
|
||||||
|
when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(null);
|
||||||
|
// Set up parameters.
|
||||||
|
Map<String, String> parameters = ImmutableMap.of("batchsize", "0");
|
||||||
|
JSONObject json = executeJSONWebScript(parameters);
|
||||||
|
assertNotNull(json);
|
||||||
|
String actualJSONString = json.toString();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
String expectedJSONString = "{\"responsestatus\":\"failed\",\"message\":\"Parameter batchsize should be a number greater than 0.\"}";
|
||||||
|
assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void extendedSecurityAspectNotCreated() throws Exception
|
||||||
|
{
|
||||||
|
when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(null);
|
||||||
|
// Set up parameters.
|
||||||
|
Map<String, String> parameters = ImmutableMap.of("batchsize", "3");
|
||||||
|
JSONObject json = executeJSONWebScript(parameters);
|
||||||
|
assertNotNull(json);
|
||||||
|
String actualJSONString = json.toString();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"There where no records to be processed.\"}";
|
||||||
|
assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void processAllRecordsWhenMaxProcessedRecordsIsZero() throws Exception
|
||||||
|
{
|
||||||
|
List<Long> ids = Stream.of(1l, 2l, 3l,4l).collect(Collectors.toList());
|
||||||
|
|
||||||
|
when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong()))
|
||||||
|
.thenReturn(ids)
|
||||||
|
.thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
ids.stream().forEach((i) -> {
|
||||||
|
NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService);
|
||||||
|
when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair<Long, NodeRef>(i, nodeRef));
|
||||||
|
when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false);
|
||||||
|
when(mockedNodeService.getProperty(nodeRef, PROP_READERS))
|
||||||
|
.thenReturn((Serializable) Collections.emptyMap());
|
||||||
|
when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS))
|
||||||
|
.thenReturn((Serializable) Collections.emptyMap());
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up parameters.
|
||||||
|
Map<String, String> parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "0");
|
||||||
|
JSONObject json = executeJSONWebScript(parameters);
|
||||||
|
assertNotNull(json);
|
||||||
|
String actualJSONString = json.toString();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 4 records.\"}";
|
||||||
|
assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenMaxProcessedRecordsIsMissingItDefaultsToBatchSize() throws Exception
|
||||||
|
{
|
||||||
|
List<Long> ids = Stream.of(1l, 2l, 3l, 4l, 5l).collect(Collectors.toList());
|
||||||
|
|
||||||
|
when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong()))
|
||||||
|
.thenReturn(ids)
|
||||||
|
.thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
ids.stream().forEach((i) -> {
|
||||||
|
NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService);
|
||||||
|
when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair<Long, NodeRef>(i, nodeRef));
|
||||||
|
when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false);
|
||||||
|
when(mockedNodeService.getProperty(nodeRef, PROP_READERS))
|
||||||
|
.thenReturn((Serializable) Collections.emptyMap());
|
||||||
|
when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS))
|
||||||
|
.thenReturn((Serializable) Collections.emptyMap());
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set up parameters.
|
||||||
|
Map<String, String> parameters = ImmutableMap.of("batchsize", "4");
|
||||||
|
JSONObject json = executeJSONWebScript(parameters);
|
||||||
|
assertNotNull(json);
|
||||||
|
String actualJSONString = json.toString();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed first 4 records.\"}";
|
||||||
|
assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString));
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user