In 4D 19 R8, we introduced a robust permission system, granting you granular control over user access to your data. This system protects your data depending on who accesses it and which data is accessed, ensuring data security by restricting unauthorized access.
But what if you wanted to further refine read access based on specific criteria?
That’s where 4D 20 R5 steps in. Restricting read data according to some criteria.
a practical use case
Thanks to the system of permission, you can give read access to a Customers dataclass to some users having the appropriate privilege. That’s very good, but if reading the Customers dataclass is granted, the user can read ALL the customers.
For example, imagine an application salespersons use to make deals with their customers. To protect confidentiality, you might restrict the read customers to those managed by the authenticated salesperson.
Of course, you could do this on your own with a custom implementation, but it could lead to cumbersome and hard-to-maintain code. In your code, you must apply your restriction at each place you read data.
Forget it and write your restriction criteria once in a single place, and that’s it!
How to implement this restriction
As the title reveals, the filter applies only to data read with ORDA, and queries handled with classic 4D are not considered.
In the concerned dataclass class, you must use the event keyword to implement a restrict() function. This function must return an entity selection of the concerned dataclass.
In the implementation, you build the entity selection, which will be applied as a restricting filter when you read data from this dataclass using some functions like query() or all(). For more details, have a look at the documentation to check all the other functions concerned by the applied filter.
Below is an example featuring an application used by salespersons to make deals with their customers. We restrict the read customers to those managed by the salesperson using the application.
This application is used in two contexts:
- as a web server
- in client-server
First, here is the data model:
Here is the Customers dataclass class:
Class extends DataClass
Function event restrict() : cs.CustomersSelection
// There is a session
If (Session#Null)
Case of
: (Session.storage.salesInfo#Null)
// Only the customers handled by the authenticated salesperson are returned
return This.query("sales.internalId = :1"; Session.storage.salesInfo.internalId)
// Data explorer
: (Session.hasPrivilege("WebAdmin"))
//No filter is applied
return Null
Else
//No customers can be read
return This.newSelection()
End case
Else
//No customers can be read
return This.newSelection()
End if
The Session object is available in a web context but also in a C/S context (see this new feature)
- The salesperson authenticated themselves with an identifier and password. The authenticated salesperson’s internal ID is stored in the Session. In the restrict() function, we only return the customers managed by this authenticated salesperson.
- The Data explorer also triggers this filter. It uses a web Session with the WebAdmin privilege. In this example, we give access to all the customers in the Data Explorer by returning Null.
- In other cases, for security reasons, we return an empty Customers entity selection to prevent reading customers.
this example in action
In a web context, the authenticated salesperson internalId has been stored in the Session. Only their customers can be read when a request /rest/Customers is run on a web page:
In a client-server context, thanks to the new Session object available in C/S, the authenticated salesperson is also stored in the session.
When we click the Get all customers button, the Customers.all() function is called, and the same filter is applied.
Download the HDI and further discover this powerful feature!