Record permission

Last published : Aug 10, 2026
Related information

Introduction

Use the record permission DSL (Domain Specific Language) to specify access rules on records of a given table.
The main goals of the record permission DSL are to not require Java coding, and to be easy to use by people without deep programming knowledge.
You can specify permission on any table using a script. The script consists of a sequence of if then else and return statements that indicate the permission for a record.
You can edit the script using the Data Model Assistant (DMA) .

Lexical structure

Introduction

The script has following structure:
begin
  <statement 1>
  <statement 2>
  ...
  <last statement>
end
All statements except the last one must be an "if then" or an "if then else" statement.
The last statement can be an "if then""if then else" or "return" statement.
Example:
if isMember(administrator) then
  // Administrator has no restrictions.
  return readWrite;

if isMember('french-team') and record.Country='F' then
  //Members of 'french-team' can view and modify data for France.
  return readWrite;

if isMember('us-team') and record.Country='US' then
  //Members of 'us-team' can view and modify data for US.
  return readWrite;

// This statement is not actually needed as 'hidden' is the default permission.
return hidden;

Character set

The Unicode character set is supported.

Character case sensitivity

The DSL is case-sensitive.

Comments

A single line comment extends from // to the end of the current line:
// This is a comment
if record.LastName = 'Doe' then // This is another comment.
  return readOnly;
A multi-line comment extends from **/***and ends with */ :
/* This is a sample of a multi-line
   comment */
if record.isActive then
  return readWrite;

Keywords

There are two types of keyword:
  • Reserved keywords are: ifthenelsebeginendreturnnullandornottruefalse\_ebx .
  • Unreserved keywords are all other keywords defined by the DSL.
The main difference between the two types of keywords is that unreserved ones, but not reserved ones, can be used as plain (unquoted) identifiers.

Identifiers

Unquoted identifier

An unquoted identifier is an unlimited-length sequence of letters, digits or underscore ( \_ ). The first character must be a letter.
Valid letters are a to z and A to Z . Valid digits are 0 to 9 .
An unquoted identifier cannot be equal to a reserved keyword.

Quoted identifiers

A quoted identifier is an unlimited length of Unicode characters
Quoted identifiers must be used surrounded by double quotes.
An unquoted identifier can be used surrounded by double quotes. This means that identifier "a\_name" is equal to a\_name.
Quoted identifiers can be reserved keywords except "\_ebx" .

Types

Supported types

The following types are supported:
Type EBX® corresponding types
Boolean xs:boolean
Decimal xs:decimal xs:int xs:integer
String xs:string xs:anyURI xs:Name osd:text osd:html osd:email osd:password osd:color osd:resource osd:locale osd:dataspaceKey osd:datasetName
Timestamp xs:dateTime
Date xs:date
Time xs:time

Literals

String literal

String literals can be any sequence of Unicode characters surrounded by single quotes. The following table displays characters that need to be replaced by an escape sequence:
Character Escape sequence
Tab \t
Backspace \b
New line \n
Carriage return \r
Form feed \f
Single quote \'
Backlash \\
A character can be specified by a Unicode escape sequence that has the format \uXXXX with XXXX the hexadecimal code of the Unicode character.
Examples
Value Syntax
O’Harra 'O\'Harra'
Noël 'No\u00EBl'
été '\u00e9\u00E9'
Note
An invalid escape or Unicode sequence generates an error at compile time.

Decimal literal

The following decimal formats are supported:
Format Examples
Integer 546 -67
Floating point 54.987 -433.876 0.00054 -0.0032
Exponent notation 34.654e-5 -45E+65 1.543e23

Timestamp literal

Timestamp literals have the format dt(yyyy-MM-dd hh:mm:ss.sss) .
Seconds are optional. When seconds are not specified, 0 is assumed. Seconds can have fractions up to millisecond precision.
The dates that are not valid in the Gregorian calendar generate an error at compile time.
Examples:
dt(2010-01-02 00:00:00.000)
dt(2019-2-3 12:56:7)
dt(2019-2-3 12:56:7.5)
dt(2019-5-7 1:6)

