Custom Share role breaks existing sites solution

ADDED: Your new group is added to the ACL of both site and document library spaces with the role taken from your new group name i.e. new group is  GROUP_site_SOMESITEID_SiteCollaboratorPlus, SiteCollaboratorPlus is the role.

When you create a custom role in Share you must know up front what roles you need – before your project begins because it breaks your existing sites if you deploy the role after the fact. This isn’t always how things work out so here is a quick little webscript that will fix existing sites when deploying a new custom role.

This is a java backed webscript that will search all existing sites that do not have your custom role security group. It will then take your new role name via Spring and dynamically add it to all sites in share (I put it in spring because we don’t want people creating new roles to ALL sites via a URL parameter).

If you are un-familiar with how the files talk to eachother or where to put things please see the Alfresco Wiki on Java backed webscripts. Once the webscript is installed, simply go to http://localhost/alfresco/wcs/ecm/sites/fixrole (Make sure you change the spring context to add YOUR custom role name)

The context file (webscript-context.xml):

This descriptor file is where you want to put your custom group name that its complaining about. Just replace your siteid with the :SITE param you see below.

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN 2.0//EN' 'http://www.springframework.org/dtd/spring-beans-2.0.dtd'>

<beans>

    <bean id="webscript.ca.abstractive.ecm.alfresco.sitefix.fix-role.get" 

      parent="webscript">

        <property name="serviceRegistry" ref="ServiceRegistry" />
        <property name="searchService" ref="SearchService" /> 
        <property name="nodeService" ref="NodeService" />
        <property name="authorityService" ref="AuthorityService" /> 

        <!-- Custom role SiteCollaboratorPlus -->
        <property name="authorityName">
            <value>GROUP_site_:SITE_SiteCollaboratorPlus</value>
        </property>  
    </bean>
</beans>

The webscript descriptor (fix-role.get.desc.xml):

<webscript>
  <shortname>Fix Share Roles</shortname>
  <description>Adds new role to all existing sites</description>
  <url>/ecm/sites/fixrole</url>
  <authentication>user</authentication>
  <format default="">argument</format>
  <family>Toolkit</family> 
</webscript>

The Java (UtilityRoleCreation.java):

package ca.abstractive.ecm.alfresco.sites;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.alfresco.model.ContentModel;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Repository;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.extensions.webscripts.AbstractWebScript;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;

public class UtilityRoleCreation extends AbstractWebScript {
 
    protected ServiceRegistry serviceRegistry = null;
    protected SearchService searchService = null; 
    protected NodeService nodeService = null;
    protected AuthorityService authorityService = null;
    protected String authorityName = null;
    protected PermissionService permissionService = null;
    
    
    /**
     * Returns a list of sites in Alfresco
     *   
     * @return a list of site nodes 
     */  
    protected List<NodeRef> getSites(){
    
        //Get all sites
        String nodeQuery = "TYPE:\"st:site\"";

        SearchParameters params = new SearchParameters();
        params.setLanguage(SearchService.LANGUAGE_LUCENE);
        params.addStore(Repository.getStoreRef());
        params.setQuery(nodeQuery);
        ResultSet results = null;
        List<NodeRef> siteNodeRefs = new ArrayList<NodeRef>();
        
        try {
            results = this.searchService.query(params);
            if (results == null) {
                return null;

            } else {

                Iterator<ResultSetRow> siteNodes = results.iterator();
                while(siteNodes.hasNext()){
                     
                     ResultSetRow siteRow = siteNodes.next();
                     NodeRef nodeRef = siteRow.getNodeRef();
                     
                     siteNodeRefs.add(nodeRef);
                }
                
                return siteNodeRefs;
            }
            
        } finally {
            if (results != null) {
                results.close();
            }
        } 
         
    }    
    
