diff --git a/config/alfresco/site-services-context.xml b/config/alfresco/site-services-context.xml
index ee2f16356a..48a3043d66 100644
--- a/config/alfresco/site-services-context.xml
+++ b/config/alfresco/site-services-context.xml
@@ -108,6 +108,7 @@
+
diff --git a/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java b/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java
index a816e93110..bbf952804d 100644
--- a/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java
+++ b/source/java/org/alfresco/repo/management/subsystems/ChildApplicationContextFactory.java
@@ -420,7 +420,7 @@ public class ChildApplicationContextFactory extends AbstractPropertyBackedBean i
addBeanFactoryPostProcessor(configurer);
// 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);
}
diff --git a/source/java/org/alfresco/repo/site/SiteServiceImpl.java b/source/java/org/alfresco/repo/site/SiteServiceImpl.java
index f308aa4d9a..ee4dc90b16 100644
--- a/source/java/org/alfresco/repo/site/SiteServiceImpl.java
+++ b/source/java/org/alfresco/repo/site/SiteServiceImpl.java
@@ -40,12 +40,16 @@ import org.alfresco.query.PagingRequest;
import org.alfresco.query.PagingResults;
import org.alfresco.repo.activities.ActivityType;
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.FilterPropString;
import org.alfresco.repo.node.getchildren.GetChildrenCannedQuery;
import org.alfresco.repo.node.getchildren.GetChildrenCannedQueryFactory;
import org.alfresco.repo.node.getchildren.FilterPropString.FilterTypeString;
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.security.authentication.AuthenticationContext;
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.json.JSONException;
import org.json.JSONObject;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.extensions.surf.util.AbstractLifecycleBean;
import org.springframework.extensions.surf.util.ParameterCheck;
/**
@@ -92,7 +98,7 @@ import org.springframework.extensions.surf.util.ParameterCheck;
*
* @author Roy Wetherall
*/
-public class SiteServiceImpl implements SiteServiceInternal, SiteModel
+public class SiteServiceImpl extends AbstractLifecycleBean implements SiteServiceInternal, SiteModel, NodeServicePolicies.OnRestoreNodePolicy
{
/** Logger */
private static Log logger = LogFactory.getLog(SiteServiceImpl.class);
@@ -148,6 +154,7 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
private SysAdminParams sysAdminParams;
private BehaviourFilter behaviourFilter;
private SitesPermissionCleaner sitesPermissionsCleaner;
+ private PolicyComponent policyComponent;
private NamedObjectRegistry> cannedQueryRegistry;
@@ -288,6 +295,11 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
{
this.retryingTransactionHelper = retryingTransactionHelper;
}
+
+ public void setPolicyComponent(PolicyComponent policyComponent)
+ {
+ this.policyComponent = policyComponent;
+ }
public void setRoleComparator(Comparator roleComparator)
{
@@ -340,6 +352,26 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
PropertyCheck.mandatory(this, "authorityService", authorityService);
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)
@@ -405,9 +437,6 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
// Remove spaces from shortName
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
NodeRef existingSite = getSiteNodeRef(shortName, false);
if (existingSite != null)
@@ -444,6 +473,27 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
// Clear the sites inherited permissions
this.permissionService.setInheritParentPermissions(siteNodeRef, false);
+ // Create the relevant groups and assign permissions
+ setupSitePermissions(siteNodeRef, shortName, visibility, null);
+
+ // Return created site information
+ Map customProperties = getSiteCustomProperties(siteNodeRef);
+ SiteInfo siteInfo = new SiteInfoImpl(sitePreset, shortName, title, description, visibility, customProperties, siteNodeRef);
+ return siteInfo;
+ }
+
+ /**
+ * Setup the Site permissions.
+ *
+ * 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> memberships)
+ {
// Get the current user
final String currentUser = authenticationContext.getCurrentUserName();
@@ -455,10 +505,10 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
Set shareZones = new HashSet(2, 1.0f);
shareZones.add(AuthorityService.ZONE_APP_SHARE);
shareZones.add(AuthorityService.ZONE_AUTH_ALFRESCO);
-
+
// Create the site's groups
- String siteGroup = authorityService
- .createAuthority(AuthorityType.GROUP, getSiteGroup(shortName, false), shortName, shareZones);
+ String siteGroup = authorityService.createAuthority(
+ AuthorityType.GROUP, getSiteGroup(shortName, false), shortName, shareZones);
QName siteType = directNodeService.getType(siteNodeRef);
Set permissions = permissionService.getSettablePermissions(siteType);
for (String permission : permissions)
@@ -467,11 +517,21 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
String permissionGroup = authorityService.createAuthority(AuthorityType.GROUP, getSiteRoleGroup(
shortName, permission, false), shortName, shareZones);
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
permissionService.setPermission(siteNodeRef, permissionGroup, permission, true);
}
-
+
// Set the memberships details
// - give all authorities site consumer if site is public
// - give all authorities read properties if site is moderated
@@ -481,20 +541,20 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
if (SiteVisibility.PUBLIC.equals(visibility) == true &&
permissions.contains(SITE_CONSUMER))
{
- // From Alfresco 3.4 the 'site public' group is configurable. Out of the box it is
- // GROUP_EVERYONE so unconfigured behaviour is unchanged. But from 3.4 admins
- // can change the value of property site.public.group via JMX/properties files
- // to be another group of their choosing.
- // This then is the group that is given SiteConsumer access to newly created sites.
- final String sitePublicGroup = sysAdminParams.getSitePublicGroup();
-
- boolean groupExists = authorityService.authorityExists(sitePublicGroup);
- if (!PermissionService.ALL_AUTHORITIES.equals(sitePublicGroup) && !groupExists)
- {
- // If the group does not exist, we cannot create the site.
- throw new SiteServiceException(MSG_VISIBILITY_GROUP_MISSING, new Object[]{sitePublicGroup});
- }
-
+ // From Alfresco 3.4 the 'site public' group is configurable. Out of the box it is
+ // GROUP_EVERYONE so unconfigured behaviour is unchanged. But from 3.4 admins
+ // can change the value of property site.public.group via JMX/properties files
+ // to be another group of their choosing.
+ // This then is the group that is given SiteConsumer access to newly created sites.
+ final String sitePublicGroup = sysAdminParams.getSitePublicGroup();
+
+ boolean groupExists = authorityService.authorityExists(sitePublicGroup);
+ if (!PermissionService.ALL_AUTHORITIES.equals(sitePublicGroup) && !groupExists)
+ {
+ // If the group does not exist, we cannot create the site.
+ throw new SiteServiceException(MSG_VISIBILITY_GROUP_MISSING, new Object[]{sitePublicGroup});
+ }
+
permissionService.setPermission(siteNodeRef, sitePublicGroup, SITE_CONSUMER, true);
}
else if (SiteVisibility.MODERATED.equals(visibility) == true &&
@@ -506,19 +566,18 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
permissionService.setPermission(siteNodeRef,
PermissionService.ALL_AUTHORITIES,
PermissionService.READ_PERMISSIONS, true);
- authorityService.addAuthority(getSiteRoleGroup(shortName,
- SiteModel.SITE_MANAGER, true), currentUser);
+ if (memberships == null)
+ {
+ // add the default site manager authority
+ authorityService.addAuthority(getSiteRoleGroup(shortName,
+ SiteModel.SITE_MANAGER, true), currentUser);
+ }
// Return nothing
return null;
}
}, AuthenticationUtil.getSystemUserName());
-
- // Return created site information
- Map customProperties = getSiteCustomProperties(siteNodeRef);
- SiteInfo siteInfo = new SiteInfoImpl(sitePreset, shortName, title, description, visibility, customProperties, siteNodeRef);
- return siteInfo;
}
/**
@@ -1238,52 +1297,79 @@ public class SiteServiceImpl implements SiteServiceInternal, SiteModel
{
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
String cacheKey = this.tenantAdminService.getCurrentUserDomain() + '_' + shortName;
this.siteNodeRefs.remove(cacheKey);
- // 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
- 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);
- }
-
+ // Collection for recording the group memberships present on the site
+ final Map> groupsMemberships = new HashMap>();
+
// Delete the associated groups
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork