Merged DEV/SITE_CONFIGURABILITY to HEAD

22041: ALF-3785 Configurable site public group.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@22043 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Neil McErlean
2010-08-27 13:08:31 +00:00
parent 0a41dd2c72
commit f51d8ac5c8
8 changed files with 169 additions and 8 deletions

View File

@@ -1,6 +1,7 @@
# Site service externalised display strings
site_service.unable_to_create=Unable to create site because the site short name {0} is already in use. Site short names must be unique.
site_service.visibility_group_missing=Unable to create site because the visibility group {0} does not exist.
site_service.can_not_update=Can not update site {0} because it does not exist.
site_service.can_not_delete=Can not delete site {0} because it does not exist.
site_service.site_no_exist=Site {0} does not exist.

View File

@@ -90,8 +90,7 @@
</property>
<property name="tenantService" ref="tenantService"/>
<property name="roleComparator" ref="siteRoleComparator" />
<property name="sysAdminParams" ref="sysAdminParams"/>
</bean>
<bean id="siteServiceScript" parent="baseJavaScriptExtension" class="org.alfresco.repo.site.script.ScriptSiteService">

View File

@@ -38,6 +38,8 @@
<property name="shareProtocol">
<value>${share.protocol}</value>
</property>
<property name="sitePublicGroup" value="${site.public.group}" />
</bean>
</beans>

View File

@@ -10,3 +10,8 @@ share.context=share
share.host=${localname}
share.port=8080
share.protocol=http
# Share Site configuration.
#
# This property controls who has visibility of created share sites.
site.public.group=GROUP_EVERYONE

View File

@@ -105,6 +105,15 @@ public interface SysAdminParams
*/
public String getShareProtocol();
/**
* Gets the group name used for public site visibility.
* Only members of this group will have SiteConsumer access to 'public' share sites.
*
* @return the name of the public site group.
* @since 3.4
*/
public String getSitePublicGroup();
/**
* Expands the special ${localname} token within a host name using the resolved DNS name for the local host.
*

View File

@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.license.LicenseService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
@@ -76,6 +77,9 @@ public class SysAdminParamsImpl implements SysAdminParams, ApplicationContextAwa
/** Share protocol. */
private String shareProtocol = "http";
// The default is GROUP_EVERYONE, although this will likely be overridden by an injected value from spring.
private String sitePublicGroup = PermissionService.ALL_AUTHORITIES;
public SysAdminParamsImpl()
{
// Establish the name of the local server so we can use it in token substitutions
@@ -283,4 +287,19 @@ public class SysAdminParamsImpl implements SysAdminParams, ApplicationContextAwa
{
return hostName.replace(TOKEN_LOCAL_NAME, localName);
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.admin.SysAdminParams#getSitePublicGroup()
*/
public String getSitePublicGroup()
{
return this.sitePublicGroup;
}
public void setSitePublicGroup(String sitePublicGroup)
{
this.sitePublicGroup = sitePublicGroup;
}
}

View File

@@ -33,6 +33,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.activities.ActivityType;
import org.alfresco.repo.admin.SysAdminParams;
import org.alfresco.repo.search.QueryParameterDefImpl;
import org.alfresco.repo.search.impl.lucene.LuceneQueryParser;
import org.alfresco.repo.security.authentication.AuthenticationContext;
@@ -70,13 +71,13 @@ import org.alfresco.service.cmr.tagging.TaggingService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.PropertyCheck;
import org.alfresco.util.PropertyMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.extensions.surf.util.ParameterCheck;
import org.alfresco.util.PropertyCheck;
/**
* Site Service Implementation. Also bootstraps the site AVM and DM stores.
@@ -109,6 +110,7 @@ public class SiteServiceImpl implements SiteService, SiteModel
/** Messages */
private static final String MSG_UNABLE_TO_CREATE = "site_service.unable_to_create";
private static final String MSG_VISIBILITY_GROUP_MISSING = "site_service.visibility_group_missing";
private static final String MSG_CAN_NOT_UPDATE = "site_service.can_not_update";
private static final String MSG_CAN_NOT_DELETE = "site_service.can_not_delete";
private static final String MSG_SITE_NO_EXIST = "site_service.site_no_exist";
@@ -133,6 +135,7 @@ public class SiteServiceImpl implements SiteService, SiteModel
private TenantAdminService tenantAdminService;
private RetryingTransactionHelper retryingTransactionHelper;
private Comparator<String> roleComparator;
private SysAdminParams sysAdminParams;
/**
@@ -269,6 +272,11 @@ public class SiteServiceImpl implements SiteService, SiteModel
this.roleComparator = roleComparator;
}
public void setSysAdminParams(SysAdminParams sysAdminParams)
{
this.sysAdminParams = sysAdminParams;
}
public Comparator<String> getRoleComparator()
{
return roleComparator;
@@ -398,7 +406,21 @@ public class SiteServiceImpl implements SiteService, SiteModel
// - add the current user to the site manager group
if (SiteVisibility.PUBLIC.equals(visibility) == true)
{
permissionService.setPermission(siteNodeRef, PermissionService.ALL_AUTHORITIES, SITE_CONSUMER, true);
// 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)
{

View File

@@ -28,6 +28,7 @@ import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.model.ForumModel;
import org.alfresco.repo.jscript.ClasspathScriptLocation;
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.model.FileFolderService;
@@ -37,6 +38,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.alfresco.service.cmr.repository.ScriptService;
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;
@@ -148,6 +150,10 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
}
}
/**
* This test method ensures that public sites can be created and that their site info is correct.
* It also tests that a duplicate site cannot be created.
*/
public void testCreateSite() throws Exception
{
// Create a public site
@@ -203,10 +209,108 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
{
// Expected
}
}
/**
* This method tests https://issues.alfresco.com/jira/browse/ALF-3785 which allows 'public' sites
* to be only visible to members of a configured group, by default EVERYONE.
*
* @author Neil McErlean
* @since 3.4
*/
@SuppressWarnings("deprecation")
public void testConfigurableSitePublicGroup() throws Exception
{
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
// We'll be configuring a JMX managed bean (in this test method only).
ChildApplicationContextFactory sysAdminSubsystem = (ChildApplicationContextFactory) applicationContext.getBean("sysAdmin");
final String sitePublicGroupPropName = "site.public.group";
final String originalSitePublicGroup = "GROUP_EVERYONE";
try
{
// Firstly we'll ensure that the site.public.group has the correct (pristine) value.
String groupName = sysAdminSubsystem.getProperty(sitePublicGroupPropName);
assertEquals(sitePublicGroupPropName + " was not the pristine value",
originalSitePublicGroup, groupName);
// Create a 'normal', unconfigured site.
SiteInfo unconfiguredSite = siteService.createSite(TEST_SITE_PRESET, "unconfigured",
TEST_TITLE, TEST_DESCRIPTION, SiteVisibility.PUBLIC);
assertTrue(containsConsumerPermission(originalSitePublicGroup, unconfiguredSite));
// Now set the managed bean's visibility group to something other than GROUP_EVERYONE.
// This is the group that will have visibility of subsequently created sites.
//
// We'll intentionally set it to a group that DOES NOT EXIST YET.
String newGroupName = this.getClass().getSimpleName() + System.currentTimeMillis();
String prefixedNewGroupName = PermissionService.GROUP_PREFIX + newGroupName;
sysAdminSubsystem.stop();
sysAdminSubsystem.setProperty(sitePublicGroupPropName, prefixedNewGroupName);
sysAdminSubsystem.start();
// Now create a site as before. It should fail as we're using a group that doesn't exist.
boolean expectedExceptionThrown = false;
try
{
siteService.createSite(TEST_SITE_PRESET, "thisShouldFail",
TEST_TITLE, TEST_DESCRIPTION, SiteVisibility.PUBLIC);
}
catch (SiteServiceException expected)
{
expectedExceptionThrown = true;
}
if (!expectedExceptionThrown)
{
fail("Expected exception on createSite with non-existent group was not thrown.");
}
// Now we'll create the group used above.
authorityService.createAuthority(AuthorityType.GROUP, newGroupName);
// And create the site as before. This time it should succeed.
SiteInfo configuredSite = siteService.createSite(TEST_SITE_PRESET, "configured",
TEST_TITLE, TEST_DESCRIPTION, SiteVisibility.PUBLIC);
// And check the permissions on the site.
assertTrue("The configured site should not have " + originalSitePublicGroup + " as SiteContributor",
!containsConsumerPermission(originalSitePublicGroup, configuredSite));
assertTrue("The configured site should have (newGroupName) as SiteContributor",
containsConsumerPermission(prefixedNewGroupName, configuredSite));
}
finally
{
// Reset the JMX bean to its out-of-the-box values.
sysAdminSubsystem.stop();
sysAdminSubsystem.setProperty(sitePublicGroupPropName, originalSitePublicGroup);
sysAdminSubsystem.start();
}
}
private boolean containsConsumerPermission(final String groupName,
SiteInfo unconfiguredSite)
{
boolean result = false;
Set<AccessPermission> perms = permissionService.getAllSetPermissions(unconfiguredSite.getNodeRef());
for (AccessPermission p : perms)
{
if (p.getAuthority().equals(groupName) &&
p.getPermission().equals(SiteModel.SITE_CONSUMER))
{
result = true;
}
}
return result;
}
/**
* This method tests that admin and system users can set site membership for a site of which they are not SiteManagers.
*/
public void testETHREEOH_15() throws Exception
{
SiteInfo siteInfo = this.siteService.createSite(TEST_SITE_PRESET, "mySiteTest", TEST_TITLE, TEST_DESCRIPTION, SiteVisibility.PUBLIC);