Uploaded image for project: '[Read Only] - Hippo Repository'
  1. [Read Only] - Hippo Repository
  2. REPO-2275

JCR users with limited read access on variants below a handle might not be able to fetch the variant to should be able to read

    XMLWordPrintable

Details

    • Bug
    • Status: Closed
    • Blocker
    • Resolution: Fixed
    • None
    • 14.0.0
    • None
    • None

    Description

      What happens is the following :

      1) The HST liveuser is used to handle a request
      2) The request is for a faceted navigation node
      3) The documents in the hippo:resultset are fetched via the liveuser

      When the above happens, to populate a document in the faceted navigation resultset,
      the read access on the canonical version (the non virtual) node has to be checked. The reason for this
      is simple: The faceted navigation query returns any document variant that matches the
      query. After this, the variants are filtered by read access!

      This is done as follows:

      1) From the virtual nodeId of the variant the canonical nodeId is fetched and during this fetch,
      the read access is checked, see in HippoLocalItemStateManager :

      public ItemState getCanonicalItemState(ItemId id) throws NoSuchItemStateException, ItemStateException {
          try {
              if (!accessManager.isGranted(id, AccessManager.READ)) {
                  return null;
              }
          } catch (RepositoryException ex) {
              return null;
          }
          return super.getItemState(id);
      }
      

      2) The 'id' above is THUS from the document variant! This is important to realize. The call
      accessManager.isGranted(id, AccessManager.READ) will hit

      HippoAccessManager#canRead(org.apache.jackrabbit.core.id.NodeId)
      

      To avoid recursion, this method adds the variant 'id' to the 'inprocessNodeReadAccess'
      cache: As long as a node is in that cache, it returns 'true' on subsequent
      invocation of canRead(id) with id the id of the variant.

      3) Then canRead continues for the variant id, but before the actual security
      domains for that node are checked, first parent id access is checked. In case of
      a variant id, this parent will be a handle

      4) For normal node access, the parent handle is always accessed earlier
      already hence already in local item state manager cache including the
      document variant reshuffling that is done in
      HippoLocalItemStateManager#reorderHandleChildNodeEntries : This reshuffling makes
      sure that the readable variants are the first child node entries, so
      for example if the readable variant for the liveuser is mydoc[3], then
      after reshuffling it become mydoc[1] (the first child)

      5) For access via the faceted navigation resultset however, the node id's
      and corresponding NodeState's for variants can be loaded while the handle
      (parent) NodeState has not yet been loaded (and not cached in the
      HippoLocalItemStateManager with reordered child node entries (variants)

      6) In (3) I mentioned that thus first parent id access is checked. This is done in
      canRead method in:

      if (!rootNodeId.equals(id) && !(id instanceof HippoNodeId)) {
          if (!canRead(nodeState.getParentId())) {
              removeAccessFromCache(id);
              return false;
          }
      }
      

      7) canRead(nodeState.getParentId()) triggers for the parent id (handle id) to fetch the
      NodeState via:

      nodeState = (NodeState) getItemState(id);
      

      8) If the NodeState for the handle has not been accessed before by the
      HippoLocalItemStateManager, as can be the case as explained for faceted navigation
      nodes, then the HippoLocalItemStateManager will get the NodeState (after which
      it gets added to the cache of Jackrabbit LocalItemStateManager).

      9) When the HippoLocalItemStateManager loads a NodeState for a hippo handle, it
      reshuffles the document variants below it based on read access: Namely, the
      readable variants MUST be the first child node entries: This is to get the
      path correct. Assume the liveuser can only read mydoc[3] (as seen by an
      admin user). However, the liveuser want to access /mydoc/mydoc because
      it can only read mydoc[3] and not mydoc[2] and mydoc[1].

      10) So, the document variants are reshuffled by checking the read access
      of the variants one by one. In the HippoLocalItemStateManager for every
      variant we invoke

      accessManager.isGranted(variant.getId(), AccessManager.READ)
      

      and if there is not read access, the variant is moved to the last child entry

      11) And now we can see the problem: We came here via (2) where we were checking the
      read access for one of the variants. That resulted in the parent NodeState lookup,
      triggering the reshuffling of all variants based on read access. BUT, the variant id
      being check in (2) has been added and still is present in the 'inprocessNodeReadAccess'
      cache, resulting in a possibly INCORRECT temporary read access for the variant id,
      making it possible incorrectly not reshuffled to the last position

      12) As a result of (11), it might be that after the variant reshuffling, we for example
      end up for a liveuser with a handle NodeState as follows:

      + mydoc (handle)
         + mydoc (draft)
         + mydoc (live)
         + mydoc (preview)
      

      13) Now, the liveuser wants to access /mydoc/mydoc, but the returned node id for that
      path is the node id for the 'draft', for which the AccessManager now does not give
      read access any more since it has been dropped from the 'inprocessNodeReadAccess'
      cache for long already. As a result, the liveuser cannot access the live variant

      Attachments

        Activity

          People

            Unassigned Unassigned
            aschrijvers Ard Schrijvers
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: