Core concepts
To understand how to use Cerberus, there are some key concepts that we'll need to elaborate on.
3 Questions
Checking for permission always comes down to 3 questions:
Who are you?
What do want access to?
How do you want to access it?
Every user action checked by Cerberus answers these 3 questions, and only if granted access can the user perform the action.
As you could probably already tell, the name Cerberus, being a 3-headed dog guarding the gates of Hades, fits this analogy perfectly.
The 'who' always refers to a User, even though they might be granted permission indirectly through a Role.
Example
Now we'll briefly explain how this is modeled.
As an example, lets take a fictitious app called Acme Project Management.
Resource Types and Actions
You will need to model your domain in terms of Resource Types and Actions, or Domain Entities and Commands/Queries.
It's not necessary to have a 100% accurate fit. Only model the Resource Types and Actions that you'll actually want to protect.
It's a simple project management tool, that provides the ability to manage projects, sprints and stories.
Logically, the Resource model might look something like this:
An Account contains Projects, which contains Sprints, which contains Stories.
In this case, there's a natural hierarchy in the domain, which will also influence how permissions are granted (spolier: you may implicitly grant permission on an inner resource through an outer resource, which will be explained later)
These are what we refer to as Resource Types. Actual instances of these types are called Resources.
Now, each Resource Type will additionally have Actions associated with it.
E.g. an Account could have an action called 'CreateProject', which describes creating a new project. And a Project could have an action called 'DeleteProject', which describes deleting the project, and so on, until all individual user actions in your domain have been defined.
In practice, a User would be assigned permissions to perform a subset of these actions on instances of these Resource Types, but more on that later.
Policies
Now that we've modeled our domain, it's time to focus on how we'll want our end-users to authorize themselves.
Grouping the 3 elements (Users, Resources, Actions) together, we end up with a concept called a Permission, which answers the 3 questions above to gain access.
In practice, you will write code that creates these permissions whenever a resource is created, and users will have the ability to create their own permissions.
However, there might be hundreds or even thousands of actions in your domain, so we abstract them away through an element called a Policy to let you give your users as fine- or coarse grained permission management as you think works best.
A Policy is nothing more than a collection of Actions on some Resource Types.
E.g. you might define a Policy called 'CanManageAccount' which includes all Actions on all Resource Types. This means that when a User has been granted this Policy on their Account, they have access to the entire account and everything in it. Conversely, you might define another Policy called 'CanReadStory' which includes only 'read' actions on the Story resource type. This is obviously a far more restricted policy.
Now, let's see how this works with Permissions.
Permissions
A combination of
a User (or Role),
a Resource (instance) and
a list of Policies
make up a Permission.
You will annotate your code with access checks (using one of our client libraries, or manually) at key places, e.g. controllers and UI elements, to check if the user currently logged can perform a specific action on the resource in question.
Cerberus will then check if a permission exists such that the user (either directly or indirectly through a role) has a permission on the resource (either directly, or indirectly through the hierarchy) that includes a policy with the action being checked.
If that all sounds very complicated, don't worry, your part is dead easy. Cerberus takes care of the dirty work, while you simply need to annotate your code with calls like this:
Last updated