Row-Level Security

Row-level security is specified in resourceAccessGrants. For each dataset from which data is returned by a query in the design file, a resourceAccessGrantList specifies the rows to which a user has access. Each grant is defined in a resourceAccessGrant that contains a principalExpression and a filterExpression.

A resourceAccessGrant must be defined for a joined resource if any query in the security definition has at least one item from the resource, even if that query does not include the related dataset.

Row-level security applies whenever access to a secured resource is requested, even if the request is indirect. For instance, a column in the Region table might be joined to a column in the Sales table. User Tomas has access to Region but not Sales. Tomas’s report uses columns from Region but he cannot see them because he does not have access to Sales.

Row-level security is defined as follows:

<resourceAccessGrants>    <!-- Begin row-level security -->
 <resourceAccessGrantList id="expense_join_resource_access_grant" label="aLabel"
              resourceId="expense_join">
  <resourceAccessGrants>
   <resourceAccessGrant id="expense_join_ROLE_SUPERMART_MANAGER_store_row_grant">
    <principalExpression>
     authentication.getPrincipal().getRoles().any{ it.getRoleName() in
     ['ROLE_SUPERMART_MANAGER'] }</principalExpression>
    <filterExpression>s.store_country in ('USA') and s.store_state in ('CA')
    </filterExpression>
   </resourceAccessGrant>
   <resourceAccessGrant id="account_ROLE_SUPERMART_MANAGER_account_row_grant"
              orMultipleExpressions="true">
    <principalExpression>
     authentication.getPrincipal().getRoles().any{ it.getRoleName() in
     ['ROLE_SUPERMART_MANAGER'] }</principalExpression>
    <filterExpression>s.store_number == 0</filterExpression>
   </resourceAccessGrant>
   <resourceAccessGrant id="account_ROLE_SUPERMART_MANAGER_account_row_grant2"
              orMultipleExpressions="true">
    <principalExpression>
     authentication.getPrincipal().getRoles().any{ it.getRoleName()
     in ['ROLE_SUPERMART_MANAGER'] }</principalExpression>
    <filterExpression>s.store_number == 24</filterExpression>
   </resourceAccessGrant>
  </resourceAccessGrants>
 </resourceAccessGrantList>
 <resourceAccessGrantList id="account_resource_access_grant" label="aLabel"
              resourceId="account">
  <resourceAccessGrants>
   <resourceAccessGrant id="account_resource_super_user_row_grant">
    <principalExpression>
     authentication.getPrincipal().getRoles().any{ it.getRoleName() in
     ['ROLE_ADMINISTRATOR'] }</principalExpression>
   </resourceAccessGrant>
   <resourceAccessGrant id="account_ROLE_SUPERMART_MANAGER_row_grant">
    <principalExpression>
     authentication.getPrincipal().getRoles().any{ it.getRoleName() in
     ['ROLE_SUPERMART_MANAGER'] }</principalExpression>
    <filterExpression>account_type == 'Expense'</filterExpression>
   </resourceAccessGrant>
  </resourceAccessGrants>
 </resourceAccessGrantList>
</resourceAccessGrants>

Elements of resourceAccessGrants are:

resourceAccessGrantList. List of grants for one dataset in the Domain.
resourceAccessGrant. Grant in the dataset for a specific case, such as a user or role.
principalExpression. Evaluation of the authentication object and user to determine the role to be granted access.
filterExpression. Filter on the dataset; determines the rows to which access is granted. Filters are applied to resource IDs. See the The DomEL Syntax for examples of valid filter expressions. For an alternative to writing filter expressions in Groovy, see the testProfileAttribute function in Operators and Functions.
Feedback
randomness