Undelete (recover from Archive store) of Share Sites now working.

- Sites deleted in 4.0 will now appear in the Trashcan, and the admin can restore them - including all user site memberships

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28921 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2011-07-11 15:26:04 +00:00
parent cc058d2425
commit 52f5a1c7d0
3 changed files with 145 additions and 58 deletions

View File

@@ -108,6 +108,7 @@
<property name="behaviourFilter" ref="policyBehaviourFilter" /> <property name="behaviourFilter" ref="policyBehaviourFilter" />
<property name="sitesPermissionsCleaner" ref="sitesPermissionsCleaner"/> <property name="sitesPermissionsCleaner" ref="sitesPermissionsCleaner"/>
<property name="cannedQueryRegistry" ref="siteCannedQueryRegistry"/> <property name="cannedQueryRegistry" ref="siteCannedQueryRegistry"/>
<property name="policyComponent" ref="policyComponent"/>
</bean> </bean>
<bean id="siteServiceScript" parent="baseJavaScriptExtension" class="org.alfresco.repo.site.script.ScriptSiteService"> <bean id="siteServiceScript" parent="baseJavaScriptExtension" class="org.alfresco.repo.site.script.ScriptSiteService">

View File

@@ -420,7 +420,7 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i
addBeanFactoryPostProcessor(configurer); addBeanFactoryPostProcessor(configurer);
// Add all the post processors of the parent, e.g. to make sure system placeholders get expanded properly // Add all the post processors of the parent, e.g. to make sure system placeholders get expanded properly
for (Object postProcessor : getParent().getBeansOfType(BeanFactoryPostProcessor.class).values()) for (Object postProcessor : getParent().getBeansOfType(BeanFactoryPostProcessor.class, false, false).values())
{ {
addBeanFactoryPostProcessor((BeanFactoryPostProcessor) postProcessor); addBeanFactoryPostProcessor((BeanFactoryPostProcessor) postProcessor);
} }

View File

