private List<Privilege> getPrivilegesToFilter(Node node) {

    if (node instanceof JCRNodeWrapper) {
      node = ((JCRNodeWrapper) node).getRealNode();
    }

    List<Privilege> privilegeToFilterOut = new ArrayList<>();

    // jcr:modifyAccessControl permission when data source is AccessControllable, only on
    // ExternalNodeImpl
    // ExtensionNodeImpl acls can be modify
    if (aclReadOnly && node instanceof ExternalNodeImpl) {
      privilegeToFilterOut.add(modifyAccessControlPrivilege);
    }

    // all write permissions in case of the data source not writable and not extendable
    if (!writable
        && node instanceof ExternalNodeImpl
        && (session.getOverridableProperties() == null
            || session.getOverridableProperties().size() == 0)) {
      privilegeToFilterOut.add(writePrivilege);
      privilegeToFilterOut.addAll(Lists.newArrayList(writePrivilege.getAggregatePrivileges()));
    }

    return privilegeToFilterOut;
  }
  public ExternalAccessControlManager(
      NamespaceRegistry namespaceRegistry,
      ExternalSessionImpl session,
      ExternalDataSource dataSource) {

    this.session = session;
    this.workspaceName = session.getWorkspace().getName();
    this.aclReadOnly =
        dataSource instanceof ExternalDataSource.AccessControllable
            || dataSource instanceof ExternalDataSource.SupportPrivileges;
    this.writable = dataSource instanceof ExternalDataSource.Writable;
    this.supportPrivileges = dataSource instanceof ExternalDataSource.SupportPrivileges;
    this.rootUserName = JahiaUserManagerService.getInstance().getRootUserName();
    this.dataSource = dataSource;

    this.pathPermissionCache =
        Collections.synchronizedMap(
            new LRUMap(SettingsBean.getInstance().getAccessManagerPathPermissionCacheMaxSize()));
    this.jahiaPrincipal =
        new JahiaPrincipal(
            session.getUserID(),
            session.getRealm(),
            session.getUserID().startsWith(JahiaLoginModule.SYSTEM),
            JahiaLoginModule.GUEST.equals(session.getUserID()));
    try {
      registry = new JahiaPrivilegeRegistry(namespaceRegistry);
      this.modifyAccessControlPrivilege =
          registry.getPrivilege("jcr:modifyAccessControl", workspaceName);
      this.writePrivilege = registry.getPrivilege("jcr:write", workspaceName);
    } catch (RepositoryException e) {
      throw new JahiaRuntimeException(e);
    }
  }
  private boolean hasPrivilegesLegacy(String absPath, Privilege[] privileges)
      throws PathNotFoundException, RepositoryException {

    // if no privilege set, return true
    if (privileges == null || privileges.length == 0) {
      return true;
    }

    // if root or system session return true
    String userID = session.getUserID();
    if (userID.startsWith(JahiaLoginModule.SYSTEM) || rootUserName.equals(userID)) {
      return true;
    }

    boolean allowed = true;
    Privilege[] granted = getPrivileges(absPath);
    for (Privilege toCheck : privileges) {
      if (toCheck != null && !ArrayUtils.contains(granted, toCheck)) {
        allowed = false;
        break;
      }
    }

    return allowed;
  }
 public boolean canManageNodeTypes(String path) throws RepositoryException {
   return hasPrivileges(
       path,
       new Privilege[] {
         registry.getPrivilege(
             JCR_NODE_TYPE_MANAGEMENT + "_" + session.getWorkspace().getName(), null)
       });
 }
 // JCR_REMOVE_NODE
 public void checkRemoveNode(String path) throws RepositoryException {
   if (!hasPrivileges(
       path,
       new Privilege[] {
         registry.getPrivilege(JCR_REMOVE_NODE + "_" + session.getWorkspace().getName(), null)
       })) {
     throw new AccessDeniedException(path);
   }
 }
 // JCR_ADD_CHILD_NODES
 public void checkAddChildNodes(String path) throws RepositoryException {
   if (!hasPrivileges(
       path,
       new Privilege[] {
         registry.getPrivilege(JCR_ADD_CHILD_NODES + "_" + session.getWorkspace().getName(), null)
       })) {
     throw new AccessDeniedException(path);
   }
 }
 public void checkRead(String path) throws RepositoryException {
   if (!hasPrivileges(
       path,
       new Privilege[] {
         registry.getPrivilege(JCR_READ + "_" + session.getWorkspace().getName(), null)
       })) {
     throw new PathNotFoundException(path);
   }
 }
 private String[] getPrivilegesNamesLegacy(String absPath) {
   ExternalContentStoreProvider.setCurrentSession(session);
   try {
     return ((ExternalDataSource.SupportPrivileges) dataSource)
         .getPrivilegesNames(session.getUserID(), absPath);
   } finally {
     ExternalContentStoreProvider.removeCurrentSession();
   }
 }
 // JCR_MODIFY_PROPERTIES
 public void checkModify(String path) throws RepositoryException {
   if (!hasPrivileges(
       path,
       new Privilege[] {
         registry.getPrivilege(
             JCR_MODIFY_PROPERTIES + "_" + session.getWorkspace().getName(), null)
       })) {
     throw new AccessDeniedException(path);
   }
 }
  @Override
  public boolean hasPrivileges(final String absPath, final Privilege[] privileges)
      throws PathNotFoundException, RepositoryException {

    if (supportPrivileges) {
      // if the node is created in the same session, return true
      for (Item item : session.getNewItems()) {
        if (item.getPath().equals(absPath)) {
          return true;
        }
      }

      // check privilege names
      return hasPrivilegesLegacy(absPath, privileges);
    } else {
      // check ACLs
      Set<String> privs = new HashSet<>();
      for (Privilege privilege : privileges) {
        privs.add(privilege.getName());
      }
      String mountPoint = session.getRepository().getStoreProvider().getMountPoint();
      Session securitySession =
          JCRSessionFactory.getInstance()
              .getCurrentSystemSession(session.getWorkspace().getName(), null, null);
      PathWrapper pathWrapper =
          new ExternalPathWrapperImpl(
              StringUtils.equals(absPath, "/") ? mountPoint : mountPoint + absPath,
              securitySession);
      return AccessManagerUtils.isGranted(
          pathWrapper,
          privs,
          securitySession,
          jahiaPrincipal,
          workspaceName,
          false,
          pathPermissionCache,
          compiledAcls,
          registry);
    }
  }
  @Override
  public Privilege[] getPrivileges(final String absPath)
      throws PathNotFoundException, RepositoryException {

    JCRNodeWrapper node =
        JCRSessionFactory.getInstance()
            .getCurrentSystemSession(workspaceName, null, null)
            .getNode(session.getRepository().getStoreProvider().getMountPoint() + absPath);
    Privilege[] privileges;
    if (supportPrivileges) {
      privileges = getPrivilegesLegacy(absPath);
    } else {
      privileges = AccessManagerUtils.getPrivileges(node, jahiaPrincipal, registry);
    }
    // filter some privileges in some specific cases, for avoid some operation from edit engines
    List<Privilege> privilegeToFilter = getPrivilegesToFilter(node.getRealNode());
    if (privilegeToFilter.size() > 0) {
      return filterPrivileges(privileges, privilegeToFilter);
    } else {
      return privileges;
    }
  }