Powered by Zoomin Software. For more details please contactZoomin

Secure MarkLogic Server

JavaScript - Matching by Paths or Attributes

  • Last Updated: June 4, 2026
  • 3 minute read
    • MarkLogic Server
    • Version 11.0
    • Documentation

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().

Alert