-
Notifications
You must be signed in to change notification settings - Fork 12
Business Rules System
The API contains a sub system designed to make it easier to apply consistent api-wide business rules for working with end points. The core concept behind the rules system is to define rules for each Model and allow/deny CRUD operations.
Rules should not be confused with validation. Where validation is only concerned with pre-write operations and focuses on fine grained control of end point fields, Rules are primarily concerned with READ operations though they do come into place in a few write situations. Still, Rules do not apply to specific field but rather high level allow/disallow access to entire records or end points.
Additionally, Rules do not enforce proactive business logic. ie. Do some other thing when saving a record. The Business Rules system will only block/allow CRUD operations or filter results sets.
The API generates a RuleList accessible as a Shared Service in Phalcon.
Consider this example where a RuleStore is added to the RuleList:
// BaseModel->initialize()
// get the shared RuleList and add a RuleStore for this model
$ruleList = $this->getDI()->get('ruleList');
$ruleList->update($this->getModelName(), $this->configureRuleStore(new \PhalconRest\Rules\Store($this)));
A RuleStore is named after it's associated Model and stored in a simple associate array. Note Th intentional coupling between the RuleStore and a particular model. This approach rules out custom end points that are not backed by a traditional Controller->Entity->Model approach. This is because many rules are implemented as specific PHQL or query param rules which are applied to defined models.
Since the RuleList is access as a shared service, it can be loaded just about anywhere in your code. Best practice is to define rules in one place, namely your Models.
- Allow/Deny Access to an Endpoint entirely
- Enforce simple and complicated filter rules when an end point is loaded or side loaded
- Apply rules in Create/Read/Update/Delete actions
Operate in Controllers to enforce broad deny conditions to an end point or individual records.
Operation on the SearchHelper using syntax very similar to Query params filters. These are applied to core PHQL queries as are generally perform faster than after-query rules. This filter is designed to use the same syntax as those defined in Example Calls and Advanced Filtering
Operate on QueryBuilder to enforce more complicated PHQL based rules. These are applied to core PHQL queries as are generally perform faster than after-query rules.
This is a special kind of rule which allows the developer to register a closure to be processed later when Add/Edit logic is submitted to the api. This is mainly used for cases where the allow/deny rule depends on the actual data posted in that particular request and thus can't be evaluated right away.
Event | Deny | Filter | Query | ModelCallback |
---|---|---|---|---|
GET Many | ✔️ | ✔️ | ✔️ | N/A |
Get 1 | ❓ | ❓ | ❓ | N/A |
Side Loading | ❓ | ✔️ | ✔️ | N/A |
POST | ✔️ | N/A | N/A | ❓ |
Delete | ✔️ | ❓ | ❓ | ❓ |
PUT/PATCH | ✔️ | ❓ | ❓ | ❓ |
Event | Deny | Filter | Query |
---|---|---|---|
GET | Controller->onConstruct |
Entity->configureSearchHelper |
Entity->runSearch |
Side Loading | - | Entity->processRelationRules |
Entity->processRelationRules |
POST | Controller->onConstruct |
N/A | N/A |
Delete | Controller->onConstruct |
❓ | ❓ |
PUT/PATCH | Controller->onConstruct |
N/A | N/A |
Basic Filter Rule
$ruleStore->addFilterRule('id', '45040', '<');
Related Field Rule
$ruleStore->addFilterRule('invoice_groups:name', 'New Default');
// how bout OR filters?
$this->ruleStore->addFilterRule('invoice_groups:name', 'New Default||Default');
Simple DenyRule
Since these rules can be applied selectively, you can run your own logic and only implement rules under some situations.
// Determine User's Group Membership and Block
if(!$user->hasGroup('MYGROUP'){
$ruleStore->addDenyRule(DELETERULES + CREATERULES);
}
Basic QueryRule