cancel
Showing results for 
Search instead for 
Did you mean: 

Customise access permissions

doiheartwentyon
Champ in-the-making
Champ in-the-making
I'm trying to extend Share's access permissions so that anyone can start a new discussion without having to be invited to the site first. After looking around the source it seemed I had to extend the "SiteConsumer" role defined in webapps/alfresco/WEB-INF/classes/alfresco/model/sitePermissionDefinitions.xml. (for the moment I'm just editing the supplied files rather than trying to package them up separately.)

So I tried adding a new permissionset which would apply to fm:forum objects, like this

   <permissionSet type="st:site" expose="selected">

      <permissionGroup name="SiteManager" allowFullControl="true" expose="true" />

      <permissionGroup name="SiteCollaborator" allowFullControl="false" expose="true">
         <includePermissionGroup permissionGroup="Collaborator" type="cm:cmobject" />
      </permissionGroup>

      <permissionGroup name="SiteContributor" allowFullControl="false" expose="true">
         <includePermissionGroup permissionGroup="Contributor" type="cm:cmobject" />
      </permissionGroup>

      <permissionGroup name="SiteConsumer" allowFullControl="false" expose="true">
         <includePermissionGroup permissionGroup="Consumer" type="cm:cmobject" />
         <includePermissionGroup permissionGroup="ForumContributor" type="fm:forum" />
      </permissionGroup>

   </permissionSet>

   <permissionSet type="fm:forum" expose="selected">

      <permissionGroup name="ForumContributor" allowFullControl="false" expose="true">
         <includePermissionGroup permissionGroup="Contributor" type="cm:cmobject" />
      </permissionGroup>

   </permissionSet>


I thought the type="fm:forum" in the new permissionSet would restrict the extra permissions to objects of that type, but that didn't happen: running Alfresco with this setup grants contributor privileges to all content objects (blog, wiki and so on)

Next I tried adding requiredType="fm:forum" to the permissionGroup, but that didn't have any effect.

I guess fm:forum isn't as tightly coupled to the forum content type as I thought it was, or the contained cm:cmobject is somehow unrestricting the permission definition. What's the recommended way to go about it?
8 REPLIES 8

zaizi
Champ in-the-making
Champ in-the-making
You know that if you create the site as public, anyone can just start a discussion and access the site functionality without joining the site first.

doiheartwentyon
Champ in-the-making
Champ in-the-making
You know that if you create the site as public, anyone can just start a discussion and access the site functionality without joining the site first.

Huh, that's strange, the site is public but I don't get that behaviour. I'm pretty sure all my users are SiteConsumer whether or not they join the site. I thought joining a public site was just a way to tell the site owner you are listening, it doesn't affect your permissions. Private sites, maybe you have to join to read content.

When I changed the permissions as above, after all, both joined and non-joined consumers were allowed to post : discussions, blog entries everything. My out-of-the-box (Labs 3 final) setup definitely prevented consumers from creating any content, including discussion topics and comments on blog entries (which is another thing I would like to permit, no idea where to do it though)

jtp
Champ in-the-making
Champ in-the-making
I've got this same issue on Labs3 Stable.  Site Consumers were unable to comment or reply unless I upped them to a contributor or collaborator.

mikeh
Star Contributor
Star Contributor
I remember going round this discussion during design sessions, but can't remember what conclusions we came to! Obviously from the app's behaviour, the consensus was that the default role of consumer was a read-only permission across the site.

I'm not the permissions expert (and he's busy right now with a new addition to his family) so don't know the best way of allowing SiteConsumers to be able to comment. I start playing with permissions around the fmSmiley Tongueost type (create permission) but I suspect you'd also have to enable create children permission on fm:topic too.

Mike

burriad
Champ in-the-making
Champ in-the-making
As an answer to the very first question: Unfortunately, it is impossible to restrict permissions to a type or an aspect only through configuration.

But the good news is that you can implement a workaround using a dynamic authority, which has the following steps:
1.  Define a dynamic authority class which checks for the presence of the type or the aspect
2. Register the class in the public-services-security-context.xml as an additional dynamic authority
3. Extend your permissionDefinitions.xml file with the additional permission.

