JBoss.orgCommunity Documentation

Chapter 37. Access Control Extension

37.1. Prerequisites
37.2. Overview
37.3. Access Context Action
37.4. The Invocation Context
37.5. Custom Extended Access Manager
37.6. Example of a custom Access Manager

This is an extension of eXo JCR Access Control features. Please read Access Control and JCR Extensions topics first.

An extended Access Control system consists of:

SetAccessControlContextAction implements Action and may be called by SessionActionInterceptor as a reaction of some events - usually before writing methods and after reading (getNode(), getProperty() etc). This SetAccessControlContextAction calls the AccessManager.setContext(InvocationContext context) method which sets the ThreadLocal invocation context for the current call.

Action's Configuration may look like as the following:

<value>
  <object type="org.exoplatform.services.jcr.impl.ext.action.ActionConfiguration">
    <field  name="eventTypes"><string>addNode,read</string></field>
    <field  name="workspace"><string>production</string></field >
    <field  name="actionClassName"><string>org.exoplatform.services.jcr.ext.access.SetAccessControlContextAction</string></field>       
  </object>
</value>

The InvocationContext contains the current Item, the current ExoContainer and the current EventType is like below:

public interface InvocationContext extends ContextBase {

  Item getCurrentItem();

  int getEventType();
  
  ExoContainer getContainer();
}

By default, all Workspaces share an AccessManager instance, created by RepositoryService at the startup (DefaultAccessManagerImpl) which supports default access control policy as described in the Access Control chapter. Custom Access Control policy can be applied to certain Workspace configuring access-manager element inside workspace as follows:

<workspace name="ws">        
   ...
   <!-- after query-handler element -->
   <access-manager class="org.exoplatform.services.jcr.CustomAccessManagerImpl">
      <properties>
         <property name="someProperty" value="value"/>
         ...
      </properties>
  </access-manager>
  ...
</workspace>

When implementing AccessManager, hasPermission() method has to be overriden so it uses the current invocation context at its discretion. For instance, it may get the current node's metadata and make a decision if the current User has appropriate permissions. Use Invocation Context's runtime properties to make a decision about current Session's privileges (see the Example below)

Simplified Sequence diagram for the Session.getNode() method (as an Example):

The sample CustomAccessManagerImpl below extends the default access manager and uses some DecisionMakingService in the overloaded hasPermission method to find out if a current user has permission to use current item, event type, user and some parameter of AccessManager. To make this Access manager work, it is necessary to configure it in jcr configuration as mentioned in Custom Extended Access Manager and SetAccessControlContextAction should be configured in the way mentioned in Access Context Action.

public class CustomAccessManagerImpl extends AccessManager {

  private String property;
  private DecisionMakingService theService;

  public CustomAccessManagerImpl (RepositoryEntry config, WorkspaceEntry wsConfig,
      DecisionMakingService someService) throws RepositoryException, RepositoryConfigurationException {
    super(config, wsConfig);
    this.property = wsConfig.getAccessManager().getParameterValue("someParam");
    this.theService = someService;
  }

  @Override
  public boolean hasPermission(AccessControlList acl, String[] permission, Identity user) {
    // call the default permission check
    if (super.hasPermission(acl, permission, user)) {
      
      Item curItem = context().getCurrentItem();
      int eventType = context().getEventType();
      ExoContainer container = context().getContainer();

      // call some service's method
      return theService.makeDecision(curItem, eventType, user, property);
    } else {
      return false;
    }
  }
}