cancel
Showing results for 
Search instead for 
Did you mean: 

Dynamic Access Rights on nodes in Alfresco?

rtitov
Champ in-the-making
Champ in-the-making
We would like to store personnel files of our employees in Alfresco. Each file would contain many documents, such as contracts, passport scans, appraisal reports etc.. Each category of documents would have its own access rights based on metadata. Most of those access rights will be coming from our own role management system. They can be very complex and not always can be defined through LDAP or ACLs. For example, a Departmental Administrative Officer would have access to a sub-set of documents for employees of her department, a supervisor would have access to some documents of his supervisees and so on. If the person changes the group, the access rights should immediately change correspondingly. Sometimes access rights for a document will be coming from an external system.
The system would contain millions of documents, so synchronising ACLs for each document with our role management system (e.g. by a regular job) does not sound feasible.
To solve this dynamic access rights problem, we are planning to replace the default PermissionService bean with our own implementation, which would extend PermissionServiceImpl class and override the hasPermission(NodeRef, PermissionReference) method with our own implementation. The “Inherit permissions” flag will be switched off on the top of the hierarchy of documents so the permissions will not be inherited and will be controlled by our code.



public class MyPermissionServiceImpl extends PermissionServiceImpl
{
  public static final String PERSONNEL_FOLDER = "personnel-folder";

  private static SoftCache cacheAcls = new SoftCache();

  private static Log log = LogFactory.getLog(MyPermissionServiceImpl.class);

  @Override
  public AccessStatus hasPermission(NodeRef passedNodeRef, PermissionReference permIn)
  {
    String fileName = (String) nodeService.getProperty(passedNodeRef, ContentModel.PROP_NAME);
    String currentUser = AuthenticationUtil.getRunAsUser();
    AccessStatus status = super.hasPermission(passedNodeRef, permIn);

    if ((status != AccessStatus.ALLOWED) && (nodeService.getPath(passedNodeRef).toString().indexOf(PERSONNEL_FOLDER) > -1))
      status = hasPermission(currentUser, fileName, passedNodeRef, permIn);

    log.info("Permission: " + currentUser + ": " + fileName + " - " + permIn + ": " + status);
    return status;
  }

  private AccessStatus hasPermission(String currentUser, String fileName, NodeRef node, PermissionReference permIn)
  {
    AccessStatus status = (AccessStatus)cacheAcls.get(node.getId() + ":" + currentUser + ":" + permIn.getName());

    if (status == null)
    {
      if (permIn.getName().startsWith(READ))
        status = hasReadPermission(currentUser, fileName, node, permIn);
      else if (permIn.getName().startsWith(WRITE) || permIn.getName().startsWith(DELETE) || permIn.getName().startsWith(CREATE_CHILDREN) || permIn.getName().startsWith(CREATE_ASSOCIATIONS))
        status = hasWritePermission(currentUser, fileName, node, permIn);
      else if (permIn.getName().equals(CANCEL_CHECK_OUT))
        status = hasCancelCheckOutPermission(currentUser, fileName, node, permIn);
      else if (permIn.getName().equals(CHANGE_PERMISSIONS))
        status = hasChangePermPermission(currentUser, fileName, node, permIn);
      else
      {
        status = AccessStatus.DENIED;
        log.fatal("UNKNOWN PERMISSION: " + currentUser + ": " + fileName + " - " + permIn + ": " + status);
      }
      cacheAcls.put(node.getId() + ":" + currentUser + ":" + permIn.getName(), status);
    }
    return status;
  }
 
  private AccessStatus hasReadPermission(String currentUser, String fileName, NodeRef node, PermissionReference permIn)
  {
    // Do our own access control
  }
 
  // …
 
}




We would like to know whether there are better ways to solve the problem of dynamic access control. If our approach is correct then we would like to know whether we need to override any other methods or beans.
2 REPLIES 2

scouil
Star Contributor
Star Contributor
Hi,

I would have personally used an interceptor instead of extending the service:
http://docs.alfresco.com/4.1/index.jsp?topic=%2Fcom.alfresco.enterprise.doc%2Fconcepts%2Fsecur-confi...

Other than that, the approach sounds sensible.

rtitov
Champ in-the-making
Champ in-the-making
Hi,

I have actually first tried with an interceptor, there is quite a nice post how to implement one:

http://forums.alfresco.com/forum/developer-discussions/alfresco-explorer-development/customizing-alf...

However, it seemed somehow that my interceptor didn't intercept all calls to PermissionService. It probably is my bug, but it was quite hard to debug so I have reverted to overriding the permission service.

I guess from the technical point of view it doesn't really matter: both approaches imply changing the Spring configuration, so they could not be done as an AMP module.

Thanks for your reply!



Welcome to the new Hyland Connect. Get started or submit feedback.