Merge release/V2.3 into release/2.4

This commit is contained in:
Ana Bozianu
2016-09-21 11:58:40 +03:00
48 changed files with 5055 additions and 1257 deletions

View File

@@ -0,0 +1,148 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.module.org_alfresco_module_rm.security;
import java.util.Set;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Deprecated extended security service for compatibility.
*
* @author Roy Wetherall
*/
public interface DeprecatedExtendedSecurityService
{
/**
* Gets the set of authorities that are extended readers for the given node.
*
* @param nodeRef node reference
* @return {@link Set}<{@link String}> set of extended readers
*
* @deprecated as of 2.5, use {@link ExtendedSecurityService#getReaders(NodeRef)}
*/
Set<String> getExtendedReaders(NodeRef nodeRef);
/**
* Get the set of authorities that are extended writers for the given node.
*
* @param nodeRef node reference
* @return {@link Set}<{@link String}> set of extended writers
*
* @deprecated as of 2.5, use {@link ExtendedSecurityService#getWriters(NodeRef)}
*/
Set<String> getExtendedWriters(NodeRef nodeRef);
/**
* Add extended security for the specified authorities to a node.
*
* As of, 2.5 this method no longer applies the extended security to parents.
*
* @param nodeRef node reference
* @param readers set of authorities to add extended read permissions
* @param writers set of authorities to add extended write permissions
*
* @deprecated as of 2.5, use {@link ExtendedSecurityService#set(NodeRef, Set, Set)}
*/
@Deprecated
void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers);
/**
* Add extended security for the specified authorities to a node.
* <p>
* If specified, the read and write extended permissions are applied to all parents up to the file plan as
* extended read. This ensures parental read, but not parental write.
*
* @param nodeRef node reference
* @param readers set of authorities to add extended read permissions
* @param writers set of authorities to add extended write permissions
* @param applyToParents true if extended security applied to parents (read only) false otherwise.
*
* @deprecated as of 2.5, because extended security is no longer applied to parents. Note that calling this method will
* only apply the extended security to the node and the applyToParents parameter value will be ignored.
*
* @see ExtendedSecurityService#set(NodeRef, Set, Set)
*/
@Deprecated void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents);
/**
* Remove all extended readers and writers from the given node reference.
*
* @param nodeRef node reference
*
* @deprecated as of 2.5, see {@link ExtendedSecurityService#remove(NodeRef)}
*/
@Deprecated void removeAllExtendedSecurity(NodeRef nodeRef);
/**
* Remove the extended security for the specified authorities from a node.
*
* @param nodeRef node reference
* @param readers set of authorities to remove as extended readers
* @param writers set of authorities to remove as extended writers
*
* @deprecated as of 2.5, because partial removal of readers and writers from node or parents is no longer supported.
* Note that calling this method will now remove all extended security from the node and never applied to parents.
*
* @see {@link ExtendedSecurityService#remove(NodeRef)}
*/
@Deprecated void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers);
/**
* Remove the extended security for the specified authorities from a node.
* <p>
* If specified, extended security will also be removed from the parent hierarchy.(read only). Note that
* extended security is records as a reference count, so security will only be utterly removed from the parent
* hierarchy if all references to the authority are removed.
*
* @param nodeRef node reference
* @param readers set of authorities to remove as extended readers
* @param writers set of authorities to remove as extedned writers
* @param applyToParents true if removal of extended security is applied to parent hierarchy (read only), false
* otherwise
*
* @deprecated as of 2.5, because partial removal of readers and writers from node or parents is no longer supported.
* Note that calling this method will now remove all extended security from the node and never applied to parents.
*
* @see {@link ExtendedSecurityService#remove(NodeRef)}
*/
@Deprecated void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents);
/**
* Remove all extended readers and writers from the given node reference.
*
* @param nodeRef node reference
* @param applyToParents if true then apply removal to parent hierarchy (read only) false otherwise.
*
* @deprecated as of 2.5, because partial removal of readers and writers from node or parents is no longer supported.
* Note that calling this method will now remove all extended security from the node and never applied to parents.
*
* @see {@link ExtendedSecurityService#remove(NodeRef)}
*/
@Deprecated void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents);
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
* #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<PermissionReference> 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<String> getAuthorites(NodeRef nodeRef)
{
Set<String> result = null;
Map<String, Integer> readerMap = (Map<String, Integer>)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 <http://www.gnu.org/licenses/>.
* #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<PermissionReference> 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<String> getAuthorites(NodeRef nodeRef)
{
Set<String> result = null;
Map<String, Integer> readerMap = (Map<String, Integer>)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";
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
* #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<PermissionReference> requiredFor;
// NOTE: we get the services directly from the application context in this way to avoid
// cyclic relationships and issues when loading the application context
/**
* @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<String> getAuthorites(NodeRef nodeRef);
/**
* @see org.alfresco.repo.security.permissions.DynamicAuthority#hasAuthority(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
*/
@Override
public boolean hasAuthority(NodeRef nodeRef, String userName)
{
boolean result = false;
Map<Pair<NodeRef, String>, Boolean> transactionCache = TransactionalResourceHelper.getMap(getTransactionCacheName());
Pair<NodeRef, String> key = new Pair<NodeRef, String>(nodeRef, userName);
if (transactionCache.containsKey(key))
{
result = transactionCache.get(key);
}
else
{
if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY))
{
Set<String> 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<String> 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 <http://www.gnu.org/licenses/>.
* #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<PermissionReference> requiredFor;
// NOTE: we get the services directly from the application context in this way to avoid
// cyclic relationships and issues when loading the application context
/**
* @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<String> getAuthorites(NodeRef nodeRef);
/**
* @see org.alfresco.repo.security.permissions.DynamicAuthority#hasAuthority(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
*/
@Override
public boolean hasAuthority(NodeRef nodeRef, String userName)
{
boolean result = false;
Map<Pair<NodeRef, String>, Boolean> transactionCache = TransactionalResourceHelper.getMap(getTransactionCacheName());
Pair<NodeRef, String> key = new Pair<NodeRef, String>(nodeRef, userName);
if (transactionCache.containsKey(key))
{
result = transactionCache.get(key);
}
else
{
if (getNodeService().hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY))
{
Set<String> 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<String> contained = getAuthorityService().getAuthoritiesForUser(userName);
authorities.retainAll(contained);
result = (authorities.size() != 0);
}
}
}
// cache result
transactionCache.put(key, result);
}
return result;
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
* #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<PermissionReference> requiredFor()
{
if (requiredFor == null)
{
requiredFor = new HashSet<PermissionReference>(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<String> getAuthorites(NodeRef nodeRef)
{
Set<String> result = null;
Map<String, Integer> map = (Map<String, Integer>)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 <http://www.gnu.org/licenses/>.
* #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<PermissionReference> requiredFor()
{
if (requiredFor == null)
{
requiredFor = new HashSet<PermissionReference>(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<String> getAuthorites(NodeRef nodeRef)
{
Set<String> result = null;
Map<String, Integer> map = (Map<String, Integer>)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";
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
* #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 <R> 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> R runAsRmAdmin(RunAsWork<R> 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 <http://www.gnu.org/licenses/>.
* #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 <R> 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> R runAsRmAdmin(RunAsWork<R> runAsWork);
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
* #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> R runAsRmAdmin(RunAsWork<R> 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 <http://www.gnu.org/licenses/>.
* #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> R runAsRmAdmin(RunAsWork<R> runAsWork)
{
return AuthenticationUtil.runAs(runAsWork, AuthenticationUtil.getAdminUserName());
}
}

View File

@@ -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<NodeRef>()
{
public NodeRef execute() throws Throwable
{
NodeRef result = null;
try
{
// get the reference to the record folder based on the relative path
result = createOrResolvePath(action, actionedUponNodeRef, finaltargetIsUnfiledRecords);
}
catch (DuplicateChildNodeNameException ex)
{
throw new ConcurrencyFailureException("Cannot create or resolve path.", ex);
}
return result;
}
}, false, true);
}
// now we have the reference to the target folder we can do some final checks to see if the action is valid
@@ -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);
}
/**

View File

@@ -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);

View File

@@ -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");

View File

@@ -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<String> readers = extendedSecurityService.getExtendedReaders(parent);
Set<String> writers = extendedSecurityService.getExtendedWriters(parent);
Set<String> readers = extendedSecurityService.getReaders(parent);
Set<String> writers = extendedSecurityService.getWriters(parent);
if (readers != null && readers.size() != 0)
{
extendedSecurityService.addExtendedSecurity(thumbnail, readers, writers, false);
extendedSecurityService.set(thumbnail, readers, writers);
}
}
@@ -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<NodeRef, NodeRef> copyMap)
{
// given the node exists and is a record
if (nodeService.exists(targetNodeRef) &&
nodeService.hasAspect(targetNodeRef, ASPECT_RECORD))
{
// then remove any extended security from the newly copied record
extendedSecurityService.remove(targetNodeRef);
}
}
}

View File

@@ -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);

View File

@@ -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<ChildAssociationRef> 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<ChildAssociationRef> 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<String> extendedReaders = extendedSecurityService.getExtendedReaders(nodeRef);
Set<String> extendedWriters = extendedSecurityService.getExtendedWriters(nodeRef);
// Move the record
fileFolderService.moveFrom(nodeRef, source, targetNodeRef, null);
// Update the originating location property
nodeService.setProperty(nodeRef, PROP_RECORD_ORIGINATING_LOCATION, targetNodeRef);
// Set the extended readers/writers
extendedSecurityService.addExtendedSecurity(nodeRef, extendedReaders, extendedWriters);
}
catch (FileExistsException | FileNotFoundException ex)
{

View File

@@ -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<String> readers = extendedPermissionService.getReaders(aclId);
Set<String> writers = extendedPermissionService.getWriters(aclId);
// get the documents readers and writers
Pair<Set<String>, Set<String>> readersAndWriters = extendedPermissionService.getReadersAndWriters(nodeRef);
// add the current owner to the list of extended writers
// get the current owner
String owner = ownableService.getOwner(nodeRef);
// get the documents primary parent assoc
@@ -971,13 +940,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
nodeService.addChild(parentAssoc.getParentRef(), nodeRef, parentAssoc.getTypeQName(), parentAssoc.getQName());
// set the extended security
Set<String> combinedWriters = new HashSet<String>(writers);
if (owner != null && !owner.isEmpty() && !owner.equals(OwnableService.NO_OWNER))
{
combinedWriters.add(owner);
}
combinedWriters.add(AuthenticationUtil.getFullyAuthenticatedUser());
extendedSecurityService.addExtendedSecurity(nodeRef, readers, combinedWriters);
extendedSecurityService.set(nodeRef, readersAndWriters);
}
finally
{
@@ -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<String> readers = extendedPermissionService.getReaders(aclId);
Set<String> writers = extendedPermissionService.getWriters(aclId);
// add the current owner to the list of extended writers
Set<String> modifiedWrtiers = new HashSet<String>(writers);
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_OWNABLE))
{
String owner = ownableService.getOwner(nodeRef);
if (owner != null && !owner.isEmpty() && !owner.equals(OwnableService.NO_OWNER))
{
modifiedWrtiers.add(owner);
}
}
// add the current user as extended writer
modifiedWrtiers.add(authenticationUtil.getFullyAuthenticatedUser());
// get the documents readers and writers
Pair<Set<String>, Set<String>> readersAndWriters = extendedPermissionService.getReadersAndWriters(nodeRef);
// copy version state and create record
NodeRef record = null;
@@ -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;
}

View File

@@ -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));

View File

@@ -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<String> getExtendedReaders(NodeRef nodeRef);
Set<String> 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<String> 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<String> readers, Set<String> writers);
Set<String> getWriters(NodeRef nodeRef);
/**
* Add extended security for the specified authorities to a node.
* Helper to allow caller to provide authority sets as a pair where the
* first is the readers and the second is the writers.
*
* @see #set(NodeRef, Set, Set)
*
* @param nodeRef node reference
* @param readersAndWriters pair where first is the set of readers and the
* second is the set of writers
*/
void set(NodeRef nodeRef, Pair<Set<String>, Set<String>> readersAndWriters);
/**
* Set extended security for a node, where the readers will be granted ReadRecord
* permission and ViewRecord capability to the node and where the writers will be
* granted Filling permission and Filling capability to the node.
* <p>
* If specified, the read and write extended permissions are applied to all parents up to the file plan as
* extended read. This ensures parental read, but not parental write.
* Note it is vaild to provide 'null' values for readers and/or writers.
*
* @param nodeRef node reference
* @param readers set of authorities to add extended read permissions
* @param writers set of authorities to add extended write permissions
* @param applyToParents true if extended security applied to parents (read only) false otherwise.
*/
void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents);
/**
* Remove the extended security for the specified authorities from a node.
* @param readers set of readers
* @param writers set of writers
*
* @param nodeRef node reference
* @param readers set of authorities to remove as extended readers
* @param writers set of authorities to remove as extended writers
* @since 2.5
*/
void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers);
void set(NodeRef nodeRef, Set<String> readers, Set<String> writers);
/**
* Remove the extended security for the specified authorities from a node.
* <p>
* If specified, extended security will also be removed from the parent hierarchy.(read only). Note that
* extended security is records as a reference count, so security will only be utterly removed from the parent
* hierarchy if all references to the authority are removed.
*
* @param nodeRef node reference
* @param readers set of authorities to remove as extended readers
* @param writers set of authorities to remove as extedned writers
* @param applyToParents true if removal of extended security is applied to parent hierarchy (read only), false
* otherwise
*/
void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents);
/**
* Remove all extended readers and writers from the given node reference.
* Removes all extended security from a node.
*
* @param nodeRef node reference
*/
void removeAllExtendedSecurity(NodeRef nodeRef);
/**
* Remove all extended readers and writers from the given node reference.
*
* @param nodeRef node reference
* @param applyToParents if true then apply removal to parent hierarchy (read only) false otherwise.
*/
void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents);
void remove(NodeRef nodeRef);
}

