Experimenting with Liferay Permissions

>> Monday, July 18, 2011

Liferay has a very rich permission and role based access system that goes beyond the portlet specification. However, as with a few other Liferay things, it is not always easy to find good documentation and examples. I recently had to work on roles and permissions for a client's project and after quite a bit of reading from different sources, of experimenting with the LR control panel, of perusing LR source code and of writing and testing code, I managed to get a fairly good understanding of how things work and how one can leverage the permission system.

In this post, I share some of my findings. Hopefully, it will save others some of the trial and error that I went through. I also wrote an example portlet based on the example available from the Liferay public SVN repository. The OpnWorks example plugin is available from our public Maven repository and is the basis for this article. I strongly recommend to download the plugin and it's sources if you want to really go through the details of this article. The plugin provides a working example as well as a way to experiment with roles and permissions since the portlet gives you feedback on which permissions you have depending on your role if and when logged in.

Configuring Permissions

First, you need to define a few things in the portlet.xml file. The following is taken from the aforementioned example:

<portlet>
<portlet-name>opnworks_permission_example</portlet-name>
<display-name>Opnworks Permission Example</display-name>
<portlet-class>com.liferay.util.bridges.mvc.MVCPortlet</portlet-class>
<init-param>
<name>view-jsp</name>
<value>/permission-view.jsp</value>
</init-param>
<init-param>
<name>help-jsp</name>
<value>/help.jsp</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>help</portlet-mode>
</supports>
<portlet-info>
<title>Opnworks Permission Example</title>
<short-title>Opnworks Permission Example</short-title>
<keywords>permission</keywords>
</portlet-info>
<security-role-ref>
<role-name>example-role</role-name>
</security-role-ref>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>

In the above declaration, the elements that pertain to permissions are the security-role-ref elements. These indicate which security roles the portlet refers to. The "example-role" is there as an example and is normally not needed. The other ones are standard Portlet role names.

The liferay-portlet.xml file contains the following information that tells the portal how standard portlet role names map to Liferay role names.
<role-mapper>
<role-name>example-role</role-name>
<role-link>Example Role</role-link>
</role-mapper>
<role-mapper>
<role-name>administrator</role-name>
<role-link>Administrator</role-link>
</role-mapper>
<role-mapper>
<role-name>guest</role-name>
<role-link>Guest</role-link>
</role-mapper>
<role-mapper>
<role-name>power-user</role-name>
<role-link>Power User</role-link>
</role-mapper>
<role-mapper>
<role-name>user</role-name>
<role-link>User</role-link>
</role-mapper>

The real interesting and useful stuff is in the resource-actions file. This is where we define default permissions for canonical roles and where we declare which action-keys our portlet exposes. It is important to note that the resource actions file must be referenced in the portlet.properties file. In the example, the portlet.properties file contains the following line:

 resource.actions.configs=resource-actions/example.xml  

The resource-actions/example.xml file must be in the classpath. It contains portlet-resource and model-resource elements that list actions associated with the resources. Our example portlet is declared as follows:

<portlet-resource>
<portlet-name>opnworks_permission_example</portlet-name>
<permissions>
<supports>
<action-key>ADD_SOMETHING</action-key>
<action-key>ADD_TO_PAGE</action-key>
<action-key>CONFIGURATION</action-key>
<action-key>VIEW</action-key>
</supports>
<community-defaults>
</community-defaults>
<guest-defaults>
<action-key>VIEW</action-key>
</guest-defaults>
<guest-unsupported>
<action-key>ADD_TO_PAGE</action-key>
</guest-unsupported>
</permissions>
</portlet-resource>

This simply says that the opnworks_permission_example supports four actions and that guests can view the portlet but cannot add the portlet to a page and that community members do not have any default permission. The ADD_TO_PAGE, CONFIGURATION and VIEW are action keys that correspond to normal or well known portlet actions. The ADD_SOMETHING key is specific to our portlet. Note that all child elements (even empty ones) are required.

Our example also contains model-resource elements such as the following:

<model-resource>
<model-name>com.opnworks.example.model.Something</model-name>
<portlet-ref>
<portlet-name>opnworks_permission_example</portlet-name>
</portlet-ref>
<permissions>
<supports>
<action-key>DELETE</action-key>
<action-key>PERMISSIONS</action-key>
<action-key>UPDATE</action-key>
<action-key>VIEW</action-key>
</supports>
<community-defaults>
<action-key>VIEW</action-key>
</community-defaults>
<guest-defaults>
<action-key>VIEW</action-key>
</guest-defaults>
<guest-unsupported>
<action-key>DELETE</action-key>
<action-key>PERMISSIONS</action-key>
<action-key>UPDATE</action-key>
<action-key>VIEW</action-key>
</guest-unsupported>
</permissions>
</model-resource>

This element declares what users can do with a specific object type (in this case instances of com.opnworks.example.model.Something). Sometimes, a portlet requires access to more than one model-resource and specifically to portal entities such as Users, Organizations, Image Galleries etc. To support this, add model-resource elements to the resource-action file. For example, the following fragment defines what the portlet can do with organizations:

<model-resource>
<model-name>com.liferay.portal.model.Organization</model-name>
<portlet-ref>
<portlet-name>opnworks_permission_example</portlet-name>
</portlet-ref>
<permissions>
<supports>
<action-key>DELETE</action-key>
<action-key>PERMISSIONS</action-key>
<action-key>UPDATE</action-key>
<action-key>VIEW</action-key>
</supports>
<community-defaults>
<action-key>VIEW</action-key>
</community-defaults>
<guest-defaults>
<action-key>VIEW</action-key>
</guest-defaults>
...etc...

With this configuration in place we can build and deploy our Liferay plugin. Simply place the portlet (you will find it in the "OpnWorks" section of the catalog) on a page and see what it says depending on whether you are a simple guest (anonymous) or a signed in user with privileges. If you have administrative privileges, you can create a role, set the permissions for this role (namely the permissions associated with the opnworks_permission_example portlet and model), assign this role to a user and sign in as this user to see what the portlet returns in terms of permissions. The following is the content of the help page displayed by the example portlet.

Help for Example Permissions Portlet

To experiment with this portlet, proceed as follows:
  1. Open a browser on your Liferay instance as Liferay administrator
  2. Create a new role named "Example Role"
  3. Create a new user named "Example User" and set the user's password
  4. Assign the "Example Role" to the newly created user
  5. Open a different browser on your Liferay instance so as to have a different session, log in as "Example User" and navigate to the page containing this portlet
  6. As the administrator, add and remove permissions related to "Opnworks Permission Example" to the "Example Role" and refresh the user's portlet to see the effect of the change in role.
  7. Experiment with the Organization permissions by associating the user with organizations and by changing his organizational role.

Checking Permissions in the Code

Obviously, you can check permissions in your JSP, controller or service code. Check out the permission-view.jsp file in the example plugin for an example. The portal also contains many examples and the Liferay practice is to create a utility or helper class such as com.opnworks.portal.example.permission.SomethingPermissionUtil to provide permission checking services for a resource type. If you need such a utility class then you will need to add a bean definition such as the following to the plugin's META-INF/ext-spring.xml file:

      <bean id="com.opnworks.portal.example.permission.SomethingPermissionUtil" class="com.opnworks.portal.example.permission.SomethingPermissionUtil">
<property name="somethingPermission">
<bean class="com.opnworks.portal.example.permission.impl.SomethingPermissionImpl" />
</property>
</bean>

Well, that was a mouthful wasn't it?

Have fun with permissions...

1 commentaires:

Anonymous,  15 February, 2013 07:13  

Well done! Very useful post!

Post a Comment

  © Blogger template Webnolia by Ourblogtemplates.com 2009

Back to TOP