Date literal

Date literals have format d(yyyy-MM-dd) .
The dates that are not valid in the Gregorian calendar generate an error at compile time.
Examples:
d(2010-01-02)
d(2019-2-3)
dt(2019-5-7)

Time literal

Time literals have the format t(hh:mm:ss.sss) .
Seconds are optional. When seconds arenot specified, 0 is assumed. Seconds can have fractions up to millisecond precision.
Invalid times generate an error at compile time.
Examples:
t(00:00:00)
t(12:56:7)
t(12:56:7.5)
t(1:6)

Boolean literal

Boolean literals are true and false .

Field access

Simple fields

Only access to optimized/indexed table field is supported. Dot notation is used to access tables fields. For example, a condition of current table fields whose path is ./OfficeAddress/City would be:
if record.OfficeAddress.City = 'Paris' then
  return readWrite;
The alias record always refers to the current record. Depending on context, other aliases might be available.
Each step (parts separated by a dot) is an identifier . This means that the following quoted notation can be used for any step:
if record."OfficeAddress".City = 'Paris' then
  return readWrite;
This is useful for steps equal to a reserved keyword or using characters, such as the minus character ( - ) or dot ( . ), which are not compatible with unquoted identifiers.
At runtime, any step can evaluate to null . In this case, the full field expression evaluates to null .

Foreign table fields

You can access foreign tables by "following" foreign keys using dot notation.
In the following example, the field Supervisor is a foreign key:
if record.Supervisor.Name = 'John Doe' then
  return readWrite;
There can be multiple levels of foreign keys, such as in the following example:
if record.Supervisor.Supervisor.Supervisor.Name = 'John Doe' then
  return readOnly;

List (multi-valued) field access

Multi-valued fields are not supported.

Associations

Aggregate functions can take as input expressions based on an association. In the following example, the field ManagedUsers is an association:
// All users that manage at least 2 persons have read write access.
if count(record.ManagedUsers[]) >= 2 then
  return readWrite;
You can apply a filter on an association. You must use an alias to access fields from the association. An association alias is declared using : . In the following example, the alias is u1 :
// All users that manage at least one person whose office is in Briton has read only access.
if exists(record.ManagedUsers:u1[u1.OfficeAddress.City='Briton']) then
  return readOnly;
A filter on an association can reference a field of the current record:
// All users that manage at least one person whose office is in the same city as user has read only access.
if exists(record.ManagedUsers:t1[t1.OfficeAddress.City=record.OfficeAddress.City]) then
  return readOnly;
Note
Currently, it is not possible to:
  • Use an aggregate function in between .
  • Select fields of an association to aggregate values.

Operators

By default, operation evaluation order is based on precedence and associativity. The order of evaluation can be indicated explicitly by using parentheses.
The following table shows all operators from highest to lowest precedence and their associativity:
Precedence Level Operator Operand type Result type Associativity
8 (access to an element of a list) . (access to fields) () (parenthesis) List index must be a decimal. Can be any type. Left to right.
7 not Boolean. Boolean.
6 * / Decimal. Decimal. Left to right.
5 + - Decimal. Decimal. Left to right.
4 < <= > >= String, Decimal, timestamp, date, time (3). Boolean. Not associative.
3 = <> String, decimal, timestamp, date, time, boolean (3). Boolean.
2 and Boolean. Boolean. Left to right.
1 or Boolean. Boolean. Left to right.

Null value management

Arithmetic operators

An arithmetic operator ( */+ and - ) returns null if any operand is null .

Comparison operators

A Comparison operator ( <<=>=>= and <> ) returns null if any operand is null .

Boolean operators

Boolean operators use thread-value logic.
Truth table for and is:
And true false null
true true false null
false false false false
null null false null
Truth table for or is:
Or true false null
true true true true
false true false null
null true null null

