How to authorize your data
For any application that has more than minimal complexity, you will want to give some users access to specific information and functions, and you will want to deny that access to others. For example, you might want to give an admin user the ability to delete an order, but you don't want anyone else to be able to do that.
The Genesis Platform enables you to do this in extremely precise ways to match your business requirements.
What you can control, and where
Until you start to specify any permissions, everything is accessible by any authenticated user. But you can insert permission statements in the relevant places to control access to data and the ability to change it.
You can also control how users are able to change data. For example, one user might be allowed to create and edit records in a table, but not delete them. Another user might be allowed to create, edit and delete records in that table.
All you need to do is specify the permissions at each point. The Genesis Platform ensures that only users with appropriate permissions are able to act at that point.
Permissions for the back end
Broadly speaking, you can insert permission statements on the back end at three levels:
- tables (data entities): control access to an entire table.
- records within a table (rows): control who has access to specific records based on the contents of each record - for example, view only records for a specific currency.
- fields within a table (attributes/columns): control which columns are visible to different users.
Permissions for the front end
You can also add authorization at the front end. This reinforces the back-end permissions and creates a seamless experience for users with different permissions.
For example, if a user does not have permission to insert or update records on a grid of data, you can set the front end so that the user does not see the relevant buttons or commands on that display.
So, you have full control of data within your application at the most granular level.
How does it work?
Authorization for data is based on Right Codes that you define for your application.
All users can have one or more User Profiles. Each User Profile has one or more Right Codes.
Once you have set up the Right Codes for your application, you can add the relevant Profiles through the front end:
- Create your Profiles: for example, Trader, Senior Trader or Operations.
- Assign one or more Right Codes to each Profile. When a user is given a Profile, she or he has all the rights belonging to that Profile.
- A user can be assigned more than one Profile.
For example, you could set up the following user profiles:
- Trader - with the Right Codes InsertTrade and AmendTrade
- Senior Trader - with only one Right Code: CancelTrade
You could then give all the traders on the team the User Profile Trader. This includes the head trader in the team, but you then also give that user the User Profile Senior Trader. This gives your head trader a superset of rights.
Front-end authorization
You can apply authorization at the front end to remove grids and buttons where there is no appropriate permission. If you don't want to do this, the system is still protected by the permissioning you have set on the back end. Users will receive error messages explaining their lack of permissions.
Example application
Check our example application, which shows the permission features that are available.
The example application has a single data table called Trade. After a remap, this will be populated with 10 entries - 5 in each of 2 Countries. Two further tables are added:
- Countries (single column)
- Mapping (which maps between User and Country to enable row authorization based upon permitted Countries)
The front-end grid demonstrates different authorizations in each quadrant - these map directly to four different Data Server queries, which you can see in the file Permissions-dataserver.kts
.
Only Users assigned to the Profile Full_Access can insert or modify trades. Currently, this is the user AmyAccess, but more Profiles and Users can be added to the application once it is installed and running.
For example, you can edit the User Country table on the Static tab to remove Canada from AmyAccess. Once you have done that, AmyAccess will only be able to enter trades against the UK. You can see the code in the file Permissions-eventhandler.kts
.
Note that only the user admin can modify Profiles and add users. The password for all users who are set up in advance is genesis.
The application also demonstrates authorization at a dataserver and eventhandler level.
The ReadMe file in the project folder provides further information on the project.
A more complex scenario
Authorization can manage more complex situations.
For example, consider the lifecycle of a trade. Perhaps you want to ensure that only super users can modify trades that have settled.
To achieve this, you could modify an existing TRADE_MODIFY event and then create a new modify event for super users only.
The following code modifies the earlier TRADE_MODIFY event to prevent users from changing the transaction if it has a status of Settled
. This is defined in an onValidate
codeblock:
eventHandler<Trade>("TRADE_MODIFY", transactional = true) {
permissioning {
permissionCodes = listOf("TradeUpdate")
}
onValidate { event ->
val trade = entityDb.get(Trade.ById(event.details.tradeId))!!
require(trade != null) { "Trade Id does not exist" }
require(trade.status != status.Settled) { "Trade is already settled" }
ack()
}
onCommit { event ->
...
}
}
You can then easily create a separate event so that super users can modify any trade. In this event, you don't need to check the status - you simply make sure that it is only available to super users.
The example code below enables any user with the Right Code SuperUser to perform any edit on a trade. Users without this Profile cannot gain access to this event. They can only use the TRADE_MODIFY event above, which, as you saw, prevents them from editing settled trades.
eventHandler<Trade>("TRADE_MODIFY_SUPERUSER", transactional = true) {
permissioning {
permissionCodes = listOf("SuperUser")
}
onCommit { event ->
...
}
}
Testing
Go to our Testing page for details of our testing tools and the dependencies that you need to declare.
For testing the auth permissions we have described here, we use common automation frameworks: cucumber and playwright.
Our example tests are able to test authorization via both the user interface and the API.
There are three types of file.
- The feature file contains the test cases, which are written in the Gherkin language. Tags are used to differentiate between the UI (
@UI
) and the API (@API
). - There are separate step definitions (written in Java) for testing the user interface and the API in the step definitions folder.
- You can find the expected results files (.json) in the result folder. The actual results are written to this folder after the tests have been executed.
The E2E tests use two different users to request data from the Data Server. Each user should (of course) see all the data that they are permissioned to view and none of the data that they are not:
- AmyAccess (full access)
- RogerRestricted (limited access)
Preparation
- For testing the API, the back-end processes must be running and healthy.
- For testing the UI, the both the back end and the front end must be running.
Before starting the servers:
- Run
remap
(which imports the data). - Run
consolidate rights
.
Both tasks should execute without any errors.
Genesis has tested the examples successfully on the H2 and Postgres databases.
Full technical details
Find more details in our in our reference documentation:
- Authorization
- [Event Handlers]/develop/server-capabilities/core-business-logic-event-handler/)
onValidate
codeblocks