    /**
     *  Webscript execute method
     *  
     */
    public void execute(WebScriptRequest req, WebScriptResponse res) 
            throws IOException  {
         
        try
        { 
            
            // build a json object
            JSONObject obj = new JSONObject();
            
            List<NodeRef> sites = this.getSites();
              
            Iterator<NodeRef> siteNodes = sites.iterator();
            while(siteNodes.hasNext()){
                 
                NodeRef nodeRef = siteNodes.next();
                  
                 //Get the sitename
                 String siteid = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);  
                 String siteGroup = new StringBuilder().append("GROUP_site_").append(siteid).toString();
                       
                 if(this.authorityService.authorityExists(siteGroup)){
                    
                    Set<String> authorities = this.authorityService.getContainedAuthorities(AuthorityType.GROUP, siteGroup, true);
                    String customRoleAuthorityName = this.authorityName.replace(":SITE", siteid);
                    
                    if (authorities.contains(customRoleAuthorityName) == false)
                     { 
                        obj.put(siteGroup, customRoleAuthorityName);
                        
                        //create the authority
                        String newAuthName = this.authorityService.createAuthority(AuthorityType.GROUP, customRoleAuthorityName.replace("GROUP_", "")); 
                        this.authorityService.addAuthority(siteGroup, newAuthName);
                         
                        // Assign the group the relevant permission on the site and document library
                        String[] bits = customRoleAuthorityName.split("_");
                        String role = bits[bits.length-1];
                        
                        permissionService.setPermission(nodeRef, customRoleAuthorityName, role, true);                            
                        NodeRef libraryNodeRef = nodeService.getChildByName(nodeRef, ContentModel.ASSOC_CONTAINS, "documentLibrary");
                        permissionService.setPermission(libraryNodeRef, customRoleAuthorityName, role, true);
                     }
                 }
            }
             
            // build a JSON string and send it back
            String jsonString = obj.toString();
            res.getWriter().write(jsonString);
        }
        catch(JSONException e)
        {
            throw new WebScriptException("Unable to serialize JSON");
        } 
    }
    
     
    
    /* ------------------------------------------------------------ */
    /* Getter/Setter methods */
    /* ------------------------------------------------------------ */
    
    /**
     * @return the serviceRegistry
     */
    public ServiceRegistry getServiceRegistry() {
        return serviceRegistry;
    }

    /**
     * @param serviceRegistry the serviceRegistry to set
     */
    public void setServiceRegistry(ServiceRegistry serviceRegistry) {
        this.serviceRegistry = serviceRegistry;
        this.searchService = serviceRegistry.getSearchService(); 
        this.nodeService = serviceRegistry.getNodeService();
        this.permissionService = serviceRegistry.getPermissionService();
    }

    /**
     * @return the searchService
     */
    public SearchService getSearchService() {
        return searchService;
    }

    /**
     * @param searchService the searchService to set
     */
    public void setSearchService(SearchService searchService) {
        this.searchService = searchService;
    }
    
    /**
     * @return the authorityService
     */
    public AuthorityService getAuthorityService() {
        return authorityService;
    }

    /**
     * @param authorityService the searchService to set
     */
    public void setAuthorityService(AuthorityService authorityService) {
        this.authorityService = authorityService;
    }
      

    /**
     * @return the nodeService
     */
    public NodeService getNodeService() {
        return nodeService;
    }

    /**
     * @param nodeService the nodeService to set
     */
    public void setNodeService(NodeService nodeService) {
        this.nodeService = nodeService;
    }


    public String getAuthorityName() {
        return authorityName;
    }


    public void setAuthorityName(String authorityName) {
        this.authorityName = authorityName;
    }
    
    /**
     * Set permission service
     */
    public void setPermissionService(PermissionService permissionService)
    {
        this.permissionService = permissionService;
    }  
    public PermissionService getPermissionService()
    {
        return permissionService;
    }
}

This entry was posted in Alfresco Share, JavaScript and tagged , by mike.priest. Bookmark the permalink.
mike.priest

About mike.priest

Alfresco Certified Engineer Mike is a software engineer and a design enthusiast. He has spent the past 5 years creating small to large scale applications for a variety of business problems including two Content Management Systems (Progress & Toolbox), a number of productivity apps, document imaging, Epos software, websites and more. His main focus is on UX/UI architecture and is always ripping things apart to find out better ways to make them work and easier to work with.

One thought on “Custom Share role breaks existing sites solution

  1. Hello, I’m trying to create a project in eclipse with your java code, but I have this two errors:

    The import org.alfresco.web cannot be resolved.
    Repository cannot be resolved.

    In the line:

    params.addStore(Repository.getStoreRef());

    For wich version is this code made? Am I missing some dependency?

    Thanx in advance,
    Andres

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>