writers);
+
+ /**
+ * Add extended security for the specified authorities to a node.
+ *
+ * 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 readers, Set 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 readers, Set writers);
+
+ /**
+ * Remove the extended security for the specified authorities from a node.
+ *
+ * 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 readers, Set 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);
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java b/rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java
similarity index 96%
rename from rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java
rename to rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java
index 198139ff11..4b166ba686 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java
+++ b/rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/ExtendedReaderDynamicAuthority.java
@@ -1,97 +1,98 @@
-/*
- * #%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 .
- * #L%
- */
-
-package org.alfresco.module.org_alfresco_module_rm.security;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
-import org.alfresco.repo.security.permissions.PermissionReference;
-import org.alfresco.service.cmr.repository.NodeRef;
-
-/**
- * Extended readers dynamic authority implementation.
- *
- * @author Roy Wetherall
- * @since 2.1
- */
-public class ExtendedReaderDynamicAuthority extends ExtendedSecurityBaseDynamicAuthority
-{
- /** Extended reader role */
- public static final String EXTENDED_READER = "ROLE_EXTENDED_READER";
-
- /**
- * @see org.alfresco.repo.security.permissions.DynamicAuthority#getAuthority()
- */
- @Override
- public String getAuthority()
- {
- return EXTENDED_READER;
- }
-
- /**
- * @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
- */
- @Override
- public Set requiredFor()
- {
- if (requiredFor == null)
- {
- requiredFor = Collections.singleton(getModelDAO().getPermissionReference(null, RMPermissionModel.READ_RECORDS));
- }
-
- return requiredFor;
- }
-
- /**
- * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef)
- */
- @SuppressWarnings("unchecked")
- protected Set getAuthorites(NodeRef nodeRef)
- {
- Set result = null;
-
- Map readerMap = (Map)getNodeService().getProperty(nodeRef, PROP_READERS);
- if (readerMap != null)
- {
- result = readerMap.keySet();
- }
-
- return result;
- }
-
- /**
- * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName()
- */
- @Override
- protected String getTransactionCacheName()
- {
- return "rm.extendedreaderdynamicauthority";
- }
-}
+/*
+ * #%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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.security;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
+import org.alfresco.repo.security.permissions.PermissionReference;
+import org.alfresco.service.cmr.repository.NodeRef;
+
+/**
+ * Extended readers dynamic authority implementation.
+ *
+ * @author Roy Wetherall
+ * @since 2.1
+ */
+@Deprecated
+public class ExtendedReaderDynamicAuthority extends ExtendedSecurityBaseDynamicAuthority
+{
+ /** Extended reader role */
+ public static final String EXTENDED_READER = "ROLE_EXTENDED_READER";
+
+ /**
+ * @see org.alfresco.repo.security.permissions.DynamicAuthority#getAuthority()
+ */
+ @Override
+ public String getAuthority()
+ {
+ return EXTENDED_READER;
+ }
+
+ /**
+ * @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
+ */
+ @Override
+ public Set requiredFor()
+ {
+ if (requiredFor == null)
+ {
+ requiredFor = Collections.singleton(getModelDAO().getPermissionReference(null, RMPermissionModel.READ_RECORDS));
+ }
+
+ return requiredFor;
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @SuppressWarnings("unchecked")
+ protected Set getAuthorites(NodeRef nodeRef)
+ {
+ Set result = null;
+
+ Map readerMap = (Map)getNodeService().getProperty(nodeRef, PROP_READERS);
+ if (readerMap != null)
+ {
+ result = readerMap.keySet();
+ }
+
+ return result;
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName()
+ */
+ @Override
+ protected String getTransactionCacheName()
+ {
+ return "rm.extendedreaderdynamicauthority";
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityBaseDynamicAuthority.java b/rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityBaseDynamicAuthority.java
similarity index 97%
rename from rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityBaseDynamicAuthority.java
rename to rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityBaseDynamicAuthority.java
index 620cede221..d48150633b 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityBaseDynamicAuthority.java
+++ b/rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityBaseDynamicAuthority.java
@@ -1,191 +1,192 @@
-/*
- * #%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 .
- * #L%
- */
-
-package org.alfresco.module.org_alfresco_module_rm.security;
-
-import java.util.Map;
-import java.util.Set;
-
-import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
-import org.alfresco.repo.security.permissions.DynamicAuthority;
-import org.alfresco.repo.security.permissions.PermissionReference;
-import org.alfresco.repo.security.permissions.impl.ModelDAO;
-import org.alfresco.repo.transaction.TransactionalResourceHelper;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.security.AuthorityService;
-import org.alfresco.util.Pair;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-
-/**
- * Extended readers dynamic authority implementation.
- *
- * @author Roy Wetherall
- * @since 2.1
- */
-public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAuthority,
- RecordsManagementModel,
- ApplicationContextAware
-{
- /** Authority service */
- private AuthorityService authorityService;
-
- /** Extended security service */
- private ExtendedSecurityService extendedSecurityService;
-
- /** Node service */
- private NodeService nodeService;
-
- /** Application context */
- protected ApplicationContext applicationContext;
-
- /** model DAO */
- protected ModelDAO modelDAO;
-
- /** permission reference */
- protected Set requiredFor;
-
- // NOTE: we get the services directly from the application context in this way to avoid
- // cyclic relationships and issues when loading the application context
-
- /**
- * @return authority service
- */
- protected AuthorityService getAuthorityService()
- {
- if (authorityService == null)
- {
- authorityService = (AuthorityService)applicationContext.getBean("authorityService");
- }
- return authorityService;
- }
-
- /**
- * @return extended security service
- */
- protected ExtendedSecurityService getExtendedSecurityService()
- {
- if (extendedSecurityService == null)
- {
- extendedSecurityService = (ExtendedSecurityService)applicationContext.getBean("extendedSecurityService");
- }
- return extendedSecurityService;
- }
-
- /**
- * @return node service
- */
- protected NodeService getNodeService()
- {
- if (nodeService == null)
- {
- nodeService = (NodeService)applicationContext.getBean("dbNodeService");
- }
- return nodeService;
- }
-
- /**
- * @return model DAO
- */
- protected ModelDAO getModelDAO()
- {
- if (modelDAO == null)
- {
- modelDAO = (ModelDAO)applicationContext.getBean("permissionsModelDAO");
- }
- return modelDAO;
- }
-
- /**
- * @return String transaction cache name
- */
- protected abstract String getTransactionCacheName();
-
- /**
- * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
- */
- @Override
- public void setApplicationContext(ApplicationContext applicationContext)
- {
- this.applicationContext = applicationContext;
- }
-
- /**
- * Gets a list of the authorities from the extended security aspect that this dynamic
- * authority is checking against.
- *
- * @param nodeRef
- * @return
- */
- protected abstract Set getAuthorites(NodeRef nodeRef);
-
- /**
- * @see org.alfresco.repo.security.permissions.DynamicAuthority#hasAuthority(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
- */
- @Override
- public boolean hasAuthority(NodeRef nodeRef, String userName)
- {
- boolean result = false;
-
- Map, Boolean> transactionCache = TransactionalResourceHelper.getMap(getTransactionCacheName());
- Pair key = new Pair(nodeRef, userName);
-
- if (transactionCache.containsKey(key))
- {
- result = transactionCache.get(key);
- }
- else
- {
- if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY))
- {
- Set authorities = getAuthorites(nodeRef);
- if (authorities != null)
- {
- // check for everyone or the user
- if (authorities.contains("GROUP_EVEYONE") ||
- authorities.contains(userName))
- {
- result = true;
- }
- else
- {
- // determine whether any of the users groups are in the extended security
- Set contained = getAuthorityService().getAuthoritiesForUser(userName);
- authorities.retainAll(contained);
- result = (authorities.size() != 0);
- }
- }
- }
-
- // cache result
- transactionCache.put(key, result);
- }
-
- return result;
- }
-}
+/*
+ * #%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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.security;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.repo.security.permissions.DynamicAuthority;
+import org.alfresco.repo.security.permissions.PermissionReference;
+import org.alfresco.repo.security.permissions.impl.ModelDAO;
+import org.alfresco.repo.transaction.TransactionalResourceHelper;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.security.AuthorityService;
+import org.alfresco.util.Pair;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ * Extended readers dynamic authority implementation.
+ *
+ * @author Roy Wetherall
+ * @since 2.1
+ */
+@Deprecated
+public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAuthority,
+ RecordsManagementModel,
+ ApplicationContextAware
+{
+ /** Authority service */
+ private AuthorityService authorityService;
+
+ /** Extended security service */
+ private ExtendedSecurityService extendedSecurityService;
+
+ /** Node service */
+ private NodeService nodeService;
+
+ /** Application context */
+ protected ApplicationContext applicationContext;
+
+ /** model DAO */
+ protected ModelDAO modelDAO;
+
+ /** permission reference */
+ protected Set requiredFor;
+
+ // NOTE: we get the services directly from the application context in this way to avoid
+ // cyclic relationships and issues when loading the application context
+
+ /**
+ * @return authority service
+ */
+ protected AuthorityService getAuthorityService()
+ {
+ if (authorityService == null)
+ {
+ authorityService = (AuthorityService)applicationContext.getBean("authorityService");
+ }
+ return authorityService;
+ }
+
+ /**
+ * @return extended security service
+ */
+ protected ExtendedSecurityService getExtendedSecurityService()
+ {
+ if (extendedSecurityService == null)
+ {
+ extendedSecurityService = (ExtendedSecurityService)applicationContext.getBean("extendedSecurityService");
+ }
+ return extendedSecurityService;
+ }
+
+ /**
+ * @return node service
+ */
+ protected NodeService getNodeService()
+ {
+ if (nodeService == null)
+ {
+ nodeService = (NodeService)applicationContext.getBean("dbNodeService");
+ }
+ return nodeService;
+ }
+
+ /**
+ * @return model DAO
+ */
+ protected ModelDAO getModelDAO()
+ {
+ if (modelDAO == null)
+ {
+ modelDAO = (ModelDAO)applicationContext.getBean("permissionsModelDAO");
+ }
+ return modelDAO;
+ }
+
+ /**
+ * @return String transaction cache name
+ */
+ protected abstract String getTransactionCacheName();
+
+ /**
+ * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
+ */
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext)
+ {
+ this.applicationContext = applicationContext;
+ }
+
+ /**
+ * Gets a list of the authorities from the extended security aspect that this dynamic
+ * authority is checking against.
+ *
+ * @param nodeRef
+ * @return
+ */
+ protected abstract Set getAuthorites(NodeRef nodeRef);
+
+ /**
+ * @see org.alfresco.repo.security.permissions.DynamicAuthority#hasAuthority(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
+ */
+ @Override
+ public boolean hasAuthority(NodeRef nodeRef, String userName)
+ {
+ boolean result = false;
+
+ Map, Boolean> transactionCache = TransactionalResourceHelper.getMap(getTransactionCacheName());
+ Pair key = new Pair(nodeRef, userName);
+
+ if (transactionCache.containsKey(key))
+ {
+ result = transactionCache.get(key);
+ }
+ else
+ {
+ if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY))
+ {
+ Set authorities = getAuthorites(nodeRef);
+ if (authorities != null)
+ {
+ // check for everyone or the user
+ if (authorities.contains("GROUP_EVEYONE") ||
+ authorities.contains(userName))
+ {
+ result = true;
+ }
+ else
+ {
+ // determine whether any of the users groups are in the extended security
+ Set contained = getAuthorityService().getAuthoritiesForUser(userName);
+ authorities.retainAll(contained);
+ result = (authorities.size() != 0);
+ }
+ }
+ }
+
+ // cache result
+ transactionCache.put(key, result);
+ }
+
+ return result;
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedWriterDynamicAuthority.java b/rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/ExtendedWriterDynamicAuthority.java
similarity index 97%
rename from rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedWriterDynamicAuthority.java
rename to rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/ExtendedWriterDynamicAuthority.java
index 14ca006206..2ce3c6a8f1 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedWriterDynamicAuthority.java
+++ b/rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/ExtendedWriterDynamicAuthority.java
@@ -1,102 +1,103 @@
-/*
- * #%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 .
- * #L%
- */
-
-package org.alfresco.module.org_alfresco_module_rm.security;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
-import org.alfresco.repo.security.permissions.PermissionReference;
-import org.alfresco.service.cmr.repository.NodeRef;
-
-/**
- * Extended writers dynamic authority implementation.
- *
- * @author Roy Wetherall
- * @since 2.1
- */
-public class ExtendedWriterDynamicAuthority extends ExtendedSecurityBaseDynamicAuthority
-{
- /** Extended writer role */
- public static final String EXTENDED_WRITER = "ROLE_EXTENDED_WRITER";
-
- /**
- * @see org.alfresco.repo.security.permissions.DynamicAuthority#getAuthority()
- */
- @Override
- public String getAuthority()
- {
- return EXTENDED_WRITER;
- }
-
- /**
- * @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
- */
- @Override
- public Set requiredFor()
- {
- if (requiredFor == null)
- {
- requiredFor = new HashSet(3);
- Collections.addAll(requiredFor,
- getModelDAO().getPermissionReference(null, RMPermissionModel.READ_RECORDS),
- getModelDAO().getPermissionReference(null, RMPermissionModel.FILING),
- getModelDAO().getPermissionReference(null, RMPermissionModel.FILE_RECORDS));
- }
-
- return requiredFor;
- }
-
- /**
- * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef)
- */
- @SuppressWarnings("unchecked")
- protected Set getAuthorites(NodeRef nodeRef)
- {
- Set result = null;
-
- Map map = (Map)getNodeService().getProperty(nodeRef, PROP_WRITERS);
- if (map != null)
- {
- result = map.keySet();
- }
-
- return result;
- }
-
- /**
- * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName()
- */
- @Override
- protected String getTransactionCacheName()
- {
- return "rm.extendedwriterdynamicauthority";
- }
-}
+/*
+ * #%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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.security;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
+import org.alfresco.repo.security.permissions.PermissionReference;
+import org.alfresco.service.cmr.repository.NodeRef;
+
+/**
+ * Extended writers dynamic authority implementation.
+ *
+ * @author Roy Wetherall
+ * @since 2.1
+ */
+@Deprecated
+public class ExtendedWriterDynamicAuthority extends ExtendedSecurityBaseDynamicAuthority
+{
+ /** Extended writer role */
+ public static final String EXTENDED_WRITER = "ROLE_EXTENDED_WRITER";
+
+ /**
+ * @see org.alfresco.repo.security.permissions.DynamicAuthority#getAuthority()
+ */
+ @Override
+ public String getAuthority()
+ {
+ return EXTENDED_WRITER;
+ }
+
+ /**
+ * @see org.alfresco.repo.security.permissions.DynamicAuthority#requiredFor()
+ */
+ @Override
+ public Set requiredFor()
+ {
+ if (requiredFor == null)
+ {
+ requiredFor = new HashSet(3);
+ Collections.addAll(requiredFor,
+ getModelDAO().getPermissionReference(null, RMPermissionModel.READ_RECORDS),
+ getModelDAO().getPermissionReference(null, RMPermissionModel.FILING),
+ getModelDAO().getPermissionReference(null, RMPermissionModel.FILE_RECORDS));
+ }
+
+ return requiredFor;
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getAuthorites(org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @SuppressWarnings("unchecked")
+ protected Set getAuthorites(NodeRef nodeRef)
+ {
+ Set result = null;
+
+ Map map = (Map)getNodeService().getProperty(nodeRef, PROP_WRITERS);
+ if (map != null)
+ {
+ result = map.keySet();
+ }
+
+ return result;
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityBaseDynamicAuthority#getTransactionCacheName()
+ */
+ @Override
+ protected String getTransactionCacheName()
+ {
+ return "rm.extendedwriterdynamicauthority";
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanAuthenticationService.java b/rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/FilePlanAuthenticationService.java
similarity index 97%
rename from rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanAuthenticationService.java
rename to rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/FilePlanAuthenticationService.java
index a2737bdc79..88914c0563 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanAuthenticationService.java
+++ b/rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/FilePlanAuthenticationService.java
@@ -1,58 +1,59 @@
-/*
- * #%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 .
- * #L%
- */
-
-package org.alfresco.module.org_alfresco_module_rm.security;
-
-import org.alfresco.repo.security.authentication.AuthenticationUtil;
-import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
-
-/**
- * File plan authentication service.
- *
- * @author Roy Wetherall
- * @since 2.1
- */
-public interface FilePlanAuthenticationService
-{
- /**
- * @return rm admin user name
- *
- * @deprecated as of 2.2, use {@link AuthenticationUtil#getAdminUserName()}
- */
- String getRmAdminUserName();
-
- /**
- * Run provided work as the global rm admin user.
- *
- * @param return type
- * @param runAsWork work to execute as the rm admin user
- * @return R result of work execution
- *
- * @deprecated as of 2.2, use {@link AuthenticationUtil#runAs(RunAsWork, AuthenticationUtil#getAdminUserName())}
- */
- R runAsRmAdmin(RunAsWork runAsWork);
-}
+/*
+ * #%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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.security;
+
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
+
+/**
+ * File plan authentication service.
+ *
+ * @author Roy Wetherall
+ * @since 2.1
+ * @deprecated as of 2.2, use {@link AuthenticationUtil}.
+ */
+public interface FilePlanAuthenticationService
+{
+ /**
+ * @return rm admin user name
+ *
+ * @deprecated as of 2.2, use {@link AuthenticationUtil#getAdminUserName()}
+ */
+ String getRmAdminUserName();
+
+ /**
+ * Run provided work as the global rm admin user.
+ *
+ * @param return type
+ * @param runAsWork work to execute as the rm admin user
+ * @return R result of work execution
+ *
+ * @deprecated as of 2.2, use {@link AuthenticationUtil#runAs(RunAsWork, AuthenticationUtil#getAdminUserName())}
+ */
+ R runAsRmAdmin(RunAsWork runAsWork);
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanAuthenticationServiceImpl.java b/rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/FilePlanAuthenticationServiceImpl.java
similarity index 97%
rename from rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanAuthenticationServiceImpl.java
rename to rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/FilePlanAuthenticationServiceImpl.java
index 9a3d84aeff..5c0a5f8ff5 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanAuthenticationServiceImpl.java
+++ b/rm-community/rm-community-repo/source/compatibility/org/alfresco/module/org_alfresco_module_rm/security/FilePlanAuthenticationServiceImpl.java
@@ -1,62 +1,63 @@
-/*
- * #%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 .
- * #L%
- */
-
-package org.alfresco.module.org_alfresco_module_rm.security;
-
-import org.alfresco.repo.security.authentication.AuthenticationUtil;
-import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
-
-/**
- * @author Roy Wetherall
- * @since 2.1
- */
-public class FilePlanAuthenticationServiceImpl implements FilePlanAuthenticationService
-{
- /** Default rm admin user values */
- @Deprecated
- public static final String DEFAULT_RM_ADMIN_USER = "rmadmin";
-
- /**
- * @see org.alfresco.module.org_alfresco_module_rm.security.FilePlanAuthenticationService#getRMAdminUserName()
- */
- @Override
- @Deprecated
- public String getRmAdminUserName()
- {
- return AuthenticationUtil.getAdminUserName();
- }
-
- /**
- * @see org.alfresco.module.org_alfresco_module_rm.security.FilePlanAuthenticationService#runAsRMAdmin(org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork)
- */
- @Override
- @Deprecated
- public R runAsRmAdmin(RunAsWork runAsWork)
- {
- return AuthenticationUtil.runAs(runAsWork, AuthenticationUtil.getAdminUserName());
- }
-}
+/*
+ * #%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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.security;
+
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+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 */
+ @Deprecated
+ public static final String DEFAULT_RM_ADMIN_USER = "rmadmin";
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.security.FilePlanAuthenticationService#getRMAdminUserName()
+ */
+ @Override
+ @Deprecated
+ public String getRmAdminUserName()
+ {
+ return AuthenticationUtil.getAdminUserName();
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.security.FilePlanAuthenticationService#runAsRMAdmin(org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork)
+ */
+ @Override
+ @Deprecated
+ public R runAsRmAdmin(RunAsWork runAsWork)
+ {
+ return AuthenticationUtil.runAs(runAsWork, AuthenticationUtil.getAdminUserName());
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java
index 9a1bbe3d8f..1c0d10ea83 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java
@@ -143,7 +143,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
- protected synchronized void executeImpl(Action action, final NodeRef actionedUponNodeRef)
+ protected synchronized void executeImpl(final Action action, final NodeRef actionedUponNodeRef)
{
String actionName = action.getActionDefinitionName();
if (isOkToProceedWithAction(actionedUponNodeRef, actionName))
@@ -165,8 +165,25 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER);
if (recordFolder == null)
{
- final boolean finaltargetIsUnfiledRecords = targetIsUnfiledRecords;
- recordFolder = createOrResolvePath(action, actionedUponNodeRef, finaltargetIsUnfiledRecords);
+ final boolean finaltargetIsUnfiledRecords = targetIsUnfiledRecords;
+ recordFolder = retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback()
+ {
+ public NodeRef execute() throws Throwable
+ {
+ NodeRef result = null;
+ try
+ {
+ // get the reference to the record folder based on the relative path
+ result = createOrResolvePath(action, actionedUponNodeRef, finaltargetIsUnfiledRecords);
+ }
+ catch (DuplicateChildNodeNameException ex)
+ {
+ throw new ConcurrencyFailureException("Cannot create or resolve path.", ex);
+ }
+
+ return result;
+ }
+ }, false, true);
}
// now we have the reference to the target folder we can do some final checks to see if the action is valid
@@ -180,29 +197,30 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr
{
try
{
- if(getMode() == CopyMoveLinkFileToActionMode.MOVE)
+ synchronized (this)
{
- fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null);
- }
- else if(getMode() == CopyMoveLinkFileToActionMode.COPY)
- {
- fileFolderService.copy(actionedUponNodeRef, finalRecordFolder, null);
- }
- else if(getMode() == CopyMoveLinkFileToActionMode.LINK)
- {
- getRecordService().link(actionedUponNodeRef, finalRecordFolder);
+ 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;
}
+
});
}
}
@@ -389,7 +407,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);
}
/**
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanServiceImpl.java
index 51884641a6..a8429536ba 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/fileplan/FilePlanServiceImpl.java
@@ -42,8 +42,6 @@ import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.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;
@@ -360,8 +358,6 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
// 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);
// prevent inheritance of rules
nodeService.addAspect(container, RuleModel.ASPECT_IGNORE_INHERITED_RULES, null);
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java
index 52abff0010..acc25e2992 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java
@@ -251,9 +251,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");
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java
index 2d266a39ea..23c58fdcd9 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java
@@ -39,6 +39,7 @@ import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
import org.alfresco.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;
@@ -65,7 +66,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
@@ -132,11 +134,11 @@ public class RecordAspect extends AbstractDisposableItem
// manage any extended readers
NodeRef parent = childAssocRef.getParentRef();
- Set readers = extendedSecurityService.getExtendedReaders(parent);
- Set writers = extendedSecurityService.getExtendedWriters(parent);
+ Set readers = extendedSecurityService.getReaders(parent);
+ Set writers = extendedSecurityService.getWriters(parent);
if (readers != null && readers.size() != 0)
{
- extendedSecurityService.addExtendedSecurity(thumbnail, readers, writers, false);
+ extendedSecurityService.set(thumbnail, readers, writers);
}
}
@@ -305,4 +307,33 @@ public class RecordAspect extends AbstractDisposableItem
scriptService.executeScript(scriptNodeRef, null, objectModel);
}
}
+
+ /**
+ * 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 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);
+ }
+ }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v21/RMv21InPlacePatch.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v21/RMv21InPlacePatch.java
index 5eaf3c79f2..5eb2b2a992 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v21/RMv21InPlacePatch.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v21/RMv21InPlacePatch.java
@@ -34,13 +34,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;
@@ -164,10 +161,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);
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/InplaceRecordServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/InplaceRecordServiceImpl.java
index 4a009c07f1..02431a8ea9 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/InplaceRecordServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/InplaceRecordServiceImpl.java
@@ -30,7 +30,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;
@@ -104,22 +103,26 @@ public class InplaceRecordServiceImpl extends ServiceBaseImpl implements Inplace
{
// remove the child association
NodeRef originatingLocation = (NodeRef) nodeService.getProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION);
- List parentAssocs = nodeService.getParentAssocs(nodeRef);
- for (ChildAssociationRef childAssociationRef : parentAssocs)
+
+ if (originatingLocation != null)
{
- if (!childAssociationRef.isPrimary() &&
- childAssociationRef.getParentRef().equals(originatingLocation) &&
- !nodeService.hasAspect(childAssociationRef.getChildRef(), ASPECT_PENDING_DELETE))
+ List parentAssocs = nodeService.getParentAssocs(nodeRef);
+ for (ChildAssociationRef childAssociationRef : parentAssocs)
{
- nodeService.removeChildAssociation(childAssociationRef);
- break;
+ 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);
}
- // remove the extended security from the node
- // this prevents the users from continuing to see the record in searchs and other linked locations
- extendedSecurityService.removeAllExtendedSecurity(nodeRef);
-
return null;
}
});
@@ -173,18 +176,11 @@ public class InplaceRecordServiceImpl extends ServiceBaseImpl implements Inplace
{
try
{
- // Get the extended readers/writers
- Set extendedReaders = extendedSecurityService.getExtendedReaders(nodeRef);
- Set 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)
{
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java
index 688802014c..2a2bb04f8b 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java
@@ -107,6 +107,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;
@@ -253,10 +254,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
@@ -417,11 +414,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);
}
/**
@@ -592,27 +584,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()
*/
@@ -914,12 +885,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 readers = extendedPermissionService.getReaders(aclId);
- Set writers = extendedPermissionService.getWriters(aclId);
+ // get the documents readers and writers
+ Pair, Set> 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
@@ -971,13 +940,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
nodeService.addChild(parentAssoc.getParentRef(), nodeRef, parentAssoc.getTypeQName(), parentAssoc.getQName());
// set the extended security
- Set combinedWriters = new HashSet(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
{
@@ -1009,24 +972,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 readers = extendedPermissionService.getReaders(aclId);
- Set writers = extendedPermissionService.getWriters(aclId);
-
- // add the current owner to the list of extended writers
- Set modifiedWrtiers = new HashSet(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> readersAndWriters = extendedPermissionService.getReadersAndWriters(nodeRef);
// copy version state and create record
NodeRef record = null;
@@ -1095,7 +1042,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
}
// set extended security on record
- extendedSecurityService.addExtendedSecurity(record, readers, writers);
+ extendedSecurityService.set(record, readersAndWriters);
return record;
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java
index 542cae9eb5..e4357d3d24 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java
@@ -45,8 +45,6 @@ import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.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;
@@ -195,8 +193,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));
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityService.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityService.java
index 6c3af1a400..afa06f4fdb 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityService.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityService.java
@@ -29,98 +29,77 @@ 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.
- *
+ *
* @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);
-
+
/**
* 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
*/
- Set getExtendedReaders(NodeRef nodeRef);
-
+ Set getReaders(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
*/
- Set getExtendedWriters(NodeRef nodeRef);
-
- /**
- * Add extended security for the specified authorities to a node.
- *
- * @param nodeRef node reference
- * @param readers set of authorities to add extended read permissions
- * @param writers set of authorities to add extended write permissions
- */
- void addExtendedSecurity(NodeRef nodeRef, Set readers, Set writers);
+ Set 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.
+ *
+ * @see #set(NodeRef, Set, Set)
+ *
+ * @param nodeRef node reference
+ * @param readersAndWriters pair where first is the set of readers and the
+ * second is the set of writers
+ */
+ void set(NodeRef nodeRef, Pair, Set> readersAndWriters);
+
+ /**
+ * Set extended security for a node, where the readers will be granted ReadRecord
+ * permission and ViewRecord capability to the node and where the writers will be
+ * granted Filling permission and Filling capability to the node.
*
- * 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 readers, Set 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 readers, Set writers);
+ void set(NodeRef nodeRef, Set readers, Set writers);
/**
- * Remove the extended security for the specified authorities from a node.
- *
- * 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 readers, Set 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);
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java
index f1db301030..fda0573794 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java
@@ -27,23 +27,37 @@
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.
@@ -53,13 +67,31 @@ import org.alfresco.util.ParameterCheck;
*/
public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
implements ExtendedSecurityService,
- RecordsManagementModel
+ RecordsManagementModel,
+ ApplicationListener
{
+ /** 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
@@ -76,118 +108,152 @@ 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()
+ {
+ 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 getExtendedReaders(NodeRef nodeRef)
- {
- Set result = null;
-
- Map readerMap = (Map)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 getExtendedWriters(NodeRef nodeRef)
- {
- Set result = null;
-
- Map map = (Map)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 readers, Set 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 readers, Set writers, boolean applyToParents)
+ public Set getReaders(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
- ParameterCheck.mandatory("applyToParents", applyToParents);
-
- if (nodeRef != null)
+
+ Set result = Collections.EMPTY_SET;
+ Pair 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
- *
- * @param nodeRef
- * @param readers
- * @param writers
- * @param applyToParents
+ * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#getWriters(org.alfresco.service.cmr.repository.NodeRef)
*/
@SuppressWarnings("unchecked")
- private void addExtendedSecurityImpl(final NodeRef nodeRef, Set readers, Set writers, boolean applyToParents)
+ @Override
+ public Set getWriters(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
- ParameterCheck.mandatory("applyToParents", applyToParents);
-
- // get the properties
- final Map properties = nodeService.getProperties(nodeRef);
-
- // update the readers map
- if (readers != null && readers.size() != 0)
+
+ Set result = Collections.EMPTY_SET;
+ Pair iprGroups = getIPRGroups(nodeRef);
+ if (iprGroups != null)
{
- // get reader map
- Map readersMap = (Map)properties.get(PROP_READERS);
-
- // set the readers property (this will in turn apply the aspect if required)
- properties.put(PROP_READERS, (Serializable)addToMap(readersMap, readers));
+ result = getAuthorities(iprGroups.getSecond());
}
-
- // update the writers map
- if (writers != null && writers.size() != 0)
- {
- // get writer map
- Map writersMap = (Map)properties.get(PROP_WRITERS);
-
- // 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);
-
+
+ return result;
+ }
+
+ /**
+ * Helper to get authorities for a given group
+ *
+ * @param group group name
+ * @return Set immediate authorities
+ */
+ private Set getAuthorities(String group)
+ {
+ Set result = new HashSet();
+ 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> readersAndWriters)
+ {
+ ParameterCheck.mandatory("nodeRef", nodeRef);
+ set(nodeRef, readersAndWriters.getFirst(), readersAndWriters.getSecond());
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#set(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
+ */
+ @Override
+ public void set(NodeRef nodeRef, Set readers, Set writers)
+ {
+ ParameterCheck.mandatory("nodeRef", nodeRef);
+
+ // remove existing extended security, assuming there is any
+ remove(nodeRef);
+
+ // find groups
+ Pair iprGroups = createOrFindIPRGroups(readers, writers);
+
+ // assign groups to correct fileplan roles
+ NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
+ filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, iprGroups.getFirst());
+ filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, iprGroups.getSecond());
+
+ // assign groups to node
+ assignIPRGroupsToNode(iprGroups, nodeRef);
+
// apply the readers to any renditions of the content
if (isRecord(nodeRef))
{
@@ -195,101 +261,300 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
for (ChildAssociationRef assoc : assocs)
{
NodeRef child = assoc.getChildRef();
- addExtendedSecurityImpl(child, readers, writers, false);
+ assignIPRGroupsToNode(iprGroups, child);
}
- }
+ }
}
-
+
/**
- *
- * @param nodeRef
- * @param readers
- * @param writers
+ * Get the IPR groups associated with a given node reference.
+ *
+ * Return null if none found.
+ *
+ * @param nodeRef node reference
+ * @return Pair where first is the read group and second if the write group, null if none found
*/
- private void addExtendedSecurityRoles(NodeRef nodeRef, Set readers, Set writers)
+ private Pair getIPRGroups(NodeRef nodeRef)
{
- NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
-
- addExtendedSecurityRolesImpl(filePlan, readers, FilePlanRoleService.ROLE_EXTENDED_READERS);
- addExtendedSecurityRolesImpl(filePlan, writers, FilePlanRoleService.ROLE_EXTENDED_WRITERS);
- }
-
- /**
- * Add extended security roles implementation
- *
- * @param filePlan file plan
- * @param authorities authorities
- * @param roleName role name
- */
- private void addExtendedSecurityRolesImpl(NodeRef filePlan, Set authorities, String roleName)
- {
- if (authorities != null)
+ Pair result = null;
+ String iprReaderGroup = null;
+ String iprWriterGroup = null;
+
+ // get all the set permissions
+ Set permissions = permissionService.getAllSetPermissions(nodeRef);
+ for (AccessPermission permission : permissions)
{
- for (String authority : authorities)
+ // look for the presence of the reader group
+ if (permission.getAuthority().startsWith(GROUP_PREFIX + READER_GROUP_PREFIX))
{
- if ((!authority.equals(PermissionService.ALL_AUTHORITIES) && !authority.equals(PermissionService.OWNER_AUTHORITY)))
- {
- // add the authority to the role
- filePlanRoleService.assignRoleToAuthority(filePlan, roleName, authority);
- }
+ 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(iprReaderGroup, iprWriterGroup);
+ }
+
+ return result;
}
-
+
/**
- *
- * @param map
- * @param keys
+ * Given a set of readers and writers find or create the appropriate IPR groups.
+ *
+ * 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.
+ *
+ * When no match is found the groups are created. Once created
+ *
+ * @param filePlan file plan
+ * @param readers authorities with read
+ * @param writers authorities with write
+ * @return Pair where first is the full name of the read group and
+ * second is the full name of the write group
+ */
+ private Pair createOrFindIPRGroups(Set readers, Set writers)
+ {
+ return new Pair(
+ 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 authorities)
+ {
+ String group = null;
+
+ // find group or determine what the next index is if no group exists or there is a clash
+ Pair groupResult = findIPRGroup(groupPrefix, authorities);
+
+ if (groupResult.getFirst() == null)
+ {
+ group = createIPRGroup(groupPrefix, authorities, groupResult.getSecond());
+ }
+ else
+ {
+ group = groupResult.getFirst();
+ }
+
+ return group;
+ }
+
+ /**
+ * Given a group name prefix and the authorities, finds the exact match existing group.
+ *
+ * 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 where first is the name of the found group, null if none found and second
+ * if the next available create index
+ */
+ private Pair findIPRGroup(String groupPrefix, Set 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 results = authorityService.getAuthorities(AuthorityType.GROUP,
+ RMAuthority.ZONE_APP_RM,
+ groupShortNamePrefix,
+ false,
+ false,
+ new PagingRequest(MAX_ITEMS*pageCount, MAX_ITEMS));
+
+ // record the total count
+ nextGroupIndex = nextGroupIndex + results.getPage().size();
+
+ // see if any of the matching groups exactly match
+ for (String group : results.getPage())
+ {
+ // if exists and matches we have found our group
+ if (isIPRGroupTrueMatch(group, authorities))
+ {
+ iprGroup = group;
+ break;
+ }
+ }
+
+ // determine if there are any more pages to inspect
+ hasMoreItems = results.hasMoreItems();
+ pageCount ++;
+ }
+
+ return new Pair(iprGroup, nextGroupIndex);
+ }
+
+ /**
+ * Determines whether a group exactly matches a list of authorities.
+ *
+ * @param authorities list of authorities
+ * @param group group
* @return
*/
- private Map addToMap(Map map, Set keys)
+ private boolean isIPRGroupTrueMatch(String group, Set authorities)
+ {
+ Set contained = authorityService.getContainedAuthorities(null, group, true);
+ return contained.equals(authorities);
+ }
+
+ /**
+ * Get IPR group prefix short name.
+ *
+ * 'package' scope to help testing.
+ *
+ * @param prefix prefix
+ * @param authorities authorities
+ * @return String group prefix short name
+ */
+ /*package*/ String getIPRGroupPrefixShortName(String prefix, Set authorities)
{
- if (map == null)
+ StringBuilder builder = new StringBuilder(128)
+ .append(prefix)
+ .append(getAuthoritySetHashCode(authorities));
+
+ return builder.toString();
+ }
+
+ /**
+ * Get IPR group short name.
+ *
+ * Note this excludes the "GROUP_" prefix.
+ *
+ * '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 authorities, int index)
+ {
+ return getIPRGroupShortName(prefix, authorities, Integer.toString(index));
+ }
+
+ /**
+ * Get IPR group short name.
+ *
+ * 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 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 authorities)
+ {
+ int result = 0;
+ if (authorities != null && !authorities.isEmpty())
{
- // create map
- map = new HashMap(7);
+ result = StringUtils.join(authorities.toArray(), "").hashCode();
}
-
- for (String key : keys)
+ 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 children, int index)
+ {
+ ParameterCheck.mandatory("groupNamePrefix", groupNamePrefix);
+
+ // get the group name
+ String groupShortName = getIPRGroupShortName(groupNamePrefix, children, index);
+
+ // create group
+ String group = authorityService.createAuthority(AuthorityType.GROUP, groupShortName, groupShortName, Collections.singleton(RMAuthority.ZONE_APP_RM));
+
+ // add root parent
+ authorityService.addAuthority(getRootIRPGroup(), group);
+
+ // add children if provided
+ if (children != null)
{
- if (!key.equals(PermissionService.ALL_AUTHORITIES))
+ for (String child : children)
{
- if (map.containsKey(key))
+ if (authorityService.authorityExists(child) &&
+ !PermissionService.ALL_AUTHORITIES.equals(child))
{
- // increment reference count
- 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
+ */
+ private void assignIPRGroupsToNode(Pair iprGroups, NodeRef nodeRef)
+ {
+ permissionService.setPermission(nodeRef, iprGroups.getFirst(), RMPermissionModel.READ_RECORDS, true);
+ permissionService.setPermission(nodeRef, iprGroups.getSecond(), RMPermissionModel.FILING, true);
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#remove(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
- public void removeExtendedSecurity(NodeRef nodeRef, Set readers, Set writers)
+ public void remove(NodeRef nodeRef)
{
- removeExtendedSecurity(nodeRef, readers, writers, 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)
- */
- @Override
- public void removeExtendedSecurity(NodeRef nodeRef, Set readers, Setwriters, boolean applyToParents)
- {
- if (hasExtendedSecurity(nodeRef))
+ ParameterCheck.mandatory("nodeRef", nodeRef);
+
+ Pair 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))
{
@@ -297,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.
- *
- * 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 readers, Set writers)
+ private void clearPermissions(NodeRef nodeRef, Pair iprGroups)
{
- Map readersMap = (Map)nodeService.getProperty(nodeRef, PROP_READERS);
- nodeService.setProperty(nodeRef, PROP_READERS, (Serializable)removeFromMap(readersMap, readers));
-
- Map writersMap = (Map)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());
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedReaders(org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @Override @Deprecated public Set getExtendedReaders(NodeRef nodeRef)
+ {
+ return getReaders(nodeRef);
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedWriters(org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @Override @Deprecated public Set getExtendedWriters(NodeRef nodeRef)
+ {
+ return getWriters(nodeRef);
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
+ */
+ @Override @Deprecated public void addExtendedSecurity(NodeRef nodeRef, Set readers, Set writers)
+ {
+ set(nodeRef, readers, writers);
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
+ */
+ @Override @Deprecated public void addExtendedSecurity(NodeRef nodeRef, Set readers, Set 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 readers, Set writers)
+ {
+ remove(nodeRef);
}
/**
- * Helper method to remove items from map or reduce reference count
- *
- * @param map ref count map
- * @param keys keys
- * @return Map ref count map
+ * @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
*/
- private Map removeFromMap(Map map, Set keys)
+ @Override @Deprecated public void removeExtendedSecurity(NodeRef nodeRef, Set readers, Setwriters, boolean applyToParents)
{
- 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;
+ remove(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#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, boolean)
*/
- @Override
- public void removeAllExtendedSecurity(NodeRef nodeRef)
+ @Override @Deprecated public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents)
{
- removeAllExtendedSecurity(nodeRef, true);
- }
-
- /**
- * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, boolean)
- */
- @Override
- public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents)
- {
- if (hasExtendedSecurity(nodeRef))
- {
- removeExtendedSecurity(nodeRef, getExtendedReaders(nodeRef), getExtendedWriters(nodeRef));
- }
+ remove(nodeRef);
}
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImpl.java
index 43068da49a..5fab978a41 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImpl.java
@@ -27,8 +27,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;
@@ -383,13 +381,29 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
boolean inheritanceAllowed = isInheritanceAllowed(nodeRef, isParentNodeFilePlan);
getPermissionService().setInheritParentPermissions(nodeRef, inheritanceAllowed);
- // clear all existing permissions
+ Set keepPerms = new HashSet(5);
+ Set 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);
}
@@ -435,9 +449,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)));
}
/**
@@ -494,20 +519,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);
@@ -589,7 +608,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);
}
/**
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImpl.java
index 4ebfc07cf8..0b714bc9da 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImpl.java
@@ -34,7 +34,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;
@@ -56,12 +55,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;
@@ -129,9 +128,6 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
/** extended security service */
private ExtendedSecurityService extendedSecurityService;
-
- /** ownable service */
- private OwnableService ownableService;
/**
* @param filePlanService file plan service
@@ -196,14 +192,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)
@@ -706,13 +694,8 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
{
public NodeRef doWork() throws Exception
{
- // get the documents readers
- Long aclId = nodeService.getNodeAclId(nodeRef);
- Set readers = extendedPermissionService.getReaders(aclId);
- Set 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> readersAndWriters = extendedPermissionService.getReadersAndWriters(nodeRef);
// grab the frozen state
NodeRef currentFrozenState = currentVersion.getFrozenStateNodeRef();
@@ -752,13 +735,7 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
linkToPreviousVersionRecord(nodeRef, record);
// set the extended security
- Set combinedWriters = new HashSet(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;
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionService.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionService.java
index 038df7e2f0..a7f1e5a5d2 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionService.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionService.java
@@ -29,7 +29,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.
@@ -46,4 +48,18 @@ public interface ExtendedPermissionService extends PermissionService
* @return {@link Set}<{@link String}> set of authorities with write access
*/
Set getWriters(Long aclId);
+
+ /**
+ * Get the readers and writers for a given node.
+ *
+ * The writers list includes the owner for the node.
+ *
+ * @param nodeRef node reference
+ * @return Pair, Set> 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> getReadersAndWriters(NodeRef nodeRef);
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java
index 74e9e818ce..31246b35f1 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java
@@ -39,8 +39,6 @@ import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.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;
@@ -50,8 +48,11 @@ import org.alfresco.repo.security.permissions.processor.PermissionProcessorRegis
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;
/**
@@ -359,13 +360,17 @@ public class ExtendedPermissionServiceImpl 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;
@@ -376,4 +381,28 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl
}
return adminRole;
}
+
+ /**
+ * @see org.alfresco.repo.security.permissions.impl.ExtendedPermissionService#getReadersAndWriters(org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @Override
+ public Pair, Set> getReadersAndWriters(NodeRef nodeRef)
+ {
+ // get the documents readers
+ Long aclId = nodeService.getNodeAclId(nodeRef);
+ Set readers = getReaders(aclId);
+ Set writers = getWriters(aclId);
+
+ // add the current owner to the list of extended writers
+ Set modifiedWrtiers = new HashSet(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> (readers, modifiedWrtiers);
+ }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java
new file mode 100644
index 0000000000..5e3020e9aa
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java
@@ -0,0 +1,267 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+/*
+ * Copyright (C) 2005-2014 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+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 executeImpl(WebScriptRequest req, Status status, Cache cache)
+ {
+ Map model = new HashMap();
+ 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 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 processedNodes = new ArrayList();
+ 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()
+ {
+ public Void execute() throws Throwable
+ {
+ // get the nodes with the extended security aspect applied
+ List 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 readers = (Map)nodeService.getProperty(nodeRef, PROP_READERS);
+ Map writers = (Map)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());
+ }
+ }
+}
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM1429Test.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM1429Test.java
index 0795d314b2..6c7560402b 100644
--- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM1429Test.java
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM1429Test.java
@@ -44,14 +44,14 @@ public class RM1429Test extends DeleteHoldTest
{
public void testDeleteHoldWithoutPermissionsOnChildren()
{
- // Create the test hold
- final NodeRef hold = createAndCheckHold();
-
- doTestInTransaction(new Test()
+ final NodeRef hold = doTestInTransaction(new Test()
{
@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);
@@ -64,7 +64,7 @@ public class RM1429Test extends DeleteHoldTest
// Add record folder to the hold
holdService.addToHold(hold, rmFolder);
- return null;
+ return hold;
}
});
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM1463Test.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM1463Test.java
index c3993d090d..3ed864a61f 100644
--- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM1463Test.java
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM1463Test.java
@@ -44,14 +44,14 @@ public class RM1463Test extends DeleteHoldTest
{
public void testAddRecordFolderToHoldWithoutFilingPermissionOnRecordFolder()
{
- // Create hold
- final NodeRef hold = createAndCheckHold();
-
- doTestInTransaction(new Test()
+ final NodeRef hold = doTestInTransaction(new Test()
{
@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);
@@ -61,7 +61,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;
}
});
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM1464Test.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM1464Test.java
index 9f603b23b9..4a9dfa3ccf 100644
--- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM1464Test.java
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM1464Test.java
@@ -44,14 +44,14 @@ public class RM1464Test extends DeleteHoldTest
{
public void testAddRecordFolderToHoldWithoutFilingPermissionOnHold()
{
- // Create hold
- final NodeRef hold = createAndCheckHold();
-
- doTestInTransaction(new Test()
+ final NodeRef hold = doTestInTransaction(new Test()
{
@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);
@@ -61,7 +61,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;
}
});
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM3993Test.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM3993Test.java
new file mode 100644
index 0000000000..20c6dc3e4d
--- /dev/null
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM3993Test.java
@@ -0,0 +1,253 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+/*
+ * Copyright (C) 2005-2014 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction;
+import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction;
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
+import org.alfresco.service.cmr.action.Action;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.rule.Rule;
+import org.alfresco.service.cmr.rule.RuleService;
+import org.alfresco.service.cmr.rule.RuleType;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * System test for RM-3993: Exceptions thrown when concurrently creating identical folder structure
+ *
+ * @author Silviu Dinuta
+ * @since 2.3.0.7
+ */
+public class RM3993Test extends BaseRMTestCase
+{
+ private static final int NUMBER_OF_BATCHES = 4;
+ private static final int NUMBER_IN_BATCH = 500;
+
+ private RuleService ruleService;
+ private NodeRef ruleFolder;
+ private NodeRef nodeRefCategory1;
+
+ @Override
+ protected void initServices()
+ {
+ super.initServices();
+
+ ruleService = (RuleService) applicationContext.getBean("RuleService");
+ }
+
+ @Override
+ protected boolean isCollaborationSiteTest()
+ {
+ return true;
+ }
+
+ @Override
+ protected boolean isRecordTest()
+ {
+ return true;
+ }
+
+ /**
+ * Given that I have auto declare configured And that I have auto file configured to a path where only the record
+ * folder needs to be created When I add lots of documents in the same transaction Then the rules should fire And
+ * the documents should be filed in the new record folder
+ */
+ public void testAutoDeclareAutoFileCreateRecordFolderOnly() throws Exception
+ {
+ doTestInTransaction(new Test()
+ {
+ @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 records = new ArrayList(NUMBER_OF_BATCHES * NUMBER_IN_BATCH);
+
+ for (int i = 0; i < NUMBER_OF_BATCHES; i++)
+ {
+ final int finali = i;
+ records.addAll(doTestInTransaction(new Test>()
+ {
+ @Override
+ public List run() throws Exception
+ {
+ List records = new ArrayList(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 temp = records.iterator();
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run() throws Exception
+ {
+ while (temp.hasNext())
+ {
+ NodeRef record = temp.next();
+ if (nodeService.hasAspect(record, ASPECT_RECORD) && recordService.isFiled(record))
+ {
+ String name = (String) nodeService.getProperty(record, ContentModel.PROP_NAME);
+ System.out.println(name + " - complete");
+ temp.remove();
+ }
+ }
+
+ return null;
+ }
+ });
+ }
+ }
+ catch (Exception exception)
+ {
+ exception.printStackTrace();
+ throw exception;
+ }
+
+ Integer numberOfRecords = AuthenticationUtil.runAsSystem(new RunAsWork()
+ {
+
+ @Override
+ public Integer doWork() throws Exception
+ {
+ List containedRecordFolders = filePlanService.getContainedRecordFolders(nodeRefCategory1);
+ int numberOfRecords = 0;
+ for(NodeRef recordFolder : containedRecordFolders)
+ {
+ numberOfRecords = numberOfRecords + fileFolderService.list(recordFolder).size();
+ }
+ return numberOfRecords;
+ }
+ });
+ assertTrue(numberOfRecords == NUMBER_OF_BATCHES * NUMBER_IN_BATCH);
+ }
+
+ private NodeRef createFile(NodeRef parentNodeRef, String name, String descrption, QName typeQName)
+ {
+ Map properties = new HashMap(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;
+ }
+}
\ No newline at end of file
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/CreateInplaceRecordTest.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/CreateInplaceRecordTest.java
new file mode 100644
index 0000000000..51159550ac
--- /dev/null
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/CreateInplaceRecordTest.java
@@ -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