Index expressions

An indexed expression with an index that evaluates null or is out of range returns null .

Functions

Functions usually return null if a parameter is null . An exception is the function isNull(value) , which never returns null .

If statement

"If then" statement

An "if then" statement has the following syntax:
if condition-expression then
  then-body-statement
The condition expression must evaluate to a boolean type.
If the expression evaluates to true , the "then" statement is executed. If the expression evaluates to false or null , the "then" statement is ignored.
The 'then' statement is a body statement .

"If then else" statement

An "if then else" statement has the following syntax:
if condition-expression then
  then-body-statement
else
  else-body-statement
The condition expression must be of boolean type.
If the expression evaluates to true , then the "then" statement is executed. If the expression evaluates to false or null , then the "else" statement is executed.
A "then" or "else" statement is a body statement .
Note
The expression:
if condition-expression then
  statement-a;
else
  statement-b;
might not be equivalent to:
if not condition-expression then
  statement-b;
else
  statement-a;
Indeed, if the expression is null, then the "else" statement is executed in both cases.

"Then" or "else" body statement

A body statement can be:
A statement block is used to group multiple statements. It starts with the keyword begin and ends with the keyword end .
begin
  <statement 1>
  <statement 2>
  ...
  <last statement>
end
All statements except last one must be an "if then" or an "if then else" statement.
The last statement can be a "if then""if then else" or a "return" statement.
if isMember('sales-team')then
begin
  if record.Country='F' then
     return readWrite;

  if record.Country='UK' then
     return readOnly;
end
else
begin
  if record.Country='D' then
     return readOnly;

  if record.Country='B' then
     return readWrite;

  return hidden;
end

Return statement

A return statement specifies access to records that meet given conditions.
The following table shows valid return statements.
Return statement Description
return hidden; The record is hidden (the user has no access).
return readOnly; The record is read only for the current user.
return readWrite; The record can be read and modified by the current user.
If no return statement applies to a given record, the value hidden is assumed.

Context variables

Introduction

Record permissions can depend on the current dataspace, dataset, or session.

Dataspace

The predefined alias dataspace provides access to information on the current dataspace.
This alias gives access to the following fields:
Name Type Description
name string The name of the dataspace. Because the dataspace namespace and the snapshot namespace are independent, the returned string is only an identifier in the context of one of the namespaces. For a global dataspace or snapshot identifier, use the field id .
id string The persistent identifier of a dataspace or snapshot. Compared to name , this identifier additionally specifies whether this id is for a dataspace or a snapshot.
isSnapshot boolean Is true if dataspace is a snapshot and false if dataspace is a branch.
Example:
if dataspace.name = 'branch-R' then
  return readOnly;

Dataset

The predefined alias dataset provides access to information on the current dataset.
This alias has the following fields:
Name Type Description
name string The name of the dataset.
Example:
if dataset.name = 'TEST' then
  return readWrite;

Session

The predefined alias session provides access to information on the current user session.
This alias has the following fields:
Name Type Description
userId string The current user’s id.
userEmail string The current user’s email.
trackingInfo string The current session’s tracking information.
To check current user’s roles, see Roles .
Example:
if session.userId = 'jdoe' then
  return readWrite;

Context functions

Roles

The following table describes the isMember() function:
Syntax Description
isMember('rolea', 'roleb'…) Returns true if the current user has at least one of the specified roles. The following built-in roles must be specified without quotes: administratorreadOnlyeveryone . Custom roles are specified as string literals. Specifying a role that does not exist is not an error. (It is considered as a role with no members.) Note The roles administrator and 'administrator' can be two distinct roles. This means that isMember(administrator) might not return the same result as is\_member('administrator'). The same rule applies for other built in roles.
Example:
if isMember('SALES', 'SUPPORT') then
  return readWrite;

// Role administrator and not surrounded by quotes:
if isMember(administrator, 'SUPPORT') then
  return readOnly;

