Roles in Alfresco 1.4
The article explains the basics involved in understanding Alfresco authorization and the means to extend its functionality, for example, to adapt it for any special requirements through configuration files. The concepts explained in the article will be useful for anyone who has started working with Alfresco code. In addition to this, a little step-by-step example towards the end helps you extend the initial Alfresco roles. Read out more in the article written by Alfonso Martin.
Once you have started with Alfresco, you will realize that you need to create or expand the default roles included with Alfresco. This task (at this moment) must be done manually through configuration files. Before diving into the Alfresco.war file to search for the property configuration files, you will need to understand a few concepts. This article will introduce you to the basics in Alfresco's role policy.
The basic concept in action authorization in Alfresco is that of permission. Permissions dictate when an action can be executed on an object by a user. Key concepts in defining authorization policy in Alfresco are:
Such elements are declared in the permissionDefinitions.xml file, located in WEB‑INF/classes/alfresco/model inside the Alfresco.war file.
Collections of permission groups, permissions, and dynamic authorities with common attributes:
- type: (Mandatory) PermissionSet is defined over a type or aspect. If it is defined over a type, then it is applicable for all objects of that type; if it is defined over an aspect, then it is applicable for all objects that have the same aspect.
- expose: (Optional) This attribute restricts the domain of Type. If the value is all, it is allowed to apply a PermissionSet to objects, which have a parent that satisfies the Type attribute. Otherwise, if the value is selected, the set is only applied to objects that satisfy Type attribute. All is assumed, if the attribute is undefined.
PermissionGroup defines its behaviour through several attributes:
- name: (Mandatory) Group identifier.
- type: (Optional) Same as in permissionSet.
- extends: Determines if the permissionGroup extends the definition of a previous group with the same name. If undefined, default value is false.
- expose: Restricts the domain of type, and if true, the permissionGroup will be applied to objects (and derivatives) that satisfy the attribute type. If it is undefined, then false is assumed.
- allowFullControl: If true, group has all privileges, else the privileges are to be assigned.
- requiresType: If false, permissionGroup can be applied to any object, otherwise only to objects that satisfies type. If undefined, the default value is true.
PermissionGroup can be composed by several permissionGroups, whose sub groups will be identified by name and type. If type is omitted, the parent’s type will be used.
A permission is the minimal unit to represent an authorization of an action on an object. It is defined by:
- name: Permission identifier
- expose: If true, the permission can be applied to derivative objects, otherwise only to objects defined in a permissionGroup context. Default value is false
- requiresType: If true, a permission can only be applied to objects defined by its group context. If it is omitted, default is false
A permission can require the authorization of other permissions, such permissions are identified by:
- on: Specifies where the permission is required—node, parent, or children.
- implies: If true, the required permission grants itself the parent’s permission. There can be only one required permission with attribute implies equal to true. If omitted, the default value is false.
Inside the permission are the declarations of the permissionGroups that contain said permission. These declarations require existent permissionGroups, and can optionally specify the node types where the permission will be applied will be applied to all nodes.
These kinds of permissions are defined outside a permissionSet, and are applied to all nodes in the hierarchy (irrespective of its type and related aspects). This kind of permission prevails over other permission types.
Roles in Alfresco are a special type of permission group, concretely permissionGroups, which are defined in permissionSets applied to nodes of type content. To use these roles in the Alfresco GUI, it is necessary to create appropriate tags in the internationalization files, more specifically, the webclient.properties (this file can vary in function of language/country) and is typically located in WEB‑INF/classes/alfresco/messages
Alfresco defines a few basic roles in the permissionDefinitions.xml. These roles are defined in an incremental manner. First, it creates a Consumer role and then defines the rest of the roles, adding functionality to the Consumer role. Predefined roles are:
- Consumer: Allows read properties, content, and children of a node.
- Editor: Adds to consumer privileges the ability to write nodes (properties, content, and children) and execute CheckOuts in nodes with aspect lockable.
- Contributor: Adds to consumer privileges the possibility of adding children and execute CheckOuts in nodes with aspect lockable.
- Collaborator: This role has the same capabilities as Contributor and Editor.
- Coordinator: This role has all privileges including the possibility of taking ownership of nodes, and changing its owner.
- Administrator: Same as Coordinator, it is defined for backward compatibility.
Default Permission Policy
After a first check out of the permissionDefinitions.xml file in Alfresco 1.4, you will find five major PermissionSets. These sets establish node permissions across the Content Model hierarchy: It starts with base type, which defines basic low-level permissions. The next set defines permissions for the cmobject node types, which at this level are defined in the permissionGroups and later will be extended by roles. Content nodes have a set, which defines the available roles. In addition to these sets, the permissionDefinitions.xml file includes two other sets. One of these sets is for nodes that have the aspect ownable, and the other is for nodes that have the aspect lockable. The permissions defined in such sets allow the execution of typical specialised actions with these kinds of nodes—Check In, Check Out, Take Ownerships, Change owner, Lock, and Unlock.
After PermissionSets, the configuration file declares GlobalPermissions. These permissions will be applied to all nodes, and they have priority over other permission types. At the moment, these permissions are:
FullControl: Allows users who have any of these roles—ROLE_ADMINISTRATOR or ROLE_OWNER.
Unlock, CheckIn and CancelCheckOut: All these allow users who have their role defined as ROLE_LOCK_OWNER
New role definition example:
This example is based on ideas explained in one of the Alfresco forums. The case study is the typical context, where three specialized folders are needed—Drafts, Pending approval and Published.
Drafts: Stores actual working documents.
Pending approval: This folder contains documents whose author(s) has/have requested approbation.
Published: Stores final versions of documents.
There exist two differentiated user groups—Creators and Approvers.
Creators have full access to folder Drafts and read access in Published; Approvers have full access to Pending approval and Published. Creators need to move documents from Drafts to Pending approval, but cannot see the folder files.
To model this situation, we create two user groups called Creators and Approvers. Then create three spaces Drafts, Pending approval and Published. Each space will have the following configuration:
Drafts: Uncheck Inherit Parent Space Permissions checkbox. Invite group Creators with role Collaborator.
Pending approval: Uncheck Inherit Parent Space Permissions checkbox. Invite group Approvers with role Coordinator.
Published: Uncheck Inherit Parent Space Permissions checkbox. Invite group Approvers with role Coordinator.
But as you can see, with this configuration there exists a situation with the prerequisite: Creators need to move documents from Drafts to Pending approval, but cannot see the folder or files. Alfresco does not include any role that satisfies this. So, it lets you create it. Open the permissionDefinitions.xml file. First define a low level permissionGroup called CreateNodes, this group should be defined inside permissionSet with type base; in other words, available for all kinds of nodes. Also inside this set we need to declare the permissions that compose this permission group: In our case only the permission _CreateNodes.
<permissionSet type="sys:base" expose="all">
<permissionGroup name="CreateNodes" expose="true"
<permission name="_CreateChildren" expose="false">
<grantedToGroup permissionGroup="CreateNodes"/> <!-- New -->
Then we need to define a role called Writer (remember, in set with type content), this role extends the behavior of a permission role declared in the set with type cmobject. The permissionGroup, Writer will include previously defined CreatedNode.
<permissionSet type="cm:cmobject" expose="selected">
<permissionGroup name="Writer" allowFullControl="false"
<permissionSet type="cm:content" expose="selected">
<permissionGroup name="Writer" extends="true" expose="true"/>
With these additions, we have created a new role called Writer that will solve our little situation. To be allowed to use it in the Alfresco GUI we need only to add a properly internationalization tag in webclient.properties:
Writer= OurWriter role
And now we can invite the Creators group to the Pending approval space with the Writer role. The creators will be able to move documents from Drafts to Pending approval, but they will not be able to read the folder. The last operation is to add a rule called Request approval in the space Drafts that moves documents from Drafts to the space Pending approval.
This is a trivial example for homework where you can try to add rules in spaces with simple workflows to formalize the process of approbations and rejections.