@@ -40,12 +40,16 @@ import org.alfresco.query.PagingRequest;
import org.alfresco.query.PagingResults; import org.alfresco.query.PagingResults;
import org.alfresco.repo.activities.ActivityType; import org.alfresco.repo.activities.ActivityType;
import org.alfresco.repo.admin.SysAdminParams; import org.alfresco.repo.admin.SysAdminParams;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.node.NodeServicePolicies.OnRestoreNodePolicy;
import org.alfresco.repo.node.getchildren.FilterProp; import org.alfresco.repo.node.getchildren.FilterProp;
import org.alfresco.repo.node.getchildren.FilterPropString; import org.alfresco.repo.node.getchildren.FilterPropString;
import org.alfresco.repo.node.getchildren.GetChildrenCannedQuery; import org.alfresco.repo.node.getchildren.GetChildrenCannedQuery;
import org.alfresco.repo.node.getchildren.GetChildrenCannedQueryFactory; import org.alfresco.repo.node.getchildren.GetChildrenCannedQueryFactory;
import org.alfresco.repo.node.getchildren.FilterPropString.FilterTypeString; import org.alfresco.repo.node.getchildren.FilterPropString.FilterTypeString;
import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.search.impl.lucene.AbstractLuceneQueryParser; import org.alfresco.repo.search.impl.lucene.AbstractLuceneQueryParser;
import org.alfresco.repo.security.authentication.AuthenticationContext; import org.alfresco.repo.security.authentication.AuthenticationContext;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
@@ -85,6 +89,8 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.springframework.context.ApplicationEvent;
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
import org.springframework.extensions.surf.util.ParameterCheck; import org.springframework.extensions.surf.util.ParameterCheck;
/** /**
@@ -92,7 +98,7 @@ import org.springframework.extensions.surf.util.ParameterCheck;
* *
* @author Roy Wetherall * @author Roy Wetherall
*/ */
public class SiteServiceImpl implements SiteServiceInternal, SiteModel public class SiteServiceImpl extends AbstractLifecycleBean implements SiteServiceInternal, SiteModel, NodeServicePolicies.OnRestoreNodePolicy
{ {
/** Logger */ /** Logger */
private static Log logger = LogFactory.getLog(SiteServiceImpl.class); private static Log logger = LogFactory.getLog(SiteServiceImpl.class);
@@ -148,6 +154,7 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
private SysAdminParams sysAdminParams; private SysAdminParams sysAdminParams;
private BehaviourFilter behaviourFilter; private BehaviourFilter behaviourFilter;
private SitesPermissionCleaner sitesPermissionsCleaner; private SitesPermissionCleaner sitesPermissionsCleaner;
private PolicyComponent policyComponent;
private NamedObjectRegistry<CannedQueryFactory<NodeRef>> cannedQueryRegistry; private NamedObjectRegistry<CannedQueryFactory<NodeRef>> cannedQueryRegistry;
@@ -289,6 +296,11 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
this.retryingTransactionHelper = retryingTransactionHelper; this.retryingTransactionHelper = retryingTransactionHelper;
} }
public void setPolicyComponent(PolicyComponent policyComponent)
{
this.policyComponent = policyComponent;
}
public void setRoleComparator(Comparator<String> roleComparator) public void setRoleComparator(Comparator<String> roleComparator)
{ {
this.roleComparator = roleComparator; this.roleComparator = roleComparator;
@@ -341,6 +353,26 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
PropertyCheck.mandatory(this, "sitesXPath", sitesXPath); PropertyCheck.mandatory(this, "sitesXPath", sitesXPath);
} }
/* (non-Javadoc)
* @see org.springframework.extensions.surf.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent)
*/
@Override
protected void onBootstrap(ApplicationEvent event)
{
this.policyComponent.bindClassBehaviour(
OnRestoreNodePolicy.QNAME,
SiteModel.TYPE_SITE,
new JavaBehaviour(this, "onRestoreNode"));
}
/* (non-Javadoc)
* @see org.springframework.extensions.surf.util.AbstractLifecycleBean#onShutdown(org.springframework.context.ApplicationEvent)
*/
@Override
protected void onShutdown(ApplicationEvent event)
{
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.alfresco.service.cmr.site.SiteService#hasCreateSitePermissions() * @see org.alfresco.service.cmr.site.SiteService#hasCreateSitePermissions()
@@ -405,9 +437,6 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
// Remove spaces from shortName // Remove spaces from shortName
final String shortName = passedShortName.replaceAll(" ", ""); final String shortName = passedShortName.replaceAll(" ", "");
/**
* Check that the site does not already exist
*/
// Check to see if we already have a site of this name // Check to see if we already have a site of this name
NodeRef existingSite = getSiteNodeRef(shortName, false); NodeRef existingSite = getSiteNodeRef(shortName, false);
if (existingSite != null) if (existingSite != null)
@@ -444,6 +473,27 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
// Clear the sites inherited permissions // Clear the sites inherited permissions
this.permissionService.setInheritParentPermissions(siteNodeRef, false); this.permissionService.setInheritParentPermissions(siteNodeRef, false);
// Create the relevant groups and assign permissions
setupSitePermissions(siteNodeRef, shortName, visibility, null);
// Return created site information
Map<QName, Serializable> customProperties = getSiteCustomProperties(siteNodeRef);
SiteInfo siteInfo = new SiteInfoImpl(sitePreset, shortName, title, description, visibility, customProperties, siteNodeRef);
return siteInfo;
}
/**
* Setup the Site permissions.
* <p>
* Creates the top-level site group, plus all the Role groups required for users of the site.
*
* @param siteNodeRef
* @param shortName
* @param visibility
*/
private void setupSitePermissions(
final NodeRef siteNodeRef, final String shortName, final SiteVisibility visibility, final Map<String, Set<String>> memberships)
{
// Get the current user // Get the current user
final String currentUser = authenticationContext.getCurrentUserName(); final String currentUser = authenticationContext.getCurrentUserName();
@@ -457,8 +507,8 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
shareZones.add(AuthorityService.ZONE_AUTH_ALFRESCO); shareZones.add(AuthorityService.ZONE_AUTH_ALFRESCO);
// Create the site's groups // Create the site's groups
String siteGroup = authorityService String siteGroup = authorityService.createAuthority(
.createAuthority(AuthorityType.GROUP, getSiteGroup(shortName, false), shortName, shareZones); AuthorityType.GROUP, getSiteGroup(shortName, false), shortName, shareZones);
QName siteType = directNodeService.getType(siteNodeRef); QName siteType = directNodeService.getType(siteNodeRef);
Set<String> permissions = permissionService.getSettablePermissions(siteType); Set<String> permissions = permissionService.getSettablePermissions(siteType);
for (String permission : permissions) for (String permission : permissions)
@@ -468,6 +518,16 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
shortName, permission, false), shortName, shareZones); shortName, permission, false), shortName, shareZones);
authorityService.addAuthority(siteGroup, permissionGroup); authorityService.addAuthority(siteGroup, permissionGroup);
// add any supplied memberships to it
String siteRoleGroup = getSiteRoleGroup(shortName, permission, true);
if (memberships != null && memberships.containsKey(siteRoleGroup))
{
for (String authority : memberships.get(siteRoleGroup))
{
authorityService.addAuthority(siteRoleGroup, authority);
}
}
// Assign the group the relevant permission on the site // Assign the group the relevant permission on the site
permissionService.setPermission(siteNodeRef, permissionGroup, permission, true); permissionService.setPermission(siteNodeRef, permissionGroup, permission, true);
} }
@@ -506,19 +566,18 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
permissionService.setPermission(siteNodeRef, permissionService.setPermission(siteNodeRef,
PermissionService.ALL_AUTHORITIES, PermissionService.ALL_AUTHORITIES,
PermissionService.READ_PERMISSIONS, true); PermissionService.READ_PERMISSIONS, true);
if (memberships == null)
{
// add the default site manager authority
authorityService.addAuthority(getSiteRoleGroup(shortName, authorityService.addAuthority(getSiteRoleGroup(shortName,
SiteModel.SITE_MANAGER, true), currentUser); SiteModel.SITE_MANAGER, true), currentUser);
}
// Return nothing // Return nothing
return null; return null;
} }
}, AuthenticationUtil.getSystemUserName()); }, AuthenticationUtil.getSystemUserName());
// Return created site information
Map<QName, Serializable> customProperties = getSiteCustomProperties(siteNodeRef);
SiteInfo siteInfo = new SiteInfoImpl(sitePreset, shortName, title, description, visibility, customProperties, siteNodeRef);
return siteInfo;
} }
/** /**
@@ -1238,29 +1297,14 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
{ {
throw new SiteServiceException(MSG_CAN_NOT_DELETE, new Object[]{shortName}); throw new SiteServiceException(MSG_CAN_NOT_DELETE, new Object[]{shortName});
} }
final QName siteType = directNodeService.getType(siteNodeRef); final QName siteType = this.directNodeService.getType(siteNodeRef);
// Delete the cached reference // Delete the cached reference
String cacheKey = this.tenantAdminService.getCurrentUserDomain() + '_' + shortName; String cacheKey = this.tenantAdminService.getCurrentUserDomain() + '_' + shortName;
this.siteNodeRefs.remove(cacheKey); this.siteNodeRefs.remove(cacheKey);
// The default behaviour is that sites cannot be deleted. But we disable that behaviour here // Collection for recording the group memberships present on the site
// in order to allow site deletion only via this service. Share calls this service for deletion. final Map<String, Set<String>> groupsMemberships = new HashMap<String, Set<String>>();
//
// See ALF-7888 for some background on this issue
behaviourFilter.disableBehaviour(siteNodeRef, ContentModel.ASPECT_UNDELETABLE);
try
{
// Delete the site node, marking it as "not to be archived" on the way.
// The site node will be permanently deleted.
this.nodeService.addAspect(siteNodeRef, ContentModel.ASPECT_TEMPORARY, null);
this.nodeService.deleteNode(siteNodeRef);
}
finally
{
behaviourFilter.enableBehaviour(siteNodeRef, ContentModel.ASPECT_UNDELETABLE);
}
// Delete the associated groups // Delete the associated groups
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>() AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
@@ -1268,23 +1312,65 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
public Object doWork() throws Exception public Object doWork() throws Exception
{ {
// Delete the master site group // Delete the master site group
authorityService.deleteAuthority(getSiteGroup(shortName, true), false); final String siteGroup = getSiteGroup(shortName, true);
if (authorityService.authorityExists(siteGroup))
{
authorityService.deleteAuthority(siteGroup, false);
// Iterate over the role related groups and delete then // Iterate over the role related groups and delete then
Set<String> permissions = permissionService.getSettablePermissions(siteType); Set<String> permissions = permissionService.getSettablePermissions(siteType);
for (String permission : permissions) for (String permission : permissions)
{ {
String siteRoleGroup = getSiteRoleGroup(shortName, permission, true); String siteRoleGroup = getSiteRoleGroup(shortName, permission, true);
// Collect up the memberships so we can potentially restore them later
Set<String> groupUsers = authorityService.getContainedAuthorities(null, siteRoleGroup, true);
groupsMemberships.put(siteRoleGroup, groupUsers);
// Delete the site role group
authorityService.deleteAuthority(siteRoleGroup); authorityService.deleteAuthority(siteRoleGroup);
} }
}
return null; return null;
} }
}, AuthenticationUtil.getSystemUserName()); }, AuthenticationUtil.getSystemUserName());
// Save the group memberships so we can use them later
this.nodeService.setProperty(siteNodeRef, QName.createQName(null, "memberships"), (Serializable)groupsMemberships);
// The default behaviour is that sites cannot be deleted. But we disable that behaviour here
// in order to allow site deletion only via this service. Share calls this service for deletion.
//
// See ALF-7888 for some background on this issue
this.behaviourFilter.disableBehaviour(siteNodeRef, ContentModel.ASPECT_UNDELETABLE);
try
{
this.nodeService.deleteNode(siteNodeRef);
}
finally
{
this.behaviourFilter.enableBehaviour(siteNodeRef, ContentModel.ASPECT_UNDELETABLE);
}
logger.debug("site deleted :" + shortName); logger.debug("site deleted :" + shortName);
} }
/**
* @see org.alfresco.repo.node.NodeServicePolicies.OnRestoreNodePolicy#onRestoreNode(org.alfresco.service.cmr.repository.ChildAssociationRef)
*/
@Override
public void onRestoreNode(ChildAssociationRef childAssocRef)
{
// regenerate the groups for the site when it is restored from the Archive store
NodeRef siteRef = childAssocRef.getChildRef();
setupSitePermissions(
siteRef,
(String)directNodeService.getProperty(siteRef, ContentModel.PROP_NAME),
getSiteVisibility(siteRef),
(Map<String, Set<String>>)directNodeService.getProperty(siteRef, QName.createQName(null, "memberships")));
}
/** /**
* @see org.alfresco.service.cmr.site.SiteService#listMembers(java.lang.String, java.lang.String, java.lang.String, int) * @see org.alfresco.service.cmr.site.SiteService#listMembers(java.lang.String, java.lang.String, java.lang.String, int)
*/ */