Session

The following table describes the session functions:
Syntax Description
getSessionInputParameter(parameterKey, lookupInParentSessions) Returns the session input parameter corresponding to the specified parameterKey . In the context of a workflow interaction, the function looks for the parameter in the input parameters of the workflow task. When lookupInParentSessions is true , the function looks for the parameter in the parent sessions. Otherwise, it looks for the parameter only in the current session.
isInWorkflowInteraction(lookupInParentSessions) Returns true if the current session is in a workflow interaction context. When lookupInParentSessions is true , the function returns true if a parent session is in a workflow interaction context. Otherwise, the function evaluates only the context of the current session.
Example:
// Give read write access if the scripted rule is called in a workflow interaction context and the 'instance' input parameter for the workflow task is 'Library'.
if isInWorkflowInteraction(true) and getSessionInputParameter('instance', true) = 'Library' then
  return readWrite;

Other functions

String matching functions

A string matching function takes three parameters:
  • A stringExpression that evaluates to a string.
  • A pattern that must be a string literal.
  • An optional boolean literal isCaseSensitive that indicates if matching is case-sensitive. If omitted, it is assumed that matching is case-insensitive.
Syntax Description
matches(stringExpression, pattern, isCaseSensitive) Returns true if stringExpression matches a java regular expression pattern .
startsWith(stringExpression, pattern, isCaseSensitive) Returns true if stringExpression starts with string pattern .
endsWith(stringExpression, pattern, isCaseSensitive) Returns true if stringExpression ends with string pattern .
contains(stringExpression, pattern, isCaseSensitive) Returns true if stringExpression contains a string pattern .
containsWholeWord(stringExpression, pattern, isCaseSensitive) Returns true if stringExpression contains a whole word pattern .
Examples:
// Give read write access if first name starts with 'a', 'b' or 'c' (case-sensitive).
if matches(record.FirstName, '[a-c].*', true) then
  return readWrite;

// Give read only access if first name starts with 'Lé' (case-insensitive).
if startsWith(record.FirstName, 'Lé') then
  return readOnly;

// Give read only access if first name ends with 'my' (case-insensitive).
if endsWith(record.FirstName, 'my') then
  return readOnly;

// Give read only access if email contains with 'BeauMont@' (case-sensitive).
if contains(record.Email, 'BeauMont@', true) then
  return readOnly;

// Give read write access if last name contains the whole word 'Michel' (case-insensitive).
if containsWholeWord(record.LastName, 'Michel', false) then
  return readWrite;

Aggregate functions

The following aggregate function can be used with associations:
Syntax Description
count(expression) Returns the number of rows of an expression.
exists(expression) Returns true if the expression evaluates to at least one row.
Examples:
// Give read write access if managed users count is at least 2.
if count(record.ManagedUsers[]) >= 2 then
  return readWrite;

// Give read only access if count of managed users that are not in Paris is less than 4.
if count(record.ManagedUsers:m1[m1.OfficeAddress.City<>'Paris']) < 4 then
  return readOnly;

// Give read write access if managed users count is at least 1.
if exists(record.ManagedUsers[]) then
  return readWrite;

// Give read write access if count of managed users that are not in Briton is at least 1.
if exists(record.ManagedUsers:u1[u1.OfficeAddress.City<>'Briton']) then
  return readWrite;

Date and time functions

The following table lists the date and time functions.
Syntax Description
datetimeNow() Returns the current date and time
dateNow() Returns the current date
timeNow() Returns the current time
Examples:
// Give read write access if the last possible update date hasn't expired yet.
if record.LastPossibleUpdateDate >= dateNow() then
  return readWrite;
else
  return readOnly;

Miscellaneous functions

The following table describes built-in functions that return a boolean.
Syntax Description
isNull(value) Returns true if value is null. Value can be an expression be of any type.
Examples:
// Give read write access if no supervisor.
if isNull(record.supervisor) then
  return readWrite;