This is the code base that Pääsuke, part of the Estonian state portal (https://eesti.ee/volitused) uses to calculate what is available for the user (which roles can add and what the user can do with the mandates (authorisations) the user already has
This application has a rule engine that performs the following checks:
- AddableRoles: (before user can start adding roles it) decides the list of roles user is allowed to add
- VerifyMandateOperations: when the user adds a mandate, it checks that the user has the right to add this role
- VerifyMandateLinks: when the user is looking at the mandates, then the rule engine checks, which actions (delete and addSubDelegate) for each mandate are allowed for the user
Contains Pojos and utility classes used by the drools module. It is in a separate module because drools maven plugin does not work well together with lombok annotations on the classes. So the classes used are in this separate module and drools module can use compiled classes from here.
Contains drools rules and queries. Uses the kie-maven-plugin to generate neccessary classes for rules. Depends on the model
module. The main purpose is offer the ee.eesti.paasuke.namespaceadapterapp.query.Queries
class to other modules.
Uses the drools module and offers rest services for performing drools queries.
You will need:
- Java 11+ (19 is fine)
NB! Maven has a plugin that generates classes based on Drools rules
./mvnw clean compile spring-boot:run
If Swagger is empty, then most likely you haven't generated classes (using ./mvnw compile)
If you have little or no knowledge about Drools rule engine, then first just try reading the rule names (first line starting with "rule ...")
For example, if rule name is: "User can add the role if user has a role in addableBy list" then the rule is just trying to find all the rules that satisfy these criteria and make them addable.
- Rule name must describe what the rule is doing
- Rule file name must start with what action it affects (or if it is creating a query then start with "queries")
- If you want to log in the *.drl rule then use on of:
- AddableRoles.log,
- VerifyMandateLinks.log
- or VerifyMandateOperations.log()
- NB! what class you're using for logging has to match the *.drl file name
- Having separate classes for logging allows later to configure different levels for different loggers
- For example, one could switch on logging for verifying mandate links but switch off logging for others.
- In order to get the logs created by rules in *.drl in logback configuration, set the level to DEBUG and set higher (WARN) if you don't want logs:
<logger name="ee.eesti.paasuke.namespaceadapterapp.logging.AddableRolesLogger" level="debug"/>
<logger name="ee.eesti.paasuke.namespaceadapterapp.logging.VerifyMandateOperations" level="debug"/>
<logger name="ee.eesti.paasuke.namespaceadapterapp.logging.VerifyMandateLinks" level="debug"/>
-
If you need to make one rule depend on another, then (for performance reasons) do not modify() or update() the object if possible. Instead, add a new object to the working memory.
For example, let's look at a use case where rule A sets a value to: MandateTriplet -> Mandate -> VerifiedLink -> delete
There is rule B that depends on this fact. This is why we should inform Drools that we have changed the MandateTriplet, but looking up this object would have a significant performance impact
Instead, the rule A (besides modifying the VerifiedLinks -> delete property), adds an additional fact: verifiedAddSubDelegateLinks.add( newFactObject)
And rule B checks the presence of this fact object.
The *.drl rules are compiled into Java code (don't try to read that generated code, it is not very intuitive)
If you modify any of the Drools rules (*.drl files) then how to get new code:
- Use the Maven plugin of your IDE to run kogito -> kogito:generateModel
- Use maven: ./mvnw -DskipTests=true clean compile
And then use your IDE to run a test that covers that specific scenario.
- Look at the tests!
- Switch on .log().all() in tests
When you want to construct custom payloads or map responses, then use model classes (class name ends with "Pojo") from the tests directory (src/test/java/ee/eesti/paasuke/namespaceadapterapp/testmodel) The reason is that application's own model classes have business logic inside, making them unsuitable for regular POJOs that are just needed to carry data.
Parameter | Mandatory | Description, example |
---|---|---|
namespace.store.url |
yes | Where to pull the list of role definitions |
namespace.store.queryTimeoutMillis |
no | Response timeout for namespace store requests (defaults to 5000ms) |
namespace.store.cacheTimeToLiveSeconds |
no | How long the roles query is cached for (defaults to 10 seconds) |