mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Merge release/V2.3.0.x into release/V2.3
This commit is contained in:
14
pom.xml
14
pom.xml
@@ -78,6 +78,7 @@
|
||||
<!-- Maven specific build properties -->
|
||||
<maven.alfresco.includeDependencies>false</maven.alfresco.includeDependencies>
|
||||
<maven.build.sourceVersion>1.7</maven.build.sourceVersion>
|
||||
<maven.build.testSourceVersion>1.8</maven.build.testSourceVersion>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<argLine>-Xmx1024m -XX:MaxPermSize=256m -Duser.language=en -Dcom.sun.management.jmxremote</argLine>
|
||||
</properties>
|
||||
@@ -148,6 +149,19 @@
|
||||
<source>${maven.build.sourceVersion}</source>
|
||||
<target>${maven.build.sourceVersion}</target>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-testCompile</id>
|
||||
<phase>process-test-sources</phase>
|
||||
<goals>
|
||||
<goal>testCompile</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<source>${maven.build.testSourceVersion}</source>
|
||||
<target>${maven.build.testSourceVersion}</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
|
@@ -58,6 +58,7 @@
|
||||
org.alfresco.service.cmr.security.PermissionService.hasPermission=ACL_ALLOW
|
||||
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.getReadersAndWriters=ACL_METHOD.ROLE_ADMINISTRATOR
|
||||
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.setPermission=ACL_NODE.0.sys:base.ChangePermissions
|
||||
|
@@ -56,3 +56,4 @@ log4j.logger.org.alfresco.module.org_alfresco_module_rm.patch=info
|
||||
# Job debug
|
||||
#
|
||||
#log4j.logger.org.alfresco.module.org_alfresco_module_rm.job=debug
|
||||
log4j.logger.org.alfresco.repo.web.scripts.roles.DynamicAuthoritiesGet=info
|
@@ -574,6 +574,9 @@
|
||||
<property name="nodeService" ref="nodeService"/>
|
||||
<property name="filePlanService" ref="filePlanService" />
|
||||
<property name="filePlanRoleService" ref="filePlanRoleService" />
|
||||
<property name="authorityService" ref="authorityService"/>
|
||||
<property name="permissionService" ref="permissionService"/>
|
||||
<property name="transactionService" ref="transactionService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="ExtendedSecurityService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
|
@@ -28,7 +28,6 @@
|
||||
<property name="cmObjectType" ref="cm.object" />
|
||||
<property name="extendedPermissionService" ref="ExtendedPermissionService" />
|
||||
<property name="extendedSecurityService" ref="ExtendedSecurityService" />
|
||||
<property name="ownableService" ref="OwnableService" />
|
||||
</bean>
|
||||
<bean class="org.alfresco.util.BeanExtender">
|
||||
<property name="beanName" value="versionService" />
|
||||
|
@@ -587,6 +587,19 @@
|
||||
</property>
|
||||
</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 -->
|
||||
<bean id="webscript.org.alfresco.rma.holds.get"
|
||||
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,4 @@
|
||||
{
|
||||
"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,21 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* #%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.Collections;
|
||||
@@ -32,6 +41,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
||||
* @author Roy Wetherall
|
||||
* @since 2.1
|
||||
*/
|
||||
@Deprecated
|
||||
public class ExtendedReaderDynamicAuthority extends ExtendedSecurityBaseDynamicAuthority
|
||||
{
|
||||
/** Extended reader role */
|
@@ -1,21 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* #%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.Map;
|
||||
@@ -39,6 +48,7 @@ import org.springframework.context.ApplicationContextAware;
|
||||
* @author Roy Wetherall
|
||||
* @since 2.1
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAuthority,
|
||||
RecordsManagementModel,
|
||||
ApplicationContextAware
|
@@ -1,21 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* #%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.Collections;
|
||||
@@ -33,6 +42,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
||||
* @author Roy Wetherall
|
||||
* @since 2.1
|
||||
*/
|
||||
@Deprecated
|
||||
public class ExtendedWriterDynamicAuthority extends ExtendedSecurityBaseDynamicAuthority
|
||||
{
|
||||
/** Extended writer role */
|
@@ -1,21 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* #%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 org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
@@ -26,6 +35,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
* @since 2.1
|
||||
* @deprecated as of 2.2, use {@link AuthenticationUtil}.
|
||||
*/
|
||||
public interface FilePlanAuthenticationService
|
||||
{
|
@@ -1,21 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* #%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 org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
@@ -25,6 +34,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
* @author Roy Wetherall
|
||||
* @since 2.1
|
||||
*/
|
||||
@Deprecated
|
||||
public class FilePlanAuthenticationServiceImpl implements FilePlanAuthenticationService
|
||||
{
|
||||
/** Default rm admin user values */
|
@@ -138,23 +138,23 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
||||
NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER);
|
||||
if (recordFolder == null)
|
||||
{
|
||||
final boolean finaltargetIsUnfiledRecords = targetIsUnfiledRecords;
|
||||
recordFolder = retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
final boolean finaltargetIsUnfiledRecords = targetIsUnfiledRecords;
|
||||
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);
|
||||
}
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
}, false, true);
|
||||
}
|
||||
@@ -170,32 +170,30 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
if(getMode() == CopyMoveLinkFileToActionMode.MOVE)
|
||||
{
|
||||
fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null);
|
||||
}
|
||||
else if(getMode() == CopyMoveLinkFileToActionMode.COPY)
|
||||
{
|
||||
fileFolderService.copy(actionedUponNodeRef, finalRecordFolder, null);
|
||||
}
|
||||
else if(getMode() == CopyMoveLinkFileToActionMode.LINK)
|
||||
{
|
||||
getRecordService().link(actionedUponNodeRef, finalRecordFolder);
|
||||
}
|
||||
}
|
||||
synchronized (this)
|
||||
{
|
||||
if (getMode() == CopyMoveLinkFileToActionMode.MOVE)
|
||||
{
|
||||
fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null);
|
||||
}
|
||||
else if (getMode() == CopyMoveLinkFileToActionMode.COPY)
|
||||
{
|
||||
fileFolderService.copy(actionedUponNodeRef, finalRecordFolder, null);
|
||||
}
|
||||
else if (getMode() == CopyMoveLinkFileToActionMode.LINK)
|
||||
{
|
||||
getRecordService().link(actionedUponNodeRef, finalRecordFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException fileNotFound)
|
||||
{
|
||||
throw new AlfrescoRuntimeException(
|
||||
"Unable to execute file to action, because the " + (mode == CopyMoveLinkFileToActionMode.MOVE ? "move" : "copy") + " operation failed.",
|
||||
fileNotFound
|
||||
);
|
||||
throw new AlfrescoRuntimeException("Unable to execute file to action, because the " + (mode == CopyMoveLinkFileToActionMode.MOVE ? "move" : "copy") + " operation failed.", fileNotFound);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -366,7 +364,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
|
||||
*/
|
||||
private NodeRef getChild(NodeRef parent, String childName)
|
||||
{
|
||||
return getNodeService().getChildByName(parent, ContentModel.ASSOC_CONTAINS, childName);
|
||||
return getNodeService().getChildByName(parent, ContentModel.ASSOC_CONTAINS, childName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -48,6 +48,9 @@ import org.springframework.extensions.surf.util.I18NUtil;
|
||||
*/
|
||||
public class DeclareRecordAction extends RMActionExecuterAbstractBase
|
||||
{
|
||||
/** action name */
|
||||
public static final String NAME = "declareRecord";
|
||||
|
||||
/** I18N */
|
||||
private static final String MSG_UNDECLARED_ONLY_RECORDS = "rm.action.undeclared-only-records";
|
||||
private static final String MSG_NO_DECLARE_MAND_PROP = "rm.action.no-declare-mand-prop";
|
||||
|
@@ -33,11 +33,10 @@ import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
|
||||
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.repo.domain.node.NodeDAO;
|
||||
import org.alfresco.repo.rule.RuleModel;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
@@ -347,23 +346,12 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
|
||||
containerType,
|
||||
properties).getChildRef();
|
||||
|
||||
// if (!inheritPermissions)
|
||||
// {
|
||||
// set inheritance to false
|
||||
getPermissionService().setInheritParentPermissions(container, false);
|
||||
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);
|
||||
// set inheritance to false
|
||||
getPermissionService().setInheritParentPermissions(container, false);
|
||||
getPermissionService().setPermission(container, allRoles, RMPermissionModel.READ_RECORDS, true);
|
||||
|
||||
// TODO set the admin users to have filing permissions on the unfiled container!!!
|
||||
// TODO we will need to be able to get a list of the admin roles from the service
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// just inherit eveything
|
||||
// TODO will change this when we are able to set permissions on holds and transfers!
|
||||
// getPermissionService().setInheritParentPermissions(container, true);
|
||||
// }
|
||||
// prevent inheritance of rules
|
||||
nodeService.addAspect(container, RuleModel.ASPECT_IGNORE_INHERITED_RULES, null);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
@@ -242,9 +242,10 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel
|
||||
QName PROP_LOADED_DATA_SET_IDS = QName.createQName(RM_URI, "loadedDataSetIds");
|
||||
|
||||
// Extended security aspect
|
||||
QName ASPECT_EXTENDED_SECURITY = QName.createQName(RM_URI, "extendedSecurity");
|
||||
QName PROP_READERS = QName.createQName(RM_URI, "readers");
|
||||
QName PROP_WRITERS = QName.createQName(RM_URI, "writers");
|
||||
// @deprecated as of 2.5, because of performance issues
|
||||
@Deprecated QName ASPECT_EXTENDED_SECURITY = QName.createQName(RM_URI, "extendedSecurity");
|
||||
@Deprecated QName PROP_READERS = QName.createQName(RM_URI, "readers");
|
||||
@Deprecated QName PROP_WRITERS = QName.createQName(RM_URI, "writers");
|
||||
|
||||
// Originating details of a record
|
||||
QName ASPECT_RECORD_ORIGINATING_DETAILS = QName.createQName(RM_URI, "recordOriginatingDetails");
|
||||
|
@@ -30,6 +30,7 @@ import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
|
||||
import org.alfresco.repo.copy.CopyBehaviourCallback;
|
||||
import org.alfresco.repo.copy.CopyDetails;
|
||||
import org.alfresco.repo.copy.CopyServicePolicies;
|
||||
import org.alfresco.repo.copy.DefaultCopyBehaviourCallback;
|
||||
import org.alfresco.repo.node.NodeServicePolicies;
|
||||
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
|
||||
@@ -56,7 +57,8 @@ public class RecordAspect extends AbstractDisposableItem
|
||||
implements NodeServicePolicies.OnCreateChildAssociationPolicy,
|
||||
RecordsManagementPolicies.OnCreateReference,
|
||||
RecordsManagementPolicies.OnRemoveReference,
|
||||
NodeServicePolicies.OnMoveNodePolicy
|
||||
NodeServicePolicies.OnMoveNodePolicy,
|
||||
CopyServicePolicies.OnCopyCompletePolicy
|
||||
{
|
||||
/** Well-known location of the scripts folder. */
|
||||
// TODO make configurable
|
||||
@@ -123,11 +125,11 @@ public class RecordAspect extends AbstractDisposableItem
|
||||
|
||||
// manage any extended readers
|
||||
NodeRef parent = childAssocRef.getParentRef();
|
||||
Set<String> readers = extendedSecurityService.getExtendedReaders(parent);
|
||||
Set<String> writers = extendedSecurityService.getExtendedWriters(parent);
|
||||
Set<String> readers = extendedSecurityService.getReaders(parent);
|
||||
Set<String> writers = extendedSecurityService.getWriters(parent);
|
||||
if (readers != null && readers.size() != 0)
|
||||
{
|
||||
extendedSecurityService.addExtendedSecurity(thumbnail, readers, writers, false);
|
||||
extendedSecurityService.set(thumbnail, readers, writers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,4 +289,33 @@ public class RecordAspect extends AbstractDisposableItem
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,13 +25,10 @@ import java.util.Set;
|
||||
import org.alfresco.model.ContentModel;
|
||||
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.RMPermissionModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.dod5015.DOD5015Model;
|
||||
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.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.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -155,10 +152,6 @@ public class RMv21InPlacePatch extends RMv21PatchComponent
|
||||
ruleService.disableRules();
|
||||
try
|
||||
{
|
||||
// set permissions
|
||||
filePlanPermissionService.setPermission(filePlan, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS);
|
||||
filePlanPermissionService.setPermission(filePlan, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING);
|
||||
|
||||
// create fileplan containers
|
||||
filePlanService.createHoldContainer(filePlan);
|
||||
filePlanService.createTransferContainer(filePlan);
|
||||
|
@@ -21,7 +21,6 @@ package org.alfresco.module.org_alfresco_module_rm.record;
|
||||
import static org.alfresco.model.ContentModel.ASPECT_PENDING_DELETE;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
@@ -95,21 +94,25 @@ public class InplaceRecordServiceImpl extends ServiceBaseImpl implements Inplace
|
||||
{
|
||||
// remove the child association
|
||||
NodeRef originatingLocation = (NodeRef) nodeService.getProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION);
|
||||
List<ChildAssociationRef> parentAssocs = nodeService.getParentAssocs(nodeRef);
|
||||
for (ChildAssociationRef childAssociationRef : parentAssocs)
|
||||
{
|
||||
if (!childAssociationRef.isPrimary() &&
|
||||
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.removeAllExtendedSecurity(nodeRef);
|
||||
if (originatingLocation != null)
|
||||
{
|
||||
List<ChildAssociationRef> parentAssocs = nodeService.getParentAssocs(nodeRef);
|
||||
for (ChildAssociationRef childAssociationRef : parentAssocs)
|
||||
{
|
||||
if (!childAssociationRef.isPrimary() &&
|
||||
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);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -164,18 +167,11 @@ public class InplaceRecordServiceImpl extends ServiceBaseImpl implements Inplace
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the extended readers/writers
|
||||
Set<String> extendedReaders = extendedSecurityService.getExtendedReaders(nodeRef);
|
||||
Set<String> extendedWriters = extendedSecurityService.getExtendedWriters(nodeRef);
|
||||
|
||||
// Move the record
|
||||
fileFolderService.moveFrom(nodeRef, source, targetNodeRef, null);
|
||||
|
||||
// Update the originating location property
|
||||
nodeService.setProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION, targetNodeRef);
|
||||
|
||||
// Set the extended readers/writers
|
||||
extendedSecurityService.addExtendedSecurity(nodeRef, extendedReaders, extendedWriters);
|
||||
}
|
||||
catch (FileExistsException | FileNotFoundException ex)
|
||||
{
|
||||
|
@@ -96,6 +96,7 @@ import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.alfresco.util.PropertyMap;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
@@ -240,10 +241,6 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
||||
this,
|
||||
"onCreateChildAssociation",
|
||||
NotificationFrequency.FIRST_EVENT);
|
||||
private JavaBehaviour onDeleteDeclaredRecordLink = new JavaBehaviour(
|
||||
this,
|
||||
"onDeleteDeclaredRecordLink",
|
||||
NotificationFrequency.FIRST_EVENT);
|
||||
|
||||
/**
|
||||
* @param identifierService identifier service
|
||||
@@ -404,11 +401,6 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
||||
TYPE_RECORD_FOLDER,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
onCreateChildAssociation);
|
||||
policyComponent.bindAssociationBehaviour(
|
||||
NodeServicePolicies.BeforeDeleteChildAssociationPolicy.QNAME,
|
||||
ContentModel.TYPE_FOLDER,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
onDeleteDeclaredRecordLink);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -579,27 +571,6 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
||||
}, 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()
|
||||
*/
|
||||
@@ -893,12 +864,10 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
||||
throw new AlfrescoRuntimeException("Unable to create record, because new record container could not be found.");
|
||||
}
|
||||
|
||||
// get the documents readers
|
||||
Long aclId = nodeService.getNodeAclId(nodeRef);
|
||||
Set<String> readers = extendedPermissionService.getReaders(aclId);
|
||||
Set<String> writers = extendedPermissionService.getWriters(aclId);
|
||||
// get the documents readers and writers
|
||||
Pair<Set<String>, Set<String>> readersAndWriters = extendedPermissionService.getReadersAndWriters(nodeRef);
|
||||
|
||||
// add the current owner to the list of extended writers
|
||||
// get the current owner
|
||||
String owner = ownableService.getOwner(nodeRef);
|
||||
|
||||
// get the documents primary parent assoc
|
||||
@@ -950,13 +919,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
||||
nodeService.addChild(parentAssoc.getParentRef(), nodeRef, parentAssoc.getTypeQName(), parentAssoc.getQName());
|
||||
|
||||
// set the extended security
|
||||
Set<String> combinedWriters = new HashSet<String>(writers);
|
||||
if (owner != null && !owner.isEmpty() && !owner.equals(OwnableService.NO_OWNER))
|
||||
{
|
||||
combinedWriters.add(owner);
|
||||
}
|
||||
combinedWriters.add(AuthenticationUtil.getFullyAuthenticatedUser());
|
||||
extendedSecurityService.addExtendedSecurity(nodeRef, readers, combinedWriters);
|
||||
extendedSecurityService.set(nodeRef, readersAndWriters);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -988,24 +951,8 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
||||
// get the unfiled record folder
|
||||
final NodeRef unfiledRecordFolder = filePlanService.getUnfiledContainer(filePlan);
|
||||
|
||||
// get the documents readers
|
||||
Long aclId = nodeService.getNodeAclId(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());
|
||||
// get the documents readers and writers
|
||||
Pair<Set<String>, Set<String>> readersAndWriters = extendedPermissionService.getReadersAndWriters(nodeRef);
|
||||
|
||||
// copy version state and create record
|
||||
NodeRef record = null;
|
||||
@@ -1074,7 +1021,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
||||
}
|
||||
|
||||
// set extended security on record
|
||||
extendedSecurityService.addExtendedSecurity(record, readers, writers);
|
||||
extendedSecurityService.set(record, readersAndWriters);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
@@ -36,8 +36,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.fileplan.FilePlanService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authority.RMAuthority;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
@@ -186,8 +184,6 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService,
|
||||
// Set the permissions
|
||||
permissionService.setInheritParentPermissions(filePlan, false);
|
||||
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
|
||||
systemContainers.add(filePlanService.createHoldContainer(filePlan));
|
||||
|
@@ -1,26 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* #%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.api.AlfrescoPublicApi;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.util.Pair;
|
||||
|
||||
/**
|
||||
* Extended security service.
|
||||
@@ -28,13 +39,17 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
||||
* @author Roy Wetherall
|
||||
* @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.
|
||||
*
|
||||
* @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);
|
||||
|
||||
@@ -44,7 +59,7 @@ public interface ExtendedSecurityService
|
||||
* @param nodeRef node reference
|
||||
* @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.
|
||||
@@ -52,66 +67,39 @@ public interface ExtendedSecurityService
|
||||
* @param nodeRef node reference
|
||||
* @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.
|
||||
* Helper to allow caller to provide authority sets as a pair where the
|
||||
* first is the readers and the second is the writers.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param readers set of authorities to add extended read permissions
|
||||
* @param writers set of authorities to add extended write permissions
|
||||
* @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 addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers);
|
||||
void set(NodeRef nodeRef, Pair<Set<String>, Set<String>> readersAndWriters);
|
||||
|
||||
/**
|
||||
* Add extended security for the specified authorities to a node.
|
||||
* 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>
|
||||
* 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.
|
||||
* Note it is vaild to provide 'null' values for readers and/or writers.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents);
|
||||
|
||||
/**
|
||||
* Remove the extended security for the specified authorities from a node.
|
||||
* @param readers set of readers
|
||||
* @param writers set of writers
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param readers set of authorities to remove as extended readers
|
||||
* @param writers set of authorities to remove as extended writers
|
||||
* @since 2.5
|
||||
*/
|
||||
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.
|
||||
* <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.
|
||||
* Removes all extended security from a node.
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
*/
|
||||
void removeAllExtendedSecurity(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);
|
||||
void remove(NodeRef nodeRef);
|
||||
}
|
||||
|
@@ -1,40 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* #%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.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.Map;
|
||||
import java.util.Set;
|
||||
|
||||
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.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.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.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.Pair;
|
||||
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.
|
||||
@@ -44,14 +67,32 @@ import org.alfresco.util.ParameterCheck;
|
||||
*/
|
||||
public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
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 */
|
||||
private FilePlanService filePlanService;
|
||||
|
||||
/** File plan role service */
|
||||
private FilePlanRoleService filePlanRoleService;
|
||||
|
||||
/** authority service */
|
||||
private AuthorityService authorityService;
|
||||
|
||||
/** permission service */
|
||||
private PermissionService permissionService;
|
||||
|
||||
/** transaction service */
|
||||
private TransactionService transactionService;
|
||||
|
||||
/**
|
||||
* @param filePlanService file plan service
|
||||
*/
|
||||
@@ -68,116 +109,150 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
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)
|
||||
*/
|
||||
@Override
|
||||
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")
|
||||
@Override
|
||||
public Set<String> getExtendedReaders(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)
|
||||
public Set<String> getReaders(NodeRef nodeRef)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
ParameterCheck.mandatory("applyToParents", applyToParents);
|
||||
|
||||
if (nodeRef != null)
|
||||
Set<String> result = Collections.EMPTY_SET;
|
||||
Pair<String, String> iprGroups = getIPRGroups(nodeRef);
|
||||
if (iprGroups != null)
|
||||
{
|
||||
addExtendedSecurityImpl(nodeRef, readers, writers, applyToParents);
|
||||
|
||||
// add to the extended security roles
|
||||
addExtendedSecurityRoles(nodeRef, readers, writers);
|
||||
result = getAuthorities(iprGroups.getFirst());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extended security implementation method
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#getWriters(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Set<String> getWriters(NodeRef nodeRef)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
Set<String> result = Collections.EMPTY_SET;
|
||||
Pair<String, String> iprGroups = getIPRGroups(nodeRef);
|
||||
if (iprGroups != null)
|
||||
{
|
||||
result = getAuthorities(iprGroups.getSecond());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to get authorities for a given group
|
||||
*
|
||||
* @param nodeRef
|
||||
* @param readers
|
||||
* @param writers
|
||||
* @param applyToParents
|
||||
* @param group group name
|
||||
* @return Set<String> immediate authorities
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addExtendedSecurityImpl(final NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
|
||||
private Set<String> getAuthorities(String group)
|
||||
{
|
||||
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);
|
||||
ParameterCheck.mandatory("applyToParents", applyToParents);
|
||||
set(nodeRef, readersAndWriters.getFirst(), readersAndWriters.getSecond());
|
||||
}
|
||||
|
||||
// get the properties
|
||||
final Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
|
||||
/**
|
||||
* @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);
|
||||
|
||||
// update the readers map
|
||||
if (readers != null && readers.size() != 0)
|
||||
{
|
||||
// get reader map
|
||||
Map<String, Integer> readersMap = (Map<String, Integer>)properties.get(PROP_READERS);
|
||||
// remove existing extended security, assuming there is any
|
||||
remove(nodeRef);
|
||||
|
||||
// set the readers property (this will in turn apply the aspect if required)
|
||||
properties.put(PROP_READERS, (Serializable)addToMap(readersMap, readers));
|
||||
}
|
||||
// find groups
|
||||
Pair<String, String> iprGroups = createOrFindIPRGroups(readers, writers);
|
||||
|
||||
// update the writers map
|
||||
if (writers != null && writers.size() != 0)
|
||||
{
|
||||
// get writer map
|
||||
Map<String, Integer> writersMap = (Map<String, Integer>)properties.get(PROP_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());
|
||||
|
||||
// set the writers property (this will in turn apply the aspect if required)
|
||||
properties.put(PROP_WRITERS, (Serializable)addToMap(writersMap, writers));
|
||||
}
|
||||
|
||||
// set properties
|
||||
nodeService.setProperties(nodeRef, properties);
|
||||
// assign groups to node
|
||||
assignIPRGroupsToNode(iprGroups, nodeRef);
|
||||
|
||||
// apply the readers to any renditions of the content
|
||||
if (isRecord(nodeRef))
|
||||
@@ -186,100 +261,299 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
for (ChildAssociationRef assoc : assocs)
|
||||
{
|
||||
NodeRef child = assoc.getChildRef();
|
||||
addExtendedSecurityImpl(child, readers, writers, false);
|
||||
assignIPRGroupsToNode(iprGroups, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IPR groups associated with a given node reference.
|
||||
* <p>
|
||||
* Return null if none found.
|
||||
*
|
||||
* @param nodeRef
|
||||
* @param readers
|
||||
* @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;
|
||||
String iprWriterGroup = null;
|
||||
|
||||
addExtendedSecurityRolesImpl(filePlan, readers, FilePlanRoleService.ROLE_EXTENDED_READERS);
|
||||
addExtendedSecurityRolesImpl(filePlan, writers, FilePlanRoleService.ROLE_EXTENDED_WRITERS);
|
||||
// get all the set permissions
|
||||
Set<AccessPermission> permissions = permissionService.getAllSetPermissions(nodeRef);
|
||||
for (AccessPermission permission : permissions)
|
||||
{
|
||||
// look for the presence of the reader group
|
||||
if (permission.getAuthority().startsWith(GROUP_PREFIX + READER_GROUP_PREFIX))
|
||||
{
|
||||
iprReaderGroup = permission.getAuthority();
|
||||
}
|
||||
// look for the presence of the writer group
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extended security roles implementation
|
||||
* Given a set of readers and writers find or create the appropriate IPR groups.
|
||||
* <p>
|
||||
* 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 authorities authorities
|
||||
* @param roleName role name
|
||||
* @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 void addExtendedSecurityRolesImpl(NodeRef filePlan, Set<String> authorities, String roleName)
|
||||
private Pair<String, String> createOrFindIPRGroups(Set<String> readers, Set<String> writers)
|
||||
{
|
||||
if (authorities != null)
|
||||
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)
|
||||
{
|
||||
for (String authority : authorities)
|
||||
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 ((!authority.equals(PermissionService.ALL_AUTHORITIES) && !authority.equals(PermissionService.OWNER_AUTHORITY)))
|
||||
// if exists and matches we have found our group
|
||||
if (isIPRGroupTrueMatch(group, authorities))
|
||||
{
|
||||
// add the authority to the role
|
||||
filePlanRoleService.assignRoleToAuthority(filePlan, roleName, authority);
|
||||
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 map
|
||||
* @param keys
|
||||
* @param authorities list of authorities
|
||||
* @param group group
|
||||
* @return
|
||||
*/
|
||||
private Map<String, Integer> addToMap(Map<String, Integer> map, Set<String> keys)
|
||||
private boolean isIPRGroupTrueMatch(String group, Set<String> authorities)
|
||||
{
|
||||
if (map == null)
|
||||
{
|
||||
// create map
|
||||
map = new HashMap<String, Integer>(7);
|
||||
}
|
||||
Set<String> contained = authorityService.getContainedAuthorities(null, group, true);
|
||||
return contained.equals(authorities);
|
||||
}
|
||||
|
||||
for (String key : keys)
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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())
|
||||
{
|
||||
if (!key.equals(PermissionService.ALL_AUTHORITIES))
|
||||
result = StringUtils.join(authorities.toArray(), "").hashCode();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
for (String child : children)
|
||||
{
|
||||
if (map.containsKey(key))
|
||||
if (authorityService.authorityExists(child) &&
|
||||
!PermissionService.ALL_AUTHORITIES.equals(child))
|
||||
{
|
||||
// increment reference count
|
||||
Integer count = map.get(key);
|
||||
map.put(key, Integer.valueOf(count.intValue()+1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// add key with initial count
|
||||
map.put(key, Integer.valueOf(1));
|
||||
authorityService.addAuthority(group, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
@Override
|
||||
public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
||||
private void assignIPRGroupsToNode(Pair<String, String> iprGroups, NodeRef nodeRef)
|
||||
{
|
||||
removeExtendedSecurity(nodeRef, readers, writers, true);
|
||||
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#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#remove(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String>writers, boolean applyToParents)
|
||||
public void remove(NodeRef nodeRef)
|
||||
{
|
||||
if (hasExtendedSecurity(nodeRef))
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
Pair<String, String> iprGroups = getIPRGroups(nodeRef);
|
||||
if (iprGroups != null)
|
||||
{
|
||||
removeExtendedSecurityImpl(nodeRef, readers, writers);
|
||||
// remove any extended security that might be present
|
||||
clearPermissions(nodeRef, iprGroups);
|
||||
|
||||
// remove the readers from any renditions of the content
|
||||
if (isRecord(nodeRef))
|
||||
@@ -288,110 +562,85 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||
for (ChildAssociationRef assoc : assocs)
|
||||
{
|
||||
NodeRef child = assoc.getChildRef();
|
||||
removeExtendedSecurityImpl(child, readers, writers);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
clearPermissions(child, iprGroups);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a set of readers and writers from a node reference.
|
||||
* <p>
|
||||
* Removes the aspect and resets the property to null if all readers and writers are removed.
|
||||
* Clear the nodes IPR permissions
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param readers {@link Set} of readers
|
||||
* @param writers {@link Set} of writers
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void removeExtendedSecurityImpl(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
||||
private void clearPermissions(NodeRef nodeRef, Pair<String, String> iprGroups)
|
||||
{
|
||||
Map<String, Integer> readersMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
|
||||
nodeService.setProperty(nodeRef, PROP_READERS, (Serializable)removeFromMap(readersMap, readers));
|
||||
|
||||
Map<String, Integer> writersMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_WRITERS);
|
||||
nodeService.setProperty(nodeRef, PROP_WRITERS, (Serializable)removeFromMap(writersMap, writers));
|
||||
|
||||
if (readersMap == null && writersMap == null)
|
||||
{
|
||||
// remove the aspect
|
||||
nodeService.removeAspect(nodeRef, ASPECT_EXTENDED_SECURITY);
|
||||
}
|
||||
// remove group permissions from node
|
||||
permissionService.clearPermission(nodeRef, iprGroups.getFirst());
|
||||
permissionService.clearPermission(nodeRef, iprGroups.getSecond());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to remove items from map or reduce reference count
|
||||
*
|
||||
* @param map ref count map
|
||||
* @param keys keys
|
||||
* @return Map<String, Integer> ref count map
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedReaders(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
private Map<String, Integer> removeFromMap(Map<String, Integer> map, Set<String> keys)
|
||||
@Override @Deprecated public Set<String> getExtendedReaders(NodeRef nodeRef)
|
||||
{
|
||||
if (map != null && keys != null && keys.size() != 0)
|
||||
{
|
||||
// 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;
|
||||
return getReaders(nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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#getExtendedWriters(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public void removeAllExtendedSecurity(NodeRef nodeRef)
|
||||
@Override @Deprecated public Set<String> getExtendedWriters(NodeRef nodeRef)
|
||||
{
|
||||
removeAllExtendedSecurity(nodeRef, true);
|
||||
return getWriters(nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, boolean)
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
|
||||
*/
|
||||
@Override
|
||||
public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents)
|
||||
@Override @Deprecated public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
||||
{
|
||||
if (hasExtendedSecurity(nodeRef))
|
||||
{
|
||||
removeExtendedSecurity(nodeRef, getExtendedReaders(nodeRef), getExtendedWriters(nodeRef));
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
|
||||
*/
|
||||
@Override @Deprecated public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String>writers, boolean applyToParents)
|
||||
{
|
||||
remove(nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, boolean)
|
||||
*/
|
||||
@Override @Deprecated public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents)
|
||||
{
|
||||
remove(nodeRef);
|
||||
}
|
||||
}
|
||||
|
@@ -18,8 +18,6 @@
|
||||
*/
|
||||
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.annotation.BehaviourKind.CLASS;
|
||||
import static org.alfresco.repo.security.authentication.AuthenticationUtil.getSystemUserName;
|
||||
@@ -374,13 +372,29 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
boolean inheritanceAllowed = isInheritanceAllowed(nodeRef, isParentNodeFilePlan);
|
||||
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);
|
||||
|
||||
// re-add keep'er permissions
|
||||
for (AccessPermission keeper : keepPerms)
|
||||
{
|
||||
setPermission(nodeRef, keeper.getAuthority(), keeper.getPermission());
|
||||
}
|
||||
|
||||
if (!inheritanceAllowed)
|
||||
{
|
||||
getPermissionService().setPermission(nodeRef, EXTENDED_READER, READ_RECORDS, true);
|
||||
getPermissionService().setPermission(nodeRef, EXTENDED_WRITER, FILING, true);
|
||||
String adminRole = getAdminRole(nodeRef);
|
||||
getPermissionService().setPermission(nodeRef, adminRole, RMPermissionModel.FILING, true);
|
||||
}
|
||||
@@ -426,9 +440,20 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
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)
|
||||
{
|
||||
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)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -485,20 +510,14 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
for (AccessPermission recordPermission : origionalRecordPerms)
|
||||
{
|
||||
String permission = recordPermission.getPermission();
|
||||
String authority = recordPermission.getAuthority();
|
||||
if ((RMPermissionModel.FILING.equals(permission) || RMPermissionModel.READ_RECORDS.equals(permission)) &&
|
||||
recordPermission.isSetDirectly() &&
|
||||
!ExtendedReaderDynamicAuthority.EXTENDED_READER.equals(authority) &&
|
||||
!ExtendedWriterDynamicAuthority.EXTENDED_WRITER.equals(authority))
|
||||
recordPermission.isSetDirectly())
|
||||
{
|
||||
// then we can assume this is a permission we want to preserve
|
||||
keepPerms.add(recordPermission);
|
||||
}
|
||||
}
|
||||
|
||||
// clear all existing permissions and start again
|
||||
permissionService.deletePermissions(record);
|
||||
|
||||
// re-setup the records permissions
|
||||
setupPermissions(destinationAssocRef.getParentRef(), record);
|
||||
|
||||
@@ -580,7 +599,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -25,7 +25,6 @@ import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -47,12 +46,12 @@ import org.alfresco.repo.version.VersionModel;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
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.Version;
|
||||
import org.alfresco.service.cmr.version.VersionHistory;
|
||||
import org.alfresco.service.cmr.version.VersionType;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.alfresco.util.PropertyMap;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
@@ -121,9 +120,6 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
|
||||
/** extended security service */
|
||||
private ExtendedSecurityService extendedSecurityService;
|
||||
|
||||
/** ownable service */
|
||||
private OwnableService ownableService;
|
||||
|
||||
/**
|
||||
* @param filePlanService file plan service
|
||||
*/
|
||||
@@ -188,14 +184,6 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
|
||||
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)
|
||||
*/
|
||||
@@ -688,13 +676,8 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
|
||||
{
|
||||
public NodeRef doWork() throws Exception
|
||||
{
|
||||
// get the documents readers
|
||||
Long aclId = nodeService.getNodeAclId(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);
|
||||
// get the documents readers and writers
|
||||
Pair<Set<String>, Set<String>> readersAndWriters = extendedPermissionService.getReadersAndWriters(nodeRef);
|
||||
|
||||
// grab the frozen state
|
||||
NodeRef currentFrozenState = currentVersion.getFrozenStateNodeRef();
|
||||
@@ -734,13 +717,7 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
|
||||
linkToPreviousVersionRecord(nodeRef, record);
|
||||
|
||||
// set the extended security
|
||||
Set<String> combinedWriters = new HashSet<String>(writers);
|
||||
if (owner != null && !owner.isEmpty() && !owner.equals(OwnableService.NO_OWNER))
|
||||
{
|
||||
combinedWriters.add(owner);
|
||||
}
|
||||
combinedWriters.add(authenticationUtil.getFullyAuthenticatedUser());
|
||||
extendedSecurityService.addExtendedSecurity(record, readers, combinedWriters);
|
||||
extendedSecurityService.set(record, readersAndWriters);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
@@ -20,7 +20,9 @@ package org.alfresco.repo.security.permissions.impl;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.util.Pair;
|
||||
|
||||
/**
|
||||
* Extended Permission Service Interface used in RM.
|
||||
@@ -31,4 +33,18 @@ import org.alfresco.service.cmr.security.PermissionService;
|
||||
public interface ExtendedPermissionService extends PermissionService
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@@ -29,16 +29,17 @@ 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.security.ExtendedReaderDynamicAuthority;
|
||||
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.repo.security.permissions.AccessControlEntry;
|
||||
import org.alfresco.repo.security.permissions.AccessControlList;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.AuthorityType;
|
||||
import org.alfresco.service.cmr.security.OwnableService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
/**
|
||||
@@ -303,13 +304,17 @@ public class RMPermissionServiceImpl extends PermissionServiceImpl
|
||||
final String adminRole = getAdminRole(nodeRef);
|
||||
if (nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT) && isNotBlank(adminRole) && !inheritParentPermissions)
|
||||
{
|
||||
setPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true);
|
||||
setPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true);
|
||||
setPermission(nodeRef, adminRole, RMPermissionModel.FILING, true);
|
||||
setPermission(nodeRef, adminRole, RMPermissionModel.FILING, true);
|
||||
}
|
||||
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)
|
||||
{
|
||||
String adminRole = null;
|
||||
@@ -320,4 +325,28 @@ public class RMPermissionServiceImpl extends PermissionServiceImpl
|
||||
}
|
||||
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,241 @@
|
||||
/*
|
||||
* 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());
|
||||
}
|
||||
}
|
||||
}
|
@@ -35,14 +35,14 @@ public class RM1429Test extends DeleteHoldTest
|
||||
{
|
||||
public void testDeleteHoldWithoutPermissionsOnChildren()
|
||||
{
|
||||
// Create the test hold
|
||||
final NodeRef hold = createAndCheckHold();
|
||||
|
||||
doTestInTransaction(new Test<Void>()
|
||||
final NodeRef hold = doTestInTransaction(new Test<NodeRef>()
|
||||
{
|
||||
@Override
|
||||
public Void run()
|
||||
public NodeRef run()
|
||||
{
|
||||
// Create the test hold
|
||||
NodeRef hold = createAndCheckHold();
|
||||
|
||||
// Add the user to the RM Manager role
|
||||
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
|
||||
|
||||
@@ -55,7 +55,7 @@ public class RM1429Test extends DeleteHoldTest
|
||||
// Add record folder to the hold
|
||||
holdService.addToHold(hold, rmFolder);
|
||||
|
||||
return null;
|
||||
return hold;
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -35,14 +35,14 @@ public class RM1463Test extends DeleteHoldTest
|
||||
{
|
||||
public void testAddRecordFolderToHoldWithoutFilingPermissionOnRecordFolder()
|
||||
{
|
||||
// Create hold
|
||||
final NodeRef hold = createAndCheckHold();
|
||||
|
||||
doTestInTransaction(new Test<Void>()
|
||||
final NodeRef hold = doTestInTransaction(new Test<NodeRef>()
|
||||
{
|
||||
@Override
|
||||
public Void run()
|
||||
public NodeRef run()
|
||||
{
|
||||
// Create hold
|
||||
NodeRef hold = createAndCheckHold();
|
||||
|
||||
// Add the user to the RM Manager role
|
||||
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
|
||||
|
||||
@@ -52,7 +52,7 @@ public class RM1463Test extends DeleteHoldTest
|
||||
// Give the user only read permissions on the record folder
|
||||
permissionService.setPermission(rmFolder, userName, RMPermissionModel.READ_RECORDS, true);
|
||||
|
||||
return null;
|
||||
return hold;
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -35,14 +35,14 @@ public class RM1464Test extends DeleteHoldTest
|
||||
{
|
||||
public void testAddRecordFolderToHoldWithoutFilingPermissionOnHold()
|
||||
{
|
||||
// Create hold
|
||||
final NodeRef hold = createAndCheckHold();
|
||||
|
||||
doTestInTransaction(new Test<Void>()
|
||||
final NodeRef hold = doTestInTransaction(new Test<NodeRef>()
|
||||
{
|
||||
@Override
|
||||
public Void run()
|
||||
public NodeRef run()
|
||||
{
|
||||
// Create hold
|
||||
NodeRef hold = createAndCheckHold();
|
||||
|
||||
// Add the user to the RM Manager role
|
||||
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_RECORDS_MANAGER, userName);
|
||||
|
||||
@@ -52,7 +52,7 @@ public class RM1464Test extends DeleteHoldTest
|
||||
// Give the user filing permissions on the record folder
|
||||
permissionService.setPermission(rmFolder, userName, RMPermissionModel.FILING, true);
|
||||
|
||||
return null;
|
||||
return hold;
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 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.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;
|
||||
}
|
||||
|
||||
List<NodeRef> allContained = filePlanService.getAllContained(nodeRefCategory1, true);
|
||||
assertTrue(allContained.size() == 2002);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
@@ -61,6 +61,9 @@ public class MoveInplaceRecordTest extends BaseRMTestCase
|
||||
private Set<String> extendedReadersBeforeMove;
|
||||
private Set<String> extendedWritersBeforeMove;
|
||||
|
||||
// primary parent of record
|
||||
private NodeRef primaryParentBeforeMove;
|
||||
|
||||
public void given()
|
||||
{
|
||||
// Create the destination folder
|
||||
@@ -84,8 +87,14 @@ public class MoveInplaceRecordTest extends BaseRMTestCase
|
||||
// Check that the document is a record now
|
||||
assertTrue(recordService.isRecord(dmDocument));
|
||||
|
||||
extendedReadersBeforeMove = extendedSecurityService.getExtendedReaders(dmDocument);
|
||||
extendedWritersBeforeMove = extendedSecurityService.getExtendedWriters(dmDocument);
|
||||
extendedReadersBeforeMove = extendedSecurityService.getReaders(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()
|
||||
@@ -105,15 +114,27 @@ public class MoveInplaceRecordTest extends BaseRMTestCase
|
||||
|
||||
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
|
||||
assertEquals(0, nodeService.getChildAssocs(dmFolder).size());
|
||||
List<ChildAssociationRef> destinationFolderChildAssocs = nodeService.getChildAssocs(destinationDmFolder);
|
||||
assertEquals(1, destinationFolderChildAssocs.size());
|
||||
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
|
||||
Set<String> extendedReadersAfterMove = extendedSecurityService.getExtendedReaders(dmDocument);
|
||||
Set<String> extendedWritersAfterMove = extendedSecurityService.getExtendedWriters(dmDocument);
|
||||
Set<String> extendedReadersAfterMove = extendedSecurityService.getReaders(dmDocument);
|
||||
Set<String> extendedWritersAfterMove = extendedSecurityService.getWriters(dmDocument);
|
||||
|
||||
assertEquals(extendedReadersBeforeMove.size(), extendedReadersAfterMove.size());
|
||||
assertEquals(extendedWritersBeforeMove.size(), extendedWritersAfterMove.size());
|
||||
|
@@ -21,6 +21,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.test.util.BaseRMTestCase;
|
||||
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.repository.NodeRef;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
@@ -53,6 +54,8 @@ public class FileReportActionTest extends BaseRMTestCase
|
||||
|
||||
private void fileReport(final String mimeType)
|
||||
{
|
||||
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||
|
||||
// create record folder
|
||||
final NodeRef recordFolder = recordFolderService.createRecordFolder(rmContainer, GUID.generate());
|
||||
|
||||
|
@@ -110,24 +110,27 @@ public class FileToActionTest extends BaseRMTestCase
|
||||
// create record from document
|
||||
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;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
|
@@ -104,7 +104,8 @@ public class RejectActionTest extends BaseRMTestCase
|
||||
assertTrue(nodeService.getParentAssocs(dmDocument).size() == 1);
|
||||
|
||||
// The extended reader information should be removed
|
||||
assertNull(extendedSecurityService.getExtendedReaders(dmDocument));
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(dmDocument));
|
||||
assertTrue(extendedSecurityService.getReaders(dmDocument).isEmpty());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@@ -1,26 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
it st * #%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.legacy.service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
@@ -92,64 +99,29 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(rmFolder));
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(record));
|
||||
|
||||
assertNull(extendedSecurityService.getExtendedReaders(record));
|
||||
assertNull(extendedSecurityService.getExtendedWriters(record));
|
||||
assertTrue(extendedSecurityService.getReaders(record).isEmpty());
|
||||
assertTrue(extendedSecurityService.getWriters(record).isEmpty());
|
||||
|
||||
Set<String> extendedReaders = new HashSet<String>(2);
|
||||
extendedReaders.add(monkey);
|
||||
extendedReaders.add(elephant);
|
||||
|
||||
extendedSecurityService.addExtendedSecurity(record, extendedReaders, null);
|
||||
|
||||
Map<String, Integer> testMap = new HashMap<String, Integer>(2);
|
||||
testMap.put(monkey, Integer.valueOf(1));
|
||||
testMap.put(elephant, Integer.valueOf(1));
|
||||
|
||||
checkExtendedReaders(record, testMap);
|
||||
extendedSecurityService.set(record, extendedReaders, null);
|
||||
checkExtendedReaders(record, extendedReaders);
|
||||
|
||||
Set<String> extendedReadersToo = new HashSet<String>(2);
|
||||
extendedReadersToo.add(monkey);
|
||||
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);
|
||||
testMapToo.put(monkey, Integer.valueOf(1));
|
||||
testMapToo.put(snake, Integer.valueOf(1));
|
||||
// test remove
|
||||
extendedSecurityService.remove(recordToo);
|
||||
|
||||
Map<String, Integer> testMapThree = new HashMap<String, Integer>(3);
|
||||
testMapThree.put(monkey, Integer.valueOf(2));
|
||||
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);
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(recordToo));
|
||||
assertTrue(extendedSecurityService.getReaders(recordToo).isEmpty());
|
||||
assertTrue(extendedSecurityService.getWriters(recordToo).isEmpty());
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -163,12 +135,12 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
||||
|
||||
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
|
||||
{
|
||||
testMap.put(monkey, Integer.valueOf(1));
|
||||
testMap.put(elephant, Integer.valueOf(1));
|
||||
extendedReaders.add(monkey);
|
||||
extendedReaders.add(elephant);
|
||||
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(filePlan));
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(rmContainer));
|
||||
@@ -177,15 +149,12 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordCategory));
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordFolder));
|
||||
|
||||
assertNull(extendedSecurityService.getExtendedReaders(record));
|
||||
assertTrue(extendedSecurityService.getReaders(record).isEmpty());
|
||||
|
||||
Set<String> extendedReaders = new HashSet<String>(2);
|
||||
extendedReaders.add(monkey);
|
||||
extendedReaders.add(elephant);
|
||||
extendedSecurityService.set(record, extendedReaders, null);
|
||||
|
||||
extendedSecurityService.addExtendedSecurity(record, extendedReaders, null);
|
||||
checkExtendedReaders(record, extendedReaders);
|
||||
|
||||
checkExtendedReaders(record, testMap);
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordCategory));
|
||||
assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordFolder));
|
||||
|
||||
@@ -197,31 +166,21 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
||||
@Override
|
||||
public void test(Void result) throws Exception
|
||||
{
|
||||
checkExtendedReaders(record, testMap);
|
||||
checkExtendedReaders(record, extendedReaders);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void checkExtendedReaders(NodeRef nodeRef, Map<String, Integer> testMap)
|
||||
/**
|
||||
* Check extended readers helper method
|
||||
*/
|
||||
private void checkExtendedReaders(NodeRef nodeRef, Set<String> testReaders)
|
||||
{
|
||||
assertTrue(extendedSecurityService.hasExtendedSecurity(nodeRef));
|
||||
|
||||
Map<String, Integer> readersMap = (Map<String,Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
|
||||
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);
|
||||
Set<String> readers = extendedSecurityService.getReaders(nodeRef);
|
||||
assertNotNull(readers);
|
||||
assertEquals(testMap.size(), readers.size());
|
||||
assertEquals(testReaders, readers);
|
||||
}
|
||||
|
||||
public void testDifferentUsersDifferentPermissions()
|
||||
|
@@ -24,8 +24,6 @@ import java.util.Set;
|
||||
|
||||
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.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.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -1232,10 +1230,6 @@ public class FilePlanPermissionServiceImplTest extends BaseRMTestCase
|
||||
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());
|
||||
assertTrue(accessPermissions.containsKey(adminRole));
|
||||
assertEquals(RMPermissionModel.FILING, accessPermissions.get(adminRole));
|
||||
|
@@ -29,8 +29,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.record.RecordService;
|
||||
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.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
@@ -172,22 +170,13 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
||||
|
||||
public void testExtendedWriters() throws Exception
|
||||
{
|
||||
final ExtendedReaderDynamicAuthority readerDy = (ExtendedReaderDynamicAuthority)applicationContext.getBean("extendedReaderDynamicAuthority");
|
||||
final ExtendedWriterDynamicAuthority writerDy = (ExtendedWriterDynamicAuthority)applicationContext.getBean("extendedWriterDynamicAuthority");
|
||||
|
||||
doTestInTransaction(new Test<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void run()
|
||||
{
|
||||
assertNull(extendedSecurityService.getExtendedReaders(recordOne));
|
||||
assertNull(extendedSecurityService.getExtendedWriters(recordOne));
|
||||
|
||||
assertFalse(readerDy.hasAuthority(recordOne, dmCollaborator));
|
||||
assertFalse(writerDy.hasAuthority(recordOne, dmCollaborator));
|
||||
|
||||
assertFalse(readerDy.hasAuthority(filePlan, dmCollaborator));
|
||||
assertFalse(writerDy.hasAuthority(filePlan, dmCollaborator));
|
||||
assertTrue(extendedSecurityService.getReaders(recordOne).isEmpty());
|
||||
assertTrue(extendedSecurityService.getWriters(recordOne).isEmpty());
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -200,16 +189,9 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
||||
{
|
||||
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(recordOne, RMPermissionModel.READ_RECORDS));
|
||||
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.EDIT_NON_RECORD_METADATA));
|
||||
|
||||
assertFalse(readerDy.hasAuthority(filePlan, dmCollaborator));
|
||||
assertFalse(writerDy.hasAuthority(filePlan, dmCollaborator));
|
||||
|
||||
return null;
|
||||
}
|
||||
}, dmCollaborator);
|
||||
@@ -221,10 +203,10 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
||||
{
|
||||
Set<String> writers = new HashSet<String>(1);
|
||||
writers.add(dmCollaborator);
|
||||
extendedSecurityService.addExtendedSecurity(recordOne, null, writers);
|
||||
extendedSecurityService.set(recordOne, null, writers);
|
||||
|
||||
assertNull(extendedSecurityService.getExtendedReaders(recordOne));
|
||||
assertFalse(extendedSecurityService.getExtendedWriters(recordOne).isEmpty());
|
||||
assertTrue(extendedSecurityService.getReaders(recordOne).isEmpty());
|
||||
assertFalse(extendedSecurityService.getWriters(recordOne).isEmpty());
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -238,9 +220,7 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(recordOne, RMPermissionModel.READ_RECORDS));
|
||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(recordOne, RMPermissionModel.FILING));
|
||||
|
||||
assertFalse(readerDy.hasAuthority(recordOne, dmCollaborator));
|
||||
assertTrue(writerDy.hasAuthority(recordOne, dmCollaborator));
|
||||
|
||||
// ALLOWED, becuase users have been added to the in-place roles
|
||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS));
|
||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(filePlan, RMPermissionModel.EDIT_NON_RECORD_METADATA));
|
||||
|
||||
@@ -302,7 +282,8 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
||||
|
||||
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, // record category
|
||||
AccessStatus.DENIED, // record folder
|
||||
@@ -311,7 +292,8 @@ public class RecordServiceImplTest extends BaseRMTestCase
|
||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(filePlan,
|
||||
RMPermissionModel.VIEW_RECORDS));
|
||||
|
||||
checkPermissions(FILING, AccessStatus.DENIED, // file plan
|
||||
checkPermissions(FILING,
|
||||
AccessStatus.DENIED, // file plan
|
||||
AccessStatus.DENIED, // unfiled container
|
||||
AccessStatus.DENIED, // record category
|
||||
AccessStatus.DENIED, // record folder
|
||||
|
@@ -262,6 +262,8 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
|
||||
/** collaboration site users */
|
||||
protected String dmConsumer;
|
||||
protected NodeRef dmConsumerNodeRef;
|
||||
protected String dmContributor;
|
||||
protected NodeRef dmContributorNodeRef;
|
||||
protected String dmCollaborator;
|
||||
protected NodeRef dmCollaboratorNodeRef;
|
||||
|
||||
@@ -412,11 +414,12 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
// As system user
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||
|
||||
// Do the tear down
|
||||
tearDownImpl();
|
||||
AuthenticationUtil.runAsSystem(() ->
|
||||
{
|
||||
tearDownImpl();
|
||||
return null;
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -591,16 +594,21 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
|
||||
|
||||
protected void setupTestUsers(final NodeRef filePlan)
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
||||
AuthenticationUtil.runAs(() ->
|
||||
{
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
|
||||
setupTestUsersImpl(filePlan);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
setupTestUsersImpl(filePlan);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
},
|
||||
AuthenticationUtil.getAdminUserName());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -676,20 +684,16 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
|
||||
*/
|
||||
protected void setupMultiHierarchyTestData()
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
@Override
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
// As system user
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||
AuthenticationUtil.runAsSystem(() ->
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(() ->
|
||||
{
|
||||
// Do setup
|
||||
setupMultiHierarchyTestDataImpl();
|
||||
|
||||
// Do setup
|
||||
setupMultiHierarchyTestDataImpl();
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return null;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -764,6 +768,10 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
|
||||
dmConsumerNodeRef = createPerson(dmConsumer);
|
||||
siteService.setMembership(collabSiteId, dmConsumer, SiteModel.SITE_CONSUMER);
|
||||
|
||||
dmContributor = GUID.generate();
|
||||
dmContributorNodeRef = createPerson(dmContributor);
|
||||
siteService.setMembership(collabSiteId, dmContributor, SiteModel.SITE_CONTRIBUTOR);
|
||||
|
||||
dmCollaborator = GUID.generate();
|
||||
dmCollaboratorNodeRef = createPerson(dmCollaborator);
|
||||
siteService.setMembership(collabSiteId, dmCollaborator, SiteModel.SITE_COLLABORATOR);
|
||||
|
@@ -30,6 +30,7 @@ import java.util.Set;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.action.impl.CompleteEventAction;
|
||||
import org.alfresco.module.org_alfresco_module_rm.action.impl.CutOffAction;
|
||||
import org.alfresco.module.org_alfresco_module_rm.action.impl.DestroyAction;
|
||||
import org.alfresco.module.org_alfresco_module_rm.action.impl.TransferAction;
|
||||
@@ -292,4 +293,20 @@ public class CommonRMTestUtils implements RecordsManagementModel
|
||||
|
||||
return filePlanRoleService.createRole(filePlan, roleName, roleName, capabilities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to complete event on disposable item
|
||||
*
|
||||
* @param disposableItem disposable item (record or record folder)
|
||||
* @param eventName event name
|
||||
*/
|
||||
public void completeEvent(NodeRef disposableItem, String eventName)
|
||||
{
|
||||
// build action properties
|
||||
Map<String, Serializable> params = new HashMap<String, Serializable>(1);
|
||||
params.put(CompleteEventAction.PARAM_EVENT_NAME, eventName);
|
||||
|
||||
// complete event
|
||||
actionService.executeRecordsManagementAction(disposableItem, CompleteEventAction.NAME, params);
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
}
|
||||
}
|
@@ -18,13 +18,10 @@
|
||||
*/
|
||||
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.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -164,15 +161,6 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
|
||||
// verify permission set on target node
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,14 +174,6 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
|
||||
// verify permission set on target node
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,14 +187,6 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
|
||||
// verify permission deleted on target node
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,16 +200,6 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
|
||||
// verify permission set on target node
|
||||
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));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,16 +213,6 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
|
||||
// verify permission set on target node
|
||||
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));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,13 +226,6 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
|
||||
// verify permission set on target node
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -294,13 +239,6 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
|
||||
// verify permission set on target node
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,23 +252,18 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
perms.add(new AccessPermissionImpl(RMPermissionModel.READ_RECORDS, AccessStatus.ALLOWED, AUTHORITY, 0));
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, times(1)).clearPermission(nodeRef, null);
|
||||
verify(mockedPermissionService, times(1)).setPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true);
|
||||
verify(mockedPermissionService, times(1)).setPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true);
|
||||
verify(mockedOwnableService, times(1)).setOwner(nodeRef, OwnableService.NO_OWNER);
|
||||
verify(mockedPermissionService).getAllSetPermissions(nodeRef);
|
||||
verify(mockedPermissionService).setInheritParentPermissions(nodeRef, isInherited);
|
||||
verify(mockedPermissionService).clearPermission(nodeRef, null);
|
||||
verify(mockedOwnableService).setOwner(nodeRef, OwnableService.NO_OWNER);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -341,21 +274,20 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
* @param read verification mode relating to setting read 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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,7 +303,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
filePlanPermissionService.setupRecordCategoryPermissions(rootRecordCategory);
|
||||
|
||||
// verify permission init
|
||||
verifyInitPermissions(filePlan, rootRecordCategory, never(), times(1));
|
||||
verifyInitPermissions(filePlan, rootRecordCategory, never(), times(1), true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -387,7 +319,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
filePlanPermissionService.setupRecordCategoryPermissions(recordCategory);
|
||||
|
||||
// verify permission init
|
||||
verifyInitPermissions(rootRecordCategory, recordCategory, times(1), times(1));
|
||||
verifyInitPermissions(rootRecordCategory, recordCategory, times(1), times(1), false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -403,7 +335,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
filePlanPermissionService.setupPermissions(recordCategory, newRecordFolder);
|
||||
|
||||
// verify permission init
|
||||
verifyInitPermissions(recordCategory, newRecordFolder, times(1), times(1));
|
||||
verifyInitPermissions(recordCategory, newRecordFolder, times(1), times(1), false, true);
|
||||
|
||||
}
|
||||
|
||||
@@ -420,7 +352,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
filePlanPermissionService.setupPermissions(newRecordFolder, newRecord);
|
||||
|
||||
// verify permission init
|
||||
verifyInitPermissions(newRecordFolder, newRecord, times(1), times(1));
|
||||
verifyInitPermissions(newRecordFolder, newRecord, times(1), times(1), false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -436,7 +368,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
filePlanPermissionService.setupPermissions(filePlan, holdContainer);
|
||||
|
||||
// verify permissions are set-up correctly
|
||||
verifyInitPermissions(filePlan, holdContainer, times(1), times(1));
|
||||
verifyInitPermissions(filePlan, holdContainer, times(1), times(1), false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -452,7 +384,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
filePlanPermissionService.setupPermissions(holdContainer, hold);
|
||||
|
||||
// verify permissions are set-up correctly
|
||||
verifyInitPermissions(holdContainer, hold, never(), times(1));
|
||||
verifyInitPermissions(holdContainer, hold, never(), times(1), false, false);
|
||||
|
||||
}
|
||||
|
||||
@@ -469,7 +401,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
filePlanPermissionService.setupPermissions(filePlan, unfiledRecordContainer);
|
||||
|
||||
// verify permissions are set-up correctly
|
||||
verifyInitPermissions(filePlan, unfiledRecordContainer, times(1), times(1));
|
||||
verifyInitPermissions(filePlan, unfiledRecordContainer, times(1), times(1), false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -485,7 +417,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
filePlanPermissionService.setupPermissions(unfiledRecordContainer, unfiledRecordFolder);
|
||||
|
||||
// verify permissions are set-up correctly
|
||||
verifyInitPermissions(unfiledRecordContainer, unfiledRecordFolder, never(), times(1));
|
||||
verifyInitPermissions(unfiledRecordContainer, unfiledRecordFolder, never(), times(1), false, true);
|
||||
|
||||
}
|
||||
|
||||
@@ -502,7 +434,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest
|
||||
filePlanPermissionService.setupPermissions(unfiledRecordFolder, unfiledRecord);
|
||||
|
||||
// verify permission init
|
||||
verifyInitPermissions(unfiledRecordFolder, unfiledRecord, times(1), times(1));
|
||||
verifyInitPermissions(unfiledRecordFolder, unfiledRecord, times(1), times(1), false, true);
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* #%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;
|
||||
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.GUID;
|
||||
|
||||
/**
|
||||
* Utilities helpful when mocking Alfresco constructs.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
* @since 2.4.a
|
||||
*/
|
||||
public class AlfMock
|
||||
{
|
||||
/**
|
||||
* Helper to generate random text value suitable for a property
|
||||
* value or node name
|
||||
*/
|
||||
public static String generateText()
|
||||
{
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to generate a qname.
|
||||
*/
|
||||
public static QName generateQName()
|
||||
{
|
||||
return generateQName(GUID.generate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to generate a qname.
|
||||
*/
|
||||
public static QName generateQName(String uri)
|
||||
{
|
||||
return QName.createQName(uri, GUID.generate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to generate a node reference.
|
||||
*
|
||||
* @return {@link NodeRef} node reference that behaves like a node that exists in the spaces store
|
||||
*/
|
||||
public static NodeRef generateNodeRef(NodeService mockedNodeService)
|
||||
{
|
||||
return generateNodeRef(mockedNodeService, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to generate a node reference of a particular type.
|
||||
*
|
||||
* @param type content type qualified name
|
||||
* @return {@link NodeRef} node reference that behaves like a node that exists in the spaces store with
|
||||
* the content type provided
|
||||
*/
|
||||
public static NodeRef generateNodeRef(NodeService mockedNodeService, QName type)
|
||||
{
|
||||
return generateNodeRef(mockedNodeService, type, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to generate a cm:content node reference with a given name.
|
||||
*
|
||||
* @param name content name
|
||||
* @return NodeRef node reference
|
||||
*/
|
||||
public static NodeRef generateCmContent(NodeService mockedNodeService, String name)
|
||||
{
|
||||
NodeRef nodeRef = generateNodeRef(mockedNodeService, ContentModel.TYPE_CONTENT, true);
|
||||
doReturn(name).when(mockedNodeService).getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to generate a node reference of a particular type with a given existence characteristic.
|
||||
*
|
||||
* @param type content type qualified name
|
||||
* @param exists indicates whether this node should behave like a node that exists or not
|
||||
* @return {@link NodeRef} node reference that behaves like a node that exists (or not) in the spaces store with
|
||||
* the content type provided
|
||||
*/
|
||||
public static NodeRef generateNodeRef(NodeService mockedNodeService, QName type, boolean exists)
|
||||
{
|
||||
NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate());
|
||||
when(mockedNodeService.exists(eq(nodeRef))).thenReturn(exists);
|
||||
if (type != null)
|
||||
{
|
||||
when(mockedNodeService.getType(eq(nodeRef))).thenReturn(type);
|
||||
}
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* 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