XQuery - Query Element Hierarchies
Use this code to insert a new document (along with permissions) into the Documents database:
(: insert document with permissions => run against Documents database :) xquery version "1.0-ml"; xdmp:document-insert( "hierarchy.xml", <root> <title>Title of the Document</title> <summary>Summary of document contents</summary> <executive-summary>Executive summary of the document contents <secret>Only role having "secret" can read this <top-secret>Only role having "top-secret" can read this </top-secret> </secret> </executive-summary> <content>Contents of document <top-secret>Only role with "top-secret" can read this <secret>Only role with "secret" can read this</secret> </top-secret> Unclassified content </content> </root>, (xdmp:permission("els-role-1", "read"), xdmp:permission("els-role-2", "read"), xdmp:permission("els-role-1", "update"), xdmp:permission("els-role-2", "update")))
Add protected paths with permissions for roles to the Security database:
(: add protected paths -> run against the Security database :) xquery version "1.0-ml"; import module namespace sec="http://marklogic.com/xdmp/security" at "/MarkLogic/security.xqy"; sec:protect-path("secret", (), (xdmp:permission("els-role-2", "read"))), sec:protect-path("top-secret", (), (xdmp:permission("els-role-1", "read"))) => Returns two numbers representing the protected paths
Note
Adding, unprotecting, or changing permissions on protected paths will trigger reindexing.
Test this example in the context of the different els-users. This first query uses the context of els-user-1
:
(: run this against the Documents database :)
xdmp:eval('fn:doc("hierarchy.xml")',(),
<options xmlns="xdmp:eval">
<user-id>{xdmp:user("els-user-1")}</user-id>
</options>
)
=>
<root>
<title>Title of the Document
</title>
<summary>Summary of document contents</summary>
<executive-summary>Executive summary of contents
</executive-summary>
<content>Contents of document
<top-secret>Only role with "top-secret" can read this</top-secret>
Unclassified content</content>
</root>
The “top-secret” role (els-user-1
) cannot see the elements marked with “secret”, only those that have no protected paths or marked with the protected path for “top-secret”. Next, run the query in the context of els-user-2
:
(: run this against the Documents database :)
xdmp:eval('fn:doc("hierarchy.xml")',(),
<options xmlns="xdmp:eval">
<user-id>{xdmp:user("els-user-2")}</user-id>
</options>
)
=>
<root>
<title>Title of the Document</title>
<summary>Summary of document contents</summary>
<executive-summary>Executive summary of contents
<secret>Only role having "secret" can read this</secret></executive-summary>
<content>Contents of document
Unclassified content</content>
</root>
Notice that even though in the original document there is an element “secret” within the “top-secret” contents of the document, it is a child of the “top-secret” element and therefore hidden to users without the “top-secret” role.
The els-user-1
(“top-secret”) cannot see the “secret” content unless you add the els-role-2
to els-user-1
. When you add the role, els-user-1
will be able to see both the “secret” and “top-secret” elements.
If you run the query as els-user-3
, the query returns an empty sequence. The els-user-3
from the previous query does not have permission to even see the document.