Let's look at the steps in detail, and I wrap up from behind:
3. In permissionDefinitions.xml:
- Add a basic permissionSet "Perm" and an extended permissionSet "Perm_ext" as follows

        <permissionGroup name="Perm" allowFullControl="false" expose="false">
            <includePermissionGroup permissionGroup="Read" type="sys:base" />
        </permissionGroup>
       
        <permissionGroup name="Perm_ext" allowFullControl="false" expose="false">
            <includePermissionGroup permissionGroup="Write" type="sys:base" />
        </permissionGroup>

- Also make sure you link the extended set to a role through a global permission

    <globalPermission permission="Perm_ext" authority="ROLE_EXT" />

1. Write your DynamicAuthority class. Below is a generic one for types, but the trick works in other settings as well

package org.alfresco.module.mymodule;

import * /* you have to do it yourself */

public class GenericTypeBasedDynamicAuthority implements DynamicAuthority {

   private NodeService nodeService;
   private PermissionsDaoComponent permissionsDaoComponent;
   private AuthorityService authorityService;
   
   // Deduced values
   private PermissionReference basePermission;
   private List<QName> applicableTypes = new ArrayList<QName>();
   private String authority;
      
   @Override
   public String getAuthority() {
      return authority;
   }

   @Override
   public boolean hasAuthority(NodeRef nodeRef, String userName) {
                AccessStatus state = hasBasePermission(nodeRef, userName);
      return (applicableTypes.contains(nodeService.getType(nodeRef)) && (state == AccessStatus.ALLOWED));            
   }

   @Override
   public Set<PermissionReference> requiredFor() {
      return null;
   }

   public void setNodeService(NodeService nodeService) {
      this.nodeService = nodeService;
   }

   public NodeService getNodeService() {
      return nodeService;
   }

   public void setPermissionsDaoComponent(PermissionsDaoComponent permissionsDaoComponent) {
      this.permissionsDaoComponent = permissionsDaoComponent;
   }

   public PermissionsDaoComponent getPermissionsDaoComponent() {
      return permissionsDaoComponent;
   }

   public void setAuthorityService(AuthorityService authorityService) {
      this.authorityService = authorityService;
   }

   public AuthorityService getAuthorityService() {
      return authorityService;
   }

   public void setAuthority(String authority) {
      this.authority = authority;
   }

   public void setTypes(List<String> types) {
      this.applicableTypes.clear();
      for (String type : types) {
         this.applicableTypes.add(QName.createQName(MyModel.NAMESPACE, type));
      }
   }

   public List<String> getTypes() {
      List<String> result = new ArrayList<String>();
      for (QName qname : applicableTypes) {
         result.add(qname.getLocalName());
      }
      return result;
   }

   public void setBaseRole(String role) {
      this.basePermission = SimplePermissionReference.getPermissionReference(ContentModel.TYPE_CMOBJECT, role);
   }

   public String getBaseRole() {
      return basePermission.getName();
   }

   private AccessStatus hasBasePermission(NodeRef nodeRef, String userName) {
      NodePermissionEntry nodePermissions = permissionsDaoComponent.getPermissions(nodeRef);
      List<? extends PermissionEntry> permEntries = nodePermissions.getPermissionEntries();
      
       Set<String> auths = getAuthorityService().getAuthorities();
       auths.add(userName);
      for (PermissionEntry permEntry : permEntries) {
         if (permEntry.getPermissionReference().equals(basePermission) &&
               auths.contains(permEntry.getAuthority()) &&
               permEntry.getAccessStatus() == AccessStatus.ALLOWED) {
            return AccessStatus.ALLOWED;
         }
      }
      
      return AccessStatus.DENIED;
   }
}

So, now the stage is set for the last configuration: the public-service-security-context.xml. Here's the excerpt:

<bean id="permissionServiceImpl" class="org.alfresco.repo.security.permissions.impl.PermissionServiceImpl">
        <property name="nodeService">
            <ref bean="mtAwareNodeService" />
        </property>
        <property name="tenantService">
            <ref bean="tenantService"/>
        </property>
        <property name="dictionaryService">
            <ref bean="dictionaryService" />
        </property>
        <property name="permissionsDaoComponent">
            <ref bean="permissionsDaoComponent" />
        </property>
        <property name="modelDAO">
            <ref bean="permissionsModelDAO" />
        </property>
        <property name="authorityService">
            <ref bean="authorityService" />
        </property>
        <property name="accessCache">
            <ref bean="permissionsAccessCache" />
        </property>
        <property name="policyComponent">
            <ref bean="policyComponent" />
        </property>
        <property name="aclDaoComponent">
            <ref bean="aclDaoComponent" />
        </property>
        <property name="dynamicAuthorities">
            <list>
                <ref bean="ownerDynamicAuthority" />
                <ref bean="lockOwnerDynamicAuthority" />
                <!– dynamic authorities for roles on types –>
                <ref bean="myDynamicAuthority" />
            
            </list>
        </property>
    </bean>

    <bean id="myDynamicAuthority" class="org.alfresco.module.mymodule.GenericTypeBasedDynamicAuthority">
        <property name="nodeService">
            <ref bean="nodeService"/>
        </property>
        <property name="permissionsDaoComponent">
            <ref bean="permissionsDaoComponent" />
        </property>
        <property name="authorityService">
            <ref bean="authorityService" />
        </property>
        <property name="authority">
            <value>ROLE_EXT</value>
        </property>
        <property name="baseRole">
            <value>Perm</value>
        </property>
        <property name="types">
            <list>
                <value>yourType</value>
            </list>
        </property>
    </bean>

Above "yourType" is the type you want to extend your permissions on.

I hope this helps! Happy hacking  :lol:

chicco0386
Champ on-the-rise
Champ on-the-rise
Hi,

I'm using Alfresco 3.1 Labs….

I want to create a new permissionGroup of Users….

So I've operate  like this:

1) open the XML file tomcat/webapps/alfresco/WEB-INF/classes/alfresco/model/permissionDefinitions.xml
2) write this
<permissionGroup name="SolaScrittura" allowFullControl="false" expose="true" >

          <includePermissionGroup permissionGroup="Read" type="sys:base" />
          <includePermissionGroup permissionGroup="CreateChildren" type="sys:base" />

      </permissionGroup>
under the
<!– ================================================ –>

   <!– Permissions available to all content and folders –>

   <!– ================================================ –>

3) after under
<!– =============================== –>

   <!– Permissions specific to content –>

   <!– =============================== –>

I alowed the Group

<permissionSet type="cm:content" expose="selected">



      <!– Content specific roles.                                                       –>

     

      <permissionGroup name="Coordinator" extends="true" expose="true"/>

      <permissionGroup name="Collaborator" extends="true" expose="true"/>

      <permissionGroup name="Contributor" extends="true" expose="true"/>

      <permissionGroup name="Editor" extends="true" expose="true"/>

      <permissionGroup name="Consumer" extends="true" expose="true"/>

      <permissionGroup name="RecordAdministrator" extends="true" expose="false"/>
      <permissionGroup name="SolaScrittura" extends="true" expose="true"/>

     

   </permissionSet>

   

   

    <permissionSet type="cm:folder" expose="selected">



      <!– Content folder specific roles.                                                       –>

     

      <permissionGroup name="Coordinator" extends="true" expose="true"/>

      <permissionGroup name="Collaborator" extends="true" expose="true"/>

      <permissionGroup name="Contributor" extends="true" expose="true"/>

      <permissionGroup name="Editor" extends="true" expose="true"/>

      <permissionGroup name="Consumer" extends="true" expose="true"/>

      <permissionGroup name="RecordAdministrator" extends="true" expose="false"/>
      <permissionGroup name="SolaScrittura" extends="true" expose="true"/>

     

   </permissionSet>

Now I want that the "SolaScrittura" user CAN'T show the create and add link into your browse menu…

HOW CAN I DO THIS?
PLEASE HELP
THANKS

benallenallen
Champ in-the-making
Champ in-the-making
Is this code going to work? It would seem that by using that member variable "authority" in a singleton you may notice some odd behaviour since the "authority" may be set by another call to the bean. I wouldn't recommend this code unless somebody can confirm that the authority member variable you are using can be guaranteed to not be changed between the hasAuthority and the getAuthority method calls.

afaust
Legendary Innovator
Legendary Innovator
Hello,

this code is going to work as far as the authority member is concerned. Of course, using a member opens up the possibility that some malicious code would alter the authority returned by getAuthority. In a controlled environment, this is pretty unlikely. If considered globally, this would also be an issue with every other spring bean if you don't hard-code your settings in your Java classes.
Never the less, since the authority is usually a development-time constant and does not need to be configured dynamically, I would use a String constant in this particular case.

Regards
Axel