diff --git a/config/alfresco/bootstrap/sitesSpace.xml b/config/alfresco/bootstrap/sitesSpace.xml index a4647aa342..f83cad3d4b 100644 --- a/config/alfresco/bootstrap/sitesSpace.xml +++ b/config/alfresco/bootstrap/sitesSpace.xml @@ -22,6 +22,40 @@ + + + + + GROUP_ALFRESCO_MODEL_ADMINISTRATORS + Collaborator + + + + + extensions + + + + + + + + + + + GROUP_ALFRESCO_MODEL_ADMINISTRATORS + Collaborator + + + + + module-deployments + + + + + + diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties index 2eb6e7f132..a56f19b34e 100644 --- a/config/alfresco/messages/patch-service.properties +++ b/config/alfresco/messages/patch-service.properties @@ -377,3 +377,9 @@ patch.db-V5.1-metadata-query-indexes.description=Add additional indexes to suppo patch.alfrescoModelAdministrators.description=Adds the 'GROUP_ALFRESCO_MODEL_ADMINISTRATORS' group patch.addInviteAddDirectEmailTemplates.description=Adds the email templates for the add-direct invite flow + +patch.addSurfConfigFolders.start=Adding surf-config children. +patch.addSurfConfigFolders.missingSurfConfig=\n\cm:surf-config folder is not present in '/app:company_home/st:sites'. +patch.addSurfConfigFolders.result=\n\Successfully added ''{0}'' folders and set the required permissions for ''{1}'' folders. +patch.addSurfConfigFolders.exist=\n\Skipped ''{0}'' folders as they already exist, but set the required permissions for ''{1}'' folders. +patch.addSurfConfigFolders.description=Adds 'cm:extensions' and 'cm:module-deployments' folders into surf-config folder. diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml index 58f5d3dd8a..53f7bd0c39 100644 --- a/config/alfresco/patch/patch-services-context.xml +++ b/config/alfresco/patch/patch-services-context.xml @@ -1304,4 +1304,54 @@ classpath:alfresco/dbscripts/upgrade/5.1/${db.script.dialect}/activiti-upgrade-5-19-0.sql + + + patch.addSurfConfigFolders + patch.addSurfConfigFolders.description + 0 + 9014 + 9015 + + + + + + + + + + + + + + + extensions + + + GROUP_ALFRESCO_MODEL_ADMINISTRATORS + + + Collaborator + + + true + + + + + module-deployments + + + GROUP_ALFRESCO_MODEL_ADMINISTRATORS + + + Collaborator + + + true + + + + + diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties index 11abc6308a..ae637e2b94 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=9014 +version.schema=9015 diff --git a/source/java/org/alfresco/repo/admin/patch/impl/AddSurfConfigFoldersPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/AddSurfConfigFoldersPatch.java new file mode 100644 index 0000000000..b106919d16 --- /dev/null +++ b/source/java/org/alfresco/repo/admin/patch/impl/AddSurfConfigFoldersPatch.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2005-2016 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 . + */ + +package org.alfresco.repo.admin.patch.impl; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.admin.patch.AbstractPatch; +import org.alfresco.repo.model.filefolder.HiddenAspect; +import org.alfresco.service.cmr.admin.PatchException; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AuthorityService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.site.SiteService; +import org.springframework.extensions.surf.util.I18NUtil; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * A patch to add folders into + * {@literal /app:company_home/st:sites/cm:surf-config} folder and optionally + * sets their permission. + * + * @author Jamal Kaabi-Mofrad + */ +public class AddSurfConfigFoldersPatch extends AbstractPatch +{ + + private static final String MSG_START = "patch.addSurfConfigFolders.start"; + private static final String MSG_RESULT = "patch.addSurfConfigFolders.result"; + private static final String MSG_EXIST = "patch.addSurfConfigFolders.exist"; + private static final String MSG_MISSING_SURFCONFIG = "patch.addSurfConfigFolders.missingSurfConfig"; + + private SiteService siteService; + private FileFolderService fileFolderService; + private PermissionService permissionService; + private AuthorityService authorityService; + private HiddenAspect hiddenAspect; + + private List folderDetailsList; + + public void setSiteService(SiteService siteService) + { + this.siteService = siteService; + } + + public void setFileFolderService(FileFolderService fileFolderService) + { + this.fileFolderService = fileFolderService; + } + + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public void setAuthorityService(AuthorityService authorityService) + { + this.authorityService = authorityService; + } + + public void setHiddenAspect(HiddenAspect hiddenAspect) + { + this.hiddenAspect = hiddenAspect; + } + + public void setFolderDetailsList(List folderDetailsList) + { + this.folderDetailsList = folderDetailsList; + } + + @Override + protected String applyInternal() throws Exception + { + StringBuilder result = new StringBuilder(I18NUtil.getMessage(MSG_START)); + + // /app:company_home/st:sites/ + NodeRef siteRoot = siteService.getSiteRoot(); + NodeRef surfConfigNodeRef = nodeService.getChildByName(siteRoot, ContentModel.ASSOC_CONTAINS, "surf-config"); + if (surfConfigNodeRef == null) + { + result.append(I18NUtil.getMessage(MSG_MISSING_SURFCONFIG)); + return result.toString(); + } + + Map createdFolders = new LinkedHashMap<>(); + Map skippedFolders = new LinkedHashMap<>(); + for (FolderDetails fd : folderDetailsList) + { + boolean appliedPermission = false; + NodeRef childFolder = nodeService.getChildByName(surfConfigNodeRef, ContentModel.ASSOC_CONTAINS, fd.folderName); + if (childFolder == null) + { + childFolder = fileFolderService.create(surfConfigNodeRef, fd.folderName, ContentModel.TYPE_FOLDER).getNodeRef(); + // apply index control aspect as part of the hidden aspect + hiddenAspect.hideNode(childFolder, false, false, false); + + appliedPermission = setPermission(childFolder, fd); + createdFolders.put(fd.folderName, appliedPermission); + } + else + { + if (fd.applyPermissionIfFolderExist) + { + appliedPermission = setPermission(childFolder, fd); + } + skippedFolders.put(fd.folderName, appliedPermission); + } + } + if (createdFolders.size() > 0) + { + result.append(I18NUtil.getMessage(MSG_RESULT, toString(createdFolders, false), toString(createdFolders, true))); + } + if (skippedFolders.size() > 0) + { + result.append(I18NUtil.getMessage(MSG_EXIST, toString(skippedFolders, false), toString(skippedFolders, true))); + } + return result.toString(); + } + + private boolean setPermission(NodeRef nodeRef, FolderDetails details) + { + if (details.authority != null && details.permission != null) + { + if (authorityService.getAuthorityNodeRef(details.authority) == null) + { + throw new PatchException("The [" + details.authority + "] is not a valid authority name"); + } + permissionService.setPermission(nodeRef, details.authority, details.permission, true); + + return true; + } + return false; + } + + private String toString(Map map, boolean onlyAppliedPermission) + { + StringBuilder sb = new StringBuilder(map.size() * 2); + for (Entry entry : map.entrySet()) + { + if (onlyAppliedPermission) + { + if (entry.getValue()) + { + sb.append(entry.getKey()).append(", "); + } + } + else + { + sb.append(entry.getKey()).append(", "); + } + } + return sb.substring(0, sb.length() - 2); + } + + /** + * @author Jamal Kaabi-Mofrad + */ + public static class FolderDetails + { + private String folderName; + private String authority; + private String permission; + // Whether to set the given permission even though the folder does exist + private boolean applyPermissionIfFolderExist; + + public void setFolderName(String folderName) + { + this.folderName = folderName; + } + + public void setAuthority(String authority) + { + this.authority = authority; + } + + public void setPermission(String permission) + { + this.permission = permission; + } + + public void setApplyPermissionIfFolderExist(boolean applyPermissionIfFolderExist) + { + this.applyPermissionIfFolderExist = applyPermissionIfFolderExist; + } + } +}