View File

@@ -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<ContextRefreshedEvent>
{
/** ipr group names */
static final String ROOT_IPR_GROUP = "INPLACE_RECORD_MANAGEMENT";
static final String READER_GROUP_PREFIX = ExtendedSecurityService.IPR_GROUP_PREFIX + "R";
static final String WRITER_GROUP_PREFIX = ExtendedSecurityService.IPR_GROUP_PREFIX + "W";
/** max page size for authority query */
private static final int MAX_ITEMS = 50;
/** File plan service */
private FilePlanService filePlanService;
/** File plan role service */
private FilePlanRoleService filePlanRoleService;
/** authority service */
private AuthorityService authorityService;
/** permission service */
private PermissionService permissionService;
/** transaction service */
private TransactionService transactionService;
/**
* @param filePlanService file plan service
@@ -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<Void>()
{
public Void execute() throws Throwable
{
// if the root group doesn't exist then create it
if (!authorityService.authorityExists(getRootIRPGroup()))
{
authorityService.createAuthority(AuthorityType.GROUP, ROOT_IPR_GROUP, ROOT_IPR_GROUP, Collections.singleton(RMAuthority.ZONE_APP_RM));
}
return null;
}
});
}
/**
* Get root IPR group name
*/
private String getRootIRPGroup()
{
return GROUP_PREFIX + ROOT_IPR_GROUP;
}
/**
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#hasExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public boolean hasExtendedSecurity(NodeRef nodeRef)
{
return nodeService.hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY);
return (getIPRGroups(nodeRef) != null);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#getExtendedReaders(org.alfresco.service.cmr.repository.NodeRef)
* @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#getReaders(org.alfresco.service.cmr.repository.NodeRef)
*/
@SuppressWarnings("unchecked")
@Override
public Set<String> getExtendedReaders(NodeRef nodeRef)
{
Set<String> result = null;
Map<String, Integer> readerMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
if (readerMap != null)
{
result = readerMap.keySet();
}
return result;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#getExtendedWriters(org.alfresco.service.cmr.repository.NodeRef)
*/
@SuppressWarnings("unchecked")
@Override
public Set<String> getExtendedWriters(NodeRef nodeRef)
{
Set<String> result = null;
Map<String, Integer> map = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_WRITERS);
if (map != null)
{
result = map.keySet();
}
return result;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
*/
@Override
public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
{
addExtendedSecurity(nodeRef, readers, writers, true);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
*/
@Override
public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
public Set<String> getReaders(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
ParameterCheck.mandatory("applyToParents", applyToParents);
if (nodeRef != null)
Set<String> result = Collections.EMPTY_SET;
Pair<String, String> iprGroups = getIPRGroups(nodeRef);
if (iprGroups != null)
{
addExtendedSecurityImpl(nodeRef, readers, writers, applyToParents);
// add to the extended security roles
addExtendedSecurityRoles(nodeRef, readers, writers);
result = getAuthorities(iprGroups.getFirst());
}
return result;
}
/**
* Add extended security implementation method
*
* @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<String> readers, Set<String> writers, boolean applyToParents)
@Override
public Set<String> getWriters(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
ParameterCheck.mandatory("applyToParents", applyToParents);
// get the properties
final Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
// update the readers map
if (readers != null && readers.size() != 0)
Set<String> result = Collections.EMPTY_SET;
Pair<String, String> iprGroups = getIPRGroups(nodeRef);
if (iprGroups != null)
{
// get reader map
Map<String, Integer> readersMap = (Map<String, Integer>)properties.get(PROP_READERS);
// set the readers property (this will in turn apply the aspect if required)
properties.put(PROP_READERS, (Serializable)addToMap(readersMap, readers));
result = getAuthorities(iprGroups.getSecond());
}
// update the writers map
if (writers != null && writers.size() != 0)
{
// get writer map
Map<String, Integer> writersMap = (Map<String, Integer>)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<String> immediate authorities
*/
private Set<String> getAuthorities(String group)
{
Set<String> result = new HashSet<String>();
result.addAll(authorityService.getContainedAuthorities(null, group, true));
return result;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#set(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.util.Pair)
*/
@Override
public void set(NodeRef nodeRef, Pair<Set<String>, Set<String>> readersAndWriters)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
set(nodeRef, readersAndWriters.getFirst(), readersAndWriters.getSecond());
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#set(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
*/
@Override
public void set(NodeRef nodeRef, Set<String> readers, Set<String> writers)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
// remove existing extended security, assuming there is any
remove(nodeRef);
// find groups
Pair<String, String> iprGroups = createOrFindIPRGroups(readers, writers);
// assign groups to correct fileplan roles
NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, iprGroups.getFirst());
filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, iprGroups.getSecond());
// assign groups to node
assignIPRGroupsToNode(iprGroups, nodeRef);
// apply the readers to any renditions of the content
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.
* <p>
* Return null if none found.
*
* @param nodeRef node reference
* @return Pair<String, String> where first is the read group and second if the write group, null if none found
*/
private void addExtendedSecurityRoles(NodeRef nodeRef, Set<String> readers, Set<String> writers)
private Pair<String, String> getIPRGroups(NodeRef nodeRef)
{
NodeRef filePlan = filePlanService.getFilePlan(nodeRef);
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<String> authorities, String roleName)
{
if (authorities != null)
Pair<String, String> result = null;
String iprReaderGroup = null;
String iprWriterGroup = null;
// get all the set permissions
Set<AccessPermission> 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<String, String>(iprReaderGroup, iprWriterGroup);
}
return result;
}
/**
*
* @param map
* @param keys
* Given a set of readers and writers find or create the appropriate IPR groups.
* <p>
* The IPR groups are named with hashes of the authority lists in order to reduce
* the set of groups that require exact match. A further index is used to handle
* a situation where there is a hash clash, but a difference in the authority lists.
* <p>
* When no match is found the groups are created. Once created
*
* @param filePlan file plan
* @param readers authorities with read
* @param writers authorities with write
* @return Pair<String, String> where first is the full name of the read group and
* second is the full name of the write group
*/
private Pair<String, String> createOrFindIPRGroups(Set<String> readers, Set<String> writers)
{
return new Pair<String, String>(
createOrFindIPRGroup(READER_GROUP_PREFIX, readers),
createOrFindIPRGroup(WRITER_GROUP_PREFIX, writers));
}
/**
* Create or find an IPR group based on the provided prefix and authorities.
*
* @param groupPrefix group prefix
* @param authorities authorities
* @return String full group name
*/
private String createOrFindIPRGroup(String groupPrefix, Set<String> authorities)
{
String group = null;
// find group or determine what the next index is if no group exists or there is a clash
Pair<String, Integer> groupResult = findIPRGroup(groupPrefix, authorities);
if (groupResult.getFirst() == null)
{
group = createIPRGroup(groupPrefix, authorities, groupResult.getSecond());
}
else
{
group = groupResult.getFirst();
}
return group;
}
/**
* Given a group name prefix and the authorities, finds the exact match existing group.
* <p>
* If the group does not exist then the group returned is null and the index shows the next available
* group index for creation.
*
* @param groupPrefix group name prefix
* @param authorities authorities
* @return Pair<String, Integer> where first is the name of the found group, null if none found and second
* if the next available create index
*/
private Pair<String, Integer> findIPRGroup(String groupPrefix, Set<String> authorities)
{
String iprGroup = null;
int nextGroupIndex = 0;
boolean hasMoreItems = true;
int pageCount = 0;
// determine the short name prefix
String groupShortNamePrefix = getIPRGroupPrefixShortName(groupPrefix, authorities);
// iterate over the authorities to find a match
while (hasMoreItems == true)
{
// get matching authorities
PagingResults<String> results = authorityService.getAuthorities(AuthorityType.GROUP,
RMAuthority.ZONE_APP_RM,
groupShortNamePrefix,
false,
false,
new PagingRequest(MAX_ITEMS*pageCount, MAX_ITEMS));
// record the total count
nextGroupIndex = nextGroupIndex + results.getPage().size();
// see if any of the matching groups exactly match
for (String group : results.getPage())
{
// if exists and matches we have found our group
if (isIPRGroupTrueMatch(group, authorities))
{
iprGroup = group;
break;
}
}
// determine if there are any more pages to inspect
hasMoreItems = results.hasMoreItems();
pageCount ++;
}
return new Pair<String, Integer>(iprGroup, nextGroupIndex);
}
/**
* Determines whether a group exactly matches a list of authorities.
*
* @param authorities list of authorities
* @param group group
* @return
*/
private Map<String, Integer> addToMap(Map<String, Integer> map, Set<String> keys)
private boolean isIPRGroupTrueMatch(String group, Set<String> authorities)
{
Set<String> contained = authorityService.getContainedAuthorities(null, group, true);
return contained.equals(authorities);
}
/**
* Get IPR group prefix short name.
* <p>
* 'package' scope to help testing.
*
* @param prefix prefix
* @param authorities authorities
* @return String group prefix short name
*/
/*package*/ String getIPRGroupPrefixShortName(String prefix, Set<String> authorities)
{
if (map == null)
StringBuilder builder = new StringBuilder(128)
.append(prefix)
.append(getAuthoritySetHashCode(authorities));
return builder.toString();
}
/**
* Get IPR group short name.
* <p>
* Note this excludes the "GROUP_" prefix.
* <p>
* 'package' scope to help testing.
*
* @param prefix prefix
* @param readers read authorities
* @param writers write authorities
* @param index group index
* @return String group short name
*/
/*package*/ String getIPRGroupShortName(String prefix, Set<String> authorities, int index)
{
return getIPRGroupShortName(prefix, authorities, Integer.toString(index));
}
/**
* Get IPR group short name.
* <p>
* Note this excludes the "GROUP_" prefix.
*
* @param prefix prefix
* @param readers read authorities
* @param writers write authorities
* @param index group index
* @return String group short name
*/
private String getIPRGroupShortName(String prefix, Set<String> authorities, String index)
{
StringBuilder builder = new StringBuilder(128)
.append(getIPRGroupPrefixShortName(prefix, authorities))
.append(index);
return builder.toString();
}
/**
* Gets the hashcode value of a set of authorities.
*
* @param authorities set of authorities
* @return int hash code
*/
private int getAuthoritySetHashCode(Set<String> authorities)
{
int result = 0;
if (authorities != null && !authorities.isEmpty())
{
// create map
map = new HashMap<String, Integer>(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<String> children, int index)
{
ParameterCheck.mandatory("groupNamePrefix", groupNamePrefix);
// get the group name
String groupShortName = getIPRGroupShortName(groupNamePrefix, children, index);
// create group
String group = authorityService.createAuthority(AuthorityType.GROUP, groupShortName, groupShortName, Collections.singleton(RMAuthority.ZONE_APP_RM));
// add root parent
authorityService.addAuthority(getRootIRPGroup(), group);
// add children if provided
if (children != null)
{
if (!key.equals(PermissionService.ALL_AUTHORITIES))
for (String child : children)
{
if (map.containsKey(key))
if (authorityService.authorityExists(child) &&
!PermissionService.ALL_AUTHORITIES.equals(child))
{
// increment reference count
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<String, String> iprGroups, NodeRef nodeRef)
{
permissionService.setPermission(nodeRef, iprGroups.getFirst(), RMPermissionModel.READ_RECORDS, true);
permissionService.setPermission(nodeRef, iprGroups.getSecond(), RMPermissionModel.FILING, true);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#remove(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> 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<String> readers, Set<String>writers, boolean applyToParents)
{
if (hasExtendedSecurity(nodeRef))
ParameterCheck.mandatory("nodeRef", nodeRef);
Pair<String, String> iprGroups = getIPRGroups(nodeRef);
if (iprGroups != null)
{
removeExtendedSecurityImpl(nodeRef, readers, writers);
// remove any extended security that might be present
clearPermissions(nodeRef, iprGroups);
// remove the readers from any renditions of the content
if (isRecord(nodeRef))
{
@@ -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.
* <p>
* Removes the aspect and resets the property to null if all readers and writers are removed.
*
* Clear the nodes IPR permissions
*
* @param nodeRef node reference
* @param readers {@link Set} of readers
* @param writers {@link Set} of writers
*/
@SuppressWarnings("unchecked")
private void removeExtendedSecurityImpl(NodeRef nodeRef, Set<String> readers, Set<String> writers)
private void clearPermissions(NodeRef nodeRef, Pair<String, String> iprGroups)
{
Map<String, Integer> readersMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
nodeService.setProperty(nodeRef, PROP_READERS, (Serializable)removeFromMap(readersMap, readers));
Map<String, Integer> writersMap = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_WRITERS);
nodeService.setProperty(nodeRef, PROP_WRITERS, (Serializable)removeFromMap(writersMap, writers));
if (readersMap == null && writersMap == null)
{
// remove the aspect
nodeService.removeAspect(nodeRef, ASPECT_EXTENDED_SECURITY);
}
// remove group permissions from node
permissionService.clearPermission(nodeRef, iprGroups.getFirst());
permissionService.clearPermission(nodeRef, iprGroups.getSecond());
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedReaders(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override @Deprecated public Set<String> 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<String> getExtendedWriters(NodeRef nodeRef)
{
return getWriters(nodeRef);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
*/
@Override @Deprecated public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
{
set(nodeRef, readers, writers);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
*/
@Override @Deprecated public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
{
set(nodeRef, readers, writers);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override @Deprecated public void removeAllExtendedSecurity(NodeRef nodeRef)
{
remove(nodeRef);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
*/
@Override @Deprecated public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
{
remove(nodeRef);
}
/**
* Helper method to remove items from map or reduce reference count
*
* @param map ref count map
* @param keys keys
* @return Map<String, Integer> ref count map
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
*/
private Map<String, Integer> removeFromMap(Map<String, Integer> map, Set<String> keys)
@Override @Deprecated public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String>writers, boolean applyToParents)
{
if (map != null && keys != null && keys.size() != 0)
{
// remove 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);
}
}

View File

@@ -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<AccessPermission> keepPerms = new HashSet<AccessPermission>(5);
Set<AccessPermission> origionalPerms= getPermissionService().getAllSetPermissions(nodeRef);
for (AccessPermission perm : origionalPerms)
{
if (perm.getAuthority().startsWith(PermissionService.GROUP_PREFIX + ExtendedSecurityService.IPR_GROUP_PREFIX))
{
// then we can assume this is a permission we want to preserve
keepPerms.add(perm);
}
}
// clear all existing permissions and start again
getPermissionService().clearPermission(nodeRef, null);
// re-add keep'er permissions
for (AccessPermission keeper : keepPerms)
{
setPermission(nodeRef, keeper.getAuthority(), keeper.getPermission());
}
if (!inheritanceAllowed)
{
getPermissionService().setPermission(nodeRef, EXTENDED_READER, READ_RECORDS, true);
getPermissionService().setPermission(nodeRef, EXTENDED_WRITER, FILING, true);
String adminRole = getAdminRole(nodeRef);
getPermissionService().setPermission(nodeRef, adminRole, RMPermissionModel.FILING, true);
}
@@ -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);
}
/**

View File

@@ -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<String> readers = extendedPermissionService.getReaders(aclId);
Set<String> writers = extendedPermissionService.getWriters(aclId);
// add the current owner to the list of extended writers
String owner = ownableService.getOwner(nodeRef);
// get the documents readers and writers
Pair<Set<String>, Set<String>> readersAndWriters = extendedPermissionService.getReadersAndWriters(nodeRef);
// grab the frozen state
NodeRef currentFrozenState = currentVersion.getFrozenStateNodeRef();
@@ -752,13 +735,7 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
linkToPreviousVersionRecord(nodeRef, record);
// set the extended security
Set<String> combinedWriters = new HashSet<String>(writers);
if (owner != null && !owner.isEmpty() && !owner.equals(OwnableService.NO_OWNER))
{
combinedWriters.add(owner);
}
combinedWriters.add(authenticationUtil.getFullyAuthenticatedUser());
extendedSecurityService.addExtendedSecurity(record, readers, combinedWriters);
extendedSecurityService.set(record, readersAndWriters);
return record;
}

View File

@@ -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<String> getWriters(Long aclId);
/**
* Get the readers and writers for a given node.
* <p>
* The writers list includes the owner for the node.
*
* @param nodeRef node reference
* @return Pair<Set<String>, Set<String>> first is a set containing all the authorities that have read permission on the
* document and second is a set containing all the authorities that have write
* permission on the document, including the owner.
*
* @since 2.5
*/
Pair<Set<String>, Set<String>> getReadersAndWriters(NodeRef nodeRef);
}

View File

@@ -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<String>, Set<String>> getReadersAndWriters(NodeRef nodeRef)
{
// get the documents readers
Long aclId = nodeService.getNodeAclId(nodeRef);
Set<String> readers = getReaders(aclId);
Set<String> writers = getWriters(aclId);
// add the current owner to the list of extended writers
Set<String> modifiedWrtiers = new HashSet<String>(writers);
String owner = ownableService.getOwner(nodeRef);
if (StringUtils.isNotBlank(owner) &&
!owner.equals(OwnableService.NO_OWNER) &&
authorityService.authorityExists(owner))
{
modifiedWrtiers.add(owner);
}
return new Pair<Set<String>, Set<String>> (readers, modifiedWrtiers);
}
}

View File

@@ -0,0 +1,267 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.web.scripts.roles;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.patch.PatchDAO;
import org.alfresco.repo.domain.qname.QNameDAO;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.Pair;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* Webscript used for removing dynamic authorities from the records.
*
* @author Silviu Dinuta
* @since 2.3.0.7
*/
@SuppressWarnings("deprecation")
public class DynamicAuthoritiesGet extends DeclarativeWebScript implements RecordsManagementModel
{
private static final String MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO = "Parameter batchsize should be a number greater than 0.";
private static final String MESSAGE_PROCESSING_BEGIN = "Processing - BEGIN";
private static final String MESSAGE_PROCESSING_END = "Processing - END";
private static final String MESSAGE_PROCESSING_RECORD_END_TEMPLATE = "Processing record {0} - END";
private static final String MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE = "Processing record {0} - BEGIN";
private static final String MESSAGE_BATCHSIZE_IS_INVALID = "Parameter batchsize is invalid.";
private static final String MESSAGE_BATCHSIZE_IS_MANDATORY = "Parameter batchsize is mandatory";
private static final String SUCCESS_STATUS = "success";
private static final String FAILED_STATUS = "failed";
/**
* The logger
*/
private static Log logger = LogFactory.getLog(DynamicAuthoritiesGet.class);
private static final String BATCH_SIZE = "batchsize";
private static final String TOTAL_NUMBER_TO_PROCESS = "maxProcessedRecords";
private static final String MODEL_STATUS = "responsestatus";
private static final String MODEL_MESSAGE = "message";
private static final String MESSAGE_ALL_TEMPLATE = "Processed {0} records.";
private static final String MESSAGE_PARTIAL_TEMPLATE = "Processed first {0} records.";
private static final String MESSAGE_NO_RECORDS_TO_PROCESS = "There where no records to be processed.";
/** services */
private PatchDAO patchDAO;
private NodeDAO nodeDAO;
private QNameDAO qnameDAO;
private NodeService nodeService;
private PermissionService permissionService;
private ExtendedSecurityService extendedSecurityService;
private TransactionService transactionService;
/** service setters */
public void setPatchDAO(PatchDAO patchDAO) { this.patchDAO = patchDAO; }
public void setNodeDAO(NodeDAO nodeDAO) { this.nodeDAO = nodeDAO; }
public void setQnameDAO(QNameDAO qnameDAO) { this.qnameDAO = qnameDAO; }
public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; }
public void setPermissionService(PermissionService permissionService) { this.permissionService = permissionService; }
public void setExtendedSecurityService(ExtendedSecurityService extendedSecurityService) { this.extendedSecurityService = extendedSecurityService; }
public void setTransactionService(TransactionService transactionService) { this.transactionService = transactionService; }
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
{
Map<String, Object> model = new HashMap<String, Object>();
String batchSizeStr = req.getParameter(BATCH_SIZE);
String totalToBeProcessedRecordsStr = req.getParameter(TOTAL_NUMBER_TO_PROCESS);
Long size = 0L;
if (StringUtils.isBlank(batchSizeStr))
{
model.put(MODEL_STATUS, FAILED_STATUS);
model.put(MODEL_MESSAGE, MESSAGE_BATCHSIZE_IS_MANDATORY);
logger.info(MESSAGE_BATCHSIZE_IS_MANDATORY);
return model;
}
try
{
size = Long.parseLong(batchSizeStr);
if(size <= 0)
{
model.put(MODEL_STATUS, FAILED_STATUS);
model.put(MODEL_MESSAGE, MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO);
logger.info(MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO);
return model;
}
}
catch(NumberFormatException ex)
{
model.put(MODEL_STATUS, FAILED_STATUS);
model.put(MODEL_MESSAGE, MESSAGE_BATCHSIZE_IS_INVALID);
logger.info(MESSAGE_BATCHSIZE_IS_INVALID);
return model;
}
final Long batchSize = size;
// get the max node id and the extended security aspect
Long maxNodeId = patchDAO.getMaxAdmNodeID();
final Pair<Long, QName> recordAspectPair = qnameDAO.getQName(ASPECT_EXTENDED_SECURITY);
if(recordAspectPair == null)
{
model.put(MODEL_STATUS, SUCCESS_STATUS);
model.put(MODEL_MESSAGE, MESSAGE_NO_RECORDS_TO_PROCESS);
logger.info(MESSAGE_NO_RECORDS_TO_PROCESS);
return model;
}
//default total number of records to be processed to batch size value
Long totalNumberOfRecordsToProcess = batchSize;
if (StringUtils.isNotBlank(totalToBeProcessedRecordsStr))
{
try
{
totalNumberOfRecordsToProcess = Long.parseLong(totalToBeProcessedRecordsStr);
}
catch(NumberFormatException ex)
{
//do nothing here, the value will remain 0L in this case
}
}
final Long maxRecordsToProcess = totalNumberOfRecordsToProcess;
final List<NodeRef> processedNodes = new ArrayList<NodeRef>();
logger.info(MESSAGE_PROCESSING_BEGIN);
// by batch size
for (Long i = 0L; i < maxNodeId; i+=batchSize)
{
if(maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess)
{
break;
}
final Long currentIndex = i;
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
// get the nodes with the extended security aspect applied
List<Long> nodeIds = patchDAO.getNodesByAspectQNameId(recordAspectPair.getFirst(), currentIndex, currentIndex + batchSize);
// process each one
for (Long nodeId : nodeIds)
{
if(maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess)
{
break;
}
NodeRef record = nodeDAO.getNodePair(nodeId).getSecond();
String recordName = (String) nodeService.getProperty(record, ContentModel.PROP_NAME);
logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE, recordName));
processNode(record);
logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_END_TEMPLATE, recordName));
processedNodes.add(record);
}
return null;
}
},
false, // read only
true); // requires new
}
logger.info(MESSAGE_PROCESSING_END);
int processedNodesSize = processedNodes.size();
String message = "";
if(totalNumberOfRecordsToProcess == 0 || (totalNumberOfRecordsToProcess > 0 && processedNodesSize < totalNumberOfRecordsToProcess))
{
message = MessageFormat.format(MESSAGE_ALL_TEMPLATE, processedNodesSize);
}
if (totalNumberOfRecordsToProcess > 0 && totalNumberOfRecordsToProcess == processedNodesSize)
{
message = MessageFormat.format(MESSAGE_PARTIAL_TEMPLATE, totalNumberOfRecordsToProcess);
}
model.put(MODEL_STATUS, SUCCESS_STATUS);
model.put(MODEL_MESSAGE, message);
logger.info(message);
return model;
}
/**
* Process each node
*
* @param nodeRef
*/
@SuppressWarnings({ "unchecked"})
private void processNode(NodeRef nodeRef)
{
// get the reader/writer data
Map<String, Integer> readers = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_READERS);
Map<String, Integer> writers = (Map<String, Integer>)nodeService.getProperty(nodeRef, PROP_WRITERS);
// remove extended security aspect
nodeService.removeAspect(nodeRef, ASPECT_EXTENDED_SECURITY);
// remove dynamic authority permissions
permissionService.clearPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER);
permissionService.clearPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER);
// if record then ...
if (nodeService.hasAspect(nodeRef, ASPECT_RECORD))
{
// re-set extended security via API
extendedSecurityService.set(nodeRef, readers.keySet(), writers.keySet());
}
}
}