Example—Introducing Roles, Users, and Execute Privileges
Consider a simple scenario with two roles: engineering
and sales
. The engineering
role is responsible for making widgets and has privileges needed to perform activities related to making widgets. The sales
role is responsible for selling widgets and has privileges to perform activities related to selling widgets.
To begin, create two roles in MarkLogic Server named engineering
and sales
respectively.
The engineering
role needs to be able to make widgets. You can create an execute privilege with the name make-widget
, and action URI http://widget.com/make-widget
to represent that privilege. The sales
role needs to sell widgets, so you create an execute privilege with the name sell-widget
and action URI http://widget.com/sell-widget
to represent that privilege.
Note
Names for execute privileges are used only as display identifiers in the Admin Interface. The action URIs are used within XQuery or JavaScript code to identify the privilege.
Ron is an engineer in your company, so you create a user for Ron and assign the engineering
role to the newly created user. Emily is an account representative, so you create a user for Emily and assign her the sales
role.
In your XQuery code, use the xdmp:security-assert()
function to ensure that only engineers make widgets and only account representatives sell widgets (if you are using JavaScript, you can similarly call xdmp.securityAssert()
in your JavaScript function to protect the code). For example:
xquery version "1.0-ml" define function make-widget(...) as ... { xdmp:security-assert("http://widget.com/make-widget", "execute"), make widget...}
If Ron is logged into the application and executes the make-widget()
function, xdmp:security-assert("http://widget.com/make-widget", "execute")
succeeds since Ron is of the engineering role which has the execute privilege to make widgets.
If Emily attempts to execute the make-widget()
function, the xdmp:security-assert()
function call throws an exception. You can catch the exception and handle it with a try/catch
in the code. If the exception is not caught, the transaction that called this function is rolled back.
Some functions are common to several protected actions. You can protect such a function with a single xdmp:security-assert()
call by providing the appropriate action URIs in a list. For example, if a user needs to execute the count-widgets()
function when making or selling widgets, you might protect the function as follows:
xquery version "1.0-ml" define function count-widgets(...) as ... { xdmp:security-assert( ("http://widget.com/make-widget", "http://widget.com/sell-widget"), "execute"), count-widget... }
If there is a function that requires more than one privilege before it can be performed, place the xdmp:security-assert() calls sequentially. For example, if you need to be a manager in the sales department to give discounts when selling the widgets, you can protect the function as follows:
xquery version "1.0-ml" define function discount-widget(...) as ... { xdmp:security-assert( "http://widget.com/sell-widget", "execute"), xdmp:security-assert( "http://widget.com/change-price", "execute"), discount widget... }
where http://widget.com/change-price
is an action URI for a change-price
execute privilege assigned to the manager
role. A user needs to have the sales
role and the manager
role, which provides the user with the sell-widget
and change-price
execute privileges, to be able to execute this function.