JavaScript - Matching by Paths or Attributes
This next example shows how protected paths can be used with fn.contains()
and fn.matches()
. The example uses the same roles from the previous example, adding a new role (els-role-3
).
First unprotect the protected paths from the previous example:
// unprotect protected paths -> run against the Security database declareUpdate(); var security = require('/MarkLogic/security.xqy'); security.unprotectPath('secret', []), security.unprotectPath('top-secret', [])
Note
Adding, unprotecting, or changing permissions on protected paths will trigger reindexing.
Create a new role els-role-3
and add els-user-3
to the role. See Create Roles and Create Users and Assign Roles for details.
Add a new document to the Documents database:
// insert document and permissions -> run this against the Documents database declareUpdate(); var perms = [xdmp.permission("els-role-1", "read"), xdmp.permission("els-role-2", "read"), xdmp.permission("els-role-3", "read"), xdmp.permission("els-role-1", "update"), xdmp.permission("els-role-2", "update"), xdmp.permission("els-role-3", "update") ]; xdmp.documentInsert( "attributes.xml", xdmp.unquote(` <root> <title>Document Title</title> <summary>Summary of document contents</summary> <executive-summary>Executive summary of contents <info attr="EU">Only role with "EU" attribute can read this summary </info> <info attr="UK">Only role with "UK" attribute can read this summary </info> <info attr="US">Only role with "US" attribute can read this summary </info> </executive-summary> <content>Contents of document Unclassified content <notes> <info attr="EU">Only role with "EU" attribute can read this content</info> <info attr="UK">Only role with "UK" attribute can read this content</info> <info attr="US">Only role with "US" attribute can read this content</info> </notes> </content> </root> `), {permissions: perms})
Add the new protected paths with permissions for roles to the Security database:
// add new protected paths -> run against the Security database declareUpdate(); var security = require('/MarkLogic/security.xqy'); security.protectPath("//info[fn:matches(@attr, 'US')]", [],[xdmp.permission("els-role-1","read", "element")]), security.protectPath("//info[fn:matches(@attr, 'UK')]", [],[xdmp.permission("els-role-2", "read", "element"), xdmp.permission("els-role-3", "read", "element")]), security.protectPath("//info[fn:matches(@attr, 'EU')]", [], [xdmp.permission("els-role-3", "read", "element")]) => Returns one number representing the protected paths
Note
Adding or changing permissions on protected paths will trigger reindexing.
Run the same queries as before, first in the context of els-user-1
, who has a role that can see the “US” attribute:
// run this query against the Documents database
xdmp.eval("fn.doc('attributes.xml')", null,
{
"userId" : xdmp.user("els-user-1")
});
=>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<title>Document Title</title>
<summary>Summary of document contents</summary>
<executive-summary>Executive summary of contents
<info attr="US">Only role with "US" attribute can read this summary</info>
</executive-summary>
<content>Contents of document
Unclassified content
<notes>
<info attr="US">Only role with "US" attribute can read this content</info>
</notes></content>
</root>
Next modify the query to run in the context of els-user-2
, who has a role that can see the “UK” attribute:
// run this query against the Documents database
xdmp.eval("fn.doc('attributes.xml')", null,
{
"userId" : xdmp.user("els-user-2")
});
=>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<title>Document Title</title>
<summary>Summary of document contents</summary>
<executive-summary>Executive summary of contents
<info attr="UK">Only role with "UK" attribute can read this summary</info></executive-summary>
<content>Contents of document
Unclassified content
<notes>
<info attr="UK">Only role with "UK" attribute can read this content</info>
</notes></content>
</root>
And finally modify the query to run in the context of els-user-3
:
// run this query against the Documents database
xdmp.eval("fn.doc('attributes.xml')", null,
{
"userId" : xdmp.user("els-user-3")
});
=>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<title>Document Title</title>
<summary>Summary of document contents</summary>
<executive-summary>Executive summary of contents
<info attr="EU">Only role with "EU" attribute can read this summary</info>
<info attr="UK">Only role with "UK" attribute can read this summary</info>
</executive-summary>
<content>Contents of document
Unclassified content
<notes>
<info attr="EU">Only role with "EU" attribute can read this content</info>
<info attr="UK">Only role with "UK" attribute can read this content</info>
</notes></content>
</root>
The els-user-3
has protected path permissions on both elements with the “EU” info attribute and the elements with the “UK” info attribute. This way, the user can see both elements.
Note
If you run the query in the context of the admin user, you will be able to see the entire document because the query is using fn.doc()
.