Using Liferay 6 Permissions within a JSF Portlet

Liferay 6.x has a fine grain permission system where you can define distinct “actions” per Portlet and grant them to one or more users or user roles. This give you a more explicit access control mechanism than the role based security of the Portlet API. For details check this article in the Liferay Wiki.

Unfortunately, using the permission system is quite tricky and requires to fiddle around in global Liferay configuration files for each and every Portlet which wants to make use of it. We decided in our project to not use it, but nevertheless here how it would work:

  1. First you’ve to create a resource-action mapping document for your portlet. In this XML description you define the action keys supported by a resource, in this case a Portlet:

    <?xml version="1.0"?>
    <resource-action-mapping>
        <portlet-resource>
            <portlet-name>myportlet_WAR_mywebapp</portlet-name>
            <permissions>
                <supports>               
                    <action-key>VIEW</action-key>
                    <action-key>TEST_PERM1</action-key>
                    <action-key>TEST_PERM2</action-key>
                </supports>
                <community-defaults/>
                <guest-defaults>
                    <action-key>VIEW</action-key>
                    <action-key>TEST_PERM1</action-key>
                </guest-defaults>
                <guest-unsupported>               
                    <action-key>TEST_PERM2</action-key>
                </guest-unsupported>
            </permissions>
        </portlet-resource>
    </resource-action-mapping>
    

    We define here two custom actions: TEST_PERM1 and TEST_PERM2. The portlet-name can be found in the Liferay control center.

  2. Copy the resource-action mapping to //webapps/ROOT/WEB-INF/classes/resource-actions/myportlet-resource-actions.xml. To make Liferay pick up your descriptor add the following line to /webapps/ROOT/WEB-INF/classes/portal-ext.properties:

     
    #Don't remove default.xml!!!
    resource.actions.configs=resource-actions/default.xml,resource-actions/myportlet-resource-actions.xml
     
    
  3. Now we could already use the actions, but it would be nice to have more expressive names for our actions. To define them add the following to the Language-ext property file (under /webapps/ROOT/WEB-INF/classes/content/Language-ext.properties:

    action.TEST_PERM1=Show Button X
    action.TEST_PERM2=Disable Page2
     
    

    After this you should be able see the actions in the configuration dialog when adding your portlet to a page:

  4. The last step is to write a neat helper method in order to check the permission within your JSF backing bean (or facelet):

      /**
       * Check the permission for the given actions
       *
       * @param actionKey String
       * @return boolean
       */
      public boolean checkPermission(String actionKey) {
        PortletRequest request = ((PortletRequest) (FacesContext.getCurrentInstance().getExternalContext().getRequest()));
       
        ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);   
        PermissionChecker permissionChecker = themeDisplay.getPermissionChecker();
       
        String name = PortalUtil.getPortletId(request);
        String primKey = themeDisplay.getLayout().getPlid() + LiferayPortletSession.LAYOUT_SEPARATOR + name;
        long groupId = themeDisplay.getScopeGroupId();
       
        return permissionChecker.hasPermission(groupId, name, primKey, actionKey);
      }
    

    This code requires the Liferay libraries in your classpath (liferay-service-6.x.x.jar).

Get JPA2 running on WebLogic 10.3

When you try to get JPA2 running on WebLogic 10.3 you might get this exception:

java.lang.NoSuchMethodError: javax/persistence/spi/PersistenceUnitInfo.getValidationMode()Ljavax/persistence/ValidationMode;
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:632)
    at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:72)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:268)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)

The reason is that WebLogic loads all JPA classes with the system classloader but ships JPA1. You have to force WebLogic to load the classes from within the lib folder of your web application.

Add to WEB-INF/weblogic.xml in your WAR project:

<wls:container-descriptor>
       <wls:prefer-web-inf-classes>true</wls:prefer-web-inf-classes>
<wls:container-descriptor>

And additionally add to META-INF/weblogic-application.xml in your EAR project:

<wls:prefer-application-packages>
	<wls:package-name>javax.persistence.*</wls:package-name>
	<wls:package-name>org.hibernate.*</wls:package-name>
	<wls:package-name>org.springframework.*</wls:package-name>
</wls:prefer-application-packages>

It seems both is necessary.