Add custom roles in Alfresco
For some cases, out of the box roles in Alfresco are not enough. However, it’s not so hard to extend them. We will see how to do it using a simple example.
Config:
- Alfresco Community 5.0.c
- Fedora 20
- Maven 3.2.3
- All-in-one Alfresco Maven SDK 2.0.0
- Intellij Idea 14
1. Use case
I have a folder which contains documents and I would like users to be able to delete and edit the documents but not create new ones, in summary I would like these permissions:
- Read
- Edit
- Delete
- But not create
Alfresco does provide the role Editor
which combines these permissions except that it doesn’t
allow us to delete documents (children). So we will try to add this advanced editor
role but before I would like to
introduce some vocabulary:
A base permission is a single unit and represents an action such as Read, Delete, Edit and so on.
A role is a set of base permissions (contains one or more base permissions). Examples are Collaborator, Contributor, Editor, …
Setting a permission is done by associating a role with an authority (user or group of users) on a specific node. It’s a triplet
role / authority / node
. The idea is to determine which actions can do a certain user on a specific node.
2. Permission definitions
To extend permissions in Alfresco you have to write permission definitions
. Actually it’s only one xml file, the
permissionDefinitions.xml
. There is a dtd associated with it, permissionSchema.dtd
, which is well documented and
gives really useful information to start with. This chapter will give details on how to configure
permissions but it really worth it having a look to these files, you can find them in the sources of Alfresco.
a. permissionSet
Define a new set of permissions (base permissions) and permission groups (roles) for a type or aspect. Sub-element of the root element. It’s usually where to start.
Sub-elements: permissionGroup
, permission
type | prefix:name | A permission set is associated with a type or aspect and applies only to that type and sub-types, or aspect and sub-aspects | mandatory |
expose | all,selected | governs if these permissions are exposed on the permission model. If all, exposes all permission groups. If selected, only the permission groups that say they are explicitly exposed are exposed | default all |
b. permissionGroup (role)
Build a new “role” combining existing permissionGroups. If the permissionGroup doesn’t include other permissionGroup, it means it has been granted to a single permission (see permission below).
Sub-element: includePermissionGroup
.
name | string | simple name of the permission. Full name includes the type uri from the outer permissionSet | mandatory |
type | prefix:name | If the permission group extends another then this attribute can be used to specify the type it extends. Normally it would assume this follows the data dictionary type hierarchy | implied |
extends | boolean | does this permission group extend one that already exists? | default false |
expose | boolean | if the the containing permission set does not expose all permission groups specify if this particular permission group is exposed or not | default false |
allowFullControl | boolean | if true, this permission group effectively grants all permissions | default false |
requiresType | default | this is useful for permission groups tied to aspects. If false, the permission group applies to all types as they could have the aspect. If true, the permission group only makes sense if the aspect has been applied | default true |
includePermissionGroup
type prefix:name the type on which to find the permission group to include permissionGroup string the name of the permission group to include as defined on the type
c. permission
Define a base permission. The permissionGroup(s) to which this permission applies are defined in the grantedToGroup element. Other permissions which are required or implied by this permission can be defined using requiredPermission elements.
Sub-element(s): grantedToGroup
, requiredPermission
.
name | string | same as permissionGroup | mandatory |
expose | boolean | same as permissionGroup | default false |
requiresType | boolean | same as permissionGroup | default true |
grantedToGroup
type prefix:name the type on which the permissionGroup is defined implied permissionGroup string the name of the permission group mandatory
requiredPermission
name string the name of the required permission or permission group mandatory type string the type of the required permission or permission group implied on node, parent, children if required permission must be present mandatory implies boolean if false the permission will be checked. If true, the permission is effectively granted along with this one default false More about implies: This will normally be false. For example, to require read permission on the parent to be able to read the node. This requirement would be recursive, as read on any node would require read on the parent of that node. If true this is the case where this permission allows the user to take another action as it is required to carry out the first. Normally you would protect the method call to require both permissions. This does really grant the other permission. If a permission A is defined that requires another permission B, with implies true, then granting someone permission A will also grant permission B. If implies is false, then granting A will not allow A until permission B is also available.
d. globalPermissions
A global permission assignment.
authority | string | the string representation of the authority | implied |
permission | string | the permission that is granted (name or full name) | mandatory |
We are now ready to customize the permissions.
3. Add custom role
a. custom permission definitions
Let’s start adding our new role Advanced Editor. In a new file customPermissionDefintion.xml
located in
{repo...}/amp/config/alfresco/module/{your-module}/model
(replace the curly brackets with your module name). Start to
add these
lines. I added as well my custom namespace
containing my content model.
Then we will add a new permissionSet
because I want the new role (permissionGroup) to be specific of my content
model.
Add the new permissionGroup in the permissionSet:
If you want to keep the permissions and permissions groups from cm:folder you need to copy/past them. I did find yet a better solution.
b. boostrap the custom permission definition
Add in your spring context file this bean definition:
My context file is located in {repo...}/amp/config/alfresco/module/{your-module}/context/{custom}-context.xml
and is
imported
by the module-context.xml.
c. Label
If you want to set this new role from the UI share you might want to give it a proper label. You must have a file
{share..}/amp/config/alfresco/module/{your-module}/messages/{custom}.properties
Add this line:
After this to use the role you can either use share “Manage Permissions” or pragmatically.
4. Further
a. site permission definitions
There is another example of permission definitions, sitePermissionDefinitions.xml
, which contains the configurations
for the
sites permissions.
b. Permission service Java API
Using the permission service from Alfresco foundation API it’s really easy to set a role to a node for an authority.
The boolean parameter is used to allow the permission.