diff --git a/config/alfresco/bootstrap/alfrescoAuthorityStore.xml b/config/alfresco/bootstrap/alfrescoAuthorityStore.xml
index add78b272e..98d46081ba 100644
--- a/config/alfresco/bootstrap/alfrescoAuthorityStore.xml
+++ b/config/alfresco/bootstrap/alfrescoAuthorityStore.xml
@@ -33,6 +33,16 @@
GROUP_EMAIL_CONTRIBUTORS
+
+
+
+
+
+ GROUP_SITE_ADMINISTRATORS
+ GROUP_SITE_ADMINISTRATORS
+ GROUP_SITE_ADMINISTRATORS
+
+
@@ -65,6 +75,11 @@
view:pathref="${system.authorities_container.childname}/cm:GROUP_EMAIL_CONTRIBUTORS"
view:childName="cm:GROUP_EMAIL_CONTRIBUTORS" />
+
+
+
@@ -86,6 +101,11 @@
view:pathref="${system.authorities_container.childname}/cm:GROUP_EMAIL_CONTRIBUTORS"
view:childName="cm:GROUP_EMAIL_CONTRIBUTORS" />
+
+
+
diff --git a/config/alfresco/bootstrap/alfrescoAuthorityStoreDefaultMembers.xml b/config/alfresco/bootstrap/alfrescoAuthorityStoreDefaultMembers.xml
index 7018d3d1b5..8e47392a4e 100644
--- a/config/alfresco/bootstrap/alfrescoAuthorityStoreDefaultMembers.xml
+++ b/config/alfresco/bootstrap/alfrescoAuthorityStoreDefaultMembers.xml
@@ -17,6 +17,14 @@
+
+
+
+
+
+
+
diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties
index 25b596153f..65067464a1 100644
--- a/config/alfresco/messages/patch-service.properties
+++ b/config/alfresco/messages/patch-service.properties
@@ -509,3 +509,8 @@ patch.upgradeToActiviti5-13.description=Upgraded Activiti tables to 5.13 version
patch.emailAliasableAspect.description=Add email aliases to attrubute table
patch.emailAliasableAspect.result=Added email aliases to attribute table
+
+patch.addGroupAuthority.start=Adding group authority.
+patch.addGroupAuthority.result=\n\Successfully added group authority: {0}
+
+patch.siteAdministrators.description=Adds the 'GROUP_SITE_ADMINISTRATORS' group
diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml
index fa87247185..686589598c 100644
--- a/config/alfresco/patch/patch-services-context.xml
+++ b/config/alfresco/patch/patch-services-context.xml
@@ -3676,5 +3676,40 @@
classpath:alfresco/dbscripts/upgrade/4.2/${db.script.dialect}/restructure-idx_alf_nprop_s-MSSQL.sql
+
+
+ patch.siteAdministrators
+ patch.siteAdministrators.description
+ 0
+ 7002
+ 7003
+
+
+
+
+
+
+
+
+
+
+
+ SITE_ADMINISTRATORS
+
+
+ SITE_ADMINISTRATORS
+
+
+ ${alfresco_user_store.adminusername}
+
+
+
+ APP.DEFAULT
+ AUTH.ALF
+
+
+
+
+
diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties
index 5d1643954c..383c221761 100644
--- a/config/alfresco/version.properties
+++ b/config/alfresco/version.properties
@@ -23,4 +23,4 @@ version.build=r@scm-revision@-b@build-number@
# Schema number
-version.schema=7002
+version.schema=7003
diff --git a/source/java/org/alfresco/repo/admin/patch/impl/AddGroupAuthorityPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/AddGroupAuthorityPatch.java
new file mode 100644
index 0000000000..7935f811cf
--- /dev/null
+++ b/source/java/org/alfresco/repo/admin/patch/impl/AddGroupAuthorityPatch.java
@@ -0,0 +1,120 @@
+
+package org.alfresco.repo.admin.patch.impl;
+
+import java.util.Set;
+
+import org.alfresco.repo.admin.patch.AbstractPatch;
+import org.alfresco.service.cmr.security.AuthorityService;
+import org.alfresco.service.cmr.security.AuthorityType;
+import org.springframework.extensions.surf.util.I18NUtil;
+
+/**
+ * A patch to add a new group authority.
+ *
+ * @author Jamal Kaabi-Mofrad
+ */
+public class AddGroupAuthorityPatch extends AbstractPatch
+{
+ private static final String MSG_START = "patch.addGroupAuthority.start";
+ private static final String MSG_RESULT = "patch.addGroupAuthority.result";
+
+ private AuthorityService authorityService;
+ private GroupAuthorityDetails groupAuthorityDetails;
+
+ /**
+ * Sets the authority service.
+ *
+ * @param authorityService the authority service
+ */
+ public void setAuthorityService(AuthorityService authorityService)
+ {
+ this.authorityService = authorityService;
+ }
+
+ /**
+ * Sets the group authority details.
+ *
+ * @param groupAuthorityDetails the groupAuthorityDetails
+ */
+ public void setGroupAuthorityDetails(GroupAuthorityDetails groupAuthorityDetails)
+ {
+ this.groupAuthorityDetails = groupAuthorityDetails;
+ }
+
+ protected void checkProperties()
+ {
+ super.checkProperties();
+ checkPropertyNotNull(authorityService, "authorityService");
+ checkPropertyNotNull(groupAuthorityDetails, "groupAuthorityDetails");
+ }
+
+ @Override
+ protected String applyInternal() throws Exception
+ {
+ StringBuilder result = new StringBuilder(I18NUtil.getMessage(MSG_START));
+
+ String groupAuthorityName = authorityService.createAuthority(AuthorityType.GROUP,
+ this.groupAuthorityDetails.groupName,
+ this.groupAuthorityDetails.groupDisplayName,
+ this.groupAuthorityDetails.authorityZones);
+
+ if (this.groupAuthorityDetails.adminUserName != null
+ && authorityService.isAdminAuthority(this.groupAuthorityDetails.adminUserName))
+ {
+ // Add admin as a member of the created group
+ authorityService.addAuthority(groupAuthorityName,
+ this.groupAuthorityDetails.adminUserName);
+ }
+ result.append(I18NUtil.getMessage(MSG_RESULT, groupAuthorityName));
+
+ return result.toString();
+ }
+
+ /**
+ * A simple POJO to encapsulate the group authority details.
+ *
+ * @author Jamal Kaabi-Mofrad
+ */
+ public static class GroupAuthorityDetails
+ {
+ private String groupName;
+ private String groupDisplayName;
+ private String adminUserName;
+ private Set authorityZones;
+
+ /**
+ * @param groupName the groupName to set
+ */
+ public void setGroupName(String groupName)
+ {
+ this.groupName = groupName;
+ }
+
+ /**
+ * @param groupDisplayName the groupDisplayName to set
+ */
+ public void setGroupDisplayName(String groupDisplayName)
+ {
+ this.groupDisplayName = groupDisplayName;
+ }
+
+ /**
+ * Sets the Admin's username, so it can be included as a member of the
+ * group. If null, an empty group will be created.
+ *
+ * @param adminUserName the adminUserName to set
+ */
+ public void setAdminUserName(String adminUserName)
+ {
+ this.adminUserName = adminUserName;
+ }
+
+ /**
+ * @param authorityZones the authorityZones to set
+ */
+ public void setAuthorityZones(Set authorityZones)
+ {
+ this.authorityZones = authorityZones;
+ }
+ }
+}
diff --git a/source/test-java/org/alfresco/repo/security/authority/AuthorityServiceTest.java b/source/test-java/org/alfresco/repo/security/authority/AuthorityServiceTest.java
index 664ad8dd31..1d6f9365fe 100644
--- a/source/test-java/org/alfresco/repo/security/authority/AuthorityServiceTest.java
+++ b/source/test-java/org/alfresco/repo/security/authority/AuthorityServiceTest.java
@@ -95,7 +95,8 @@ public class AuthorityServiceTest extends TestCase
private static final int DEFAULT_SITE_GRP_CNT = 5; // default number of groups per site
private static final int DEFAULT_SITE_ROOT_GRP_CNT = 1; // default number of root groups per site
- private static final int DEFAULT_GRP_CNT = 2; // default (non-site) bootstrap groups - eg. GROUP_ALFRESCO_ADMINISTRATORS, GROUP_EMAIL_CONTRIBUTORS
+ private static final int DEFAULT_GRP_CNT = 3; // default (non-site) bootstrap groups -
+ // eg. GROUP_ALFRESCO_ADMINISTRATORS, GROUP_EMAIL_CONTRIBUTORS, GROUP_SITE_ADMINISTRATORS
private int SITE_CNT = 0;
private int GRP_CNT = 0;
@@ -430,7 +431,7 @@ public class AuthorityServiceTest extends TestCase
assertTrue(authorityService.hasAdminAuthority());
assertTrue(pubAuthorityService.hasAdminAuthority());
Set authorities = authorityService.getAuthorities();
- assertEquals("Unexpected result: " + authorities, 4 + (SITE_CNT*2), authorityService.getAuthorities().size());
+ assertEquals("Unexpected result: " + authorities, 4 + (SITE_CNT*3), authorityService.getAuthorities().size());
}
public void testNoUser()