This is the second part of the blog about casbin.
Here we will discuss about the casbin model that we shall use in our project application.
Here is the link of a sample policy file.
p, user_role_post_publish, post_publish_group, (POST)|(GET) p, user_role_user, user_group, (DELETE)|(POST) p, admin_role_user_manage, user_manage_group, (GET)|(DELETE) p, admin_role_post_manage, post_manage_group, (GET)|(DELETE) g2, /api/post, post_publish_group g2, /api/admin/posts, post_manage_group g2, /api/user/logout, user_group g2, /api/user, user_group g2, /api/admin/users, user_manage_group g2, /api/admin/post/:id, post_manage_group g2, /api/admin/user/:id, user_manage_group g3, /api/post/:id, publicAction g3, /api/posts, publicAction g3, /api/auth/login, publicAction g3, /api/auth/signup, publicAction g, admin, admin_role_user_manage g, admin, admin_role_post_manage g, admin, user_role_post_publish g, admin, user_role_user
Let's try to understand this -
p here represents policy. Policies generally have 3 parts -
action. Here they can be understood as
Furthermore, we can assign a
group to our
object or as used here,
The first line of the file is
p, user_role_post_publish, post_publish_group, (POST)|(GET)
This is a policy where all users that have the role
user_role_post_publish can make a
GET request on the subject
post_publish_group, which is a group.
post_publish_group has the
/api/post path, as mentioned in the file -
g2, /api/post, post_publish_group
Similarly, when we write
p, user_role_user, user_group, (DELETE)|(POST)
It simply means that users with
user_role_user role can make
POST requests on url paths in the
user_group group. These url paths are
publicAction is a group which has paths which are accessible to every user regardless of role.
A group can have multiple url paths, an url path cannot belong to more than one group.
.conf file -
[request_definition] r = sub, obj, act [policy_definition] p = sub, obj, act [role_definition] g = _, _ g2 = _, _ g3 = _, _ g4 = _, _ [policy_effect] e = some(where (p.eft == allow)) [matchers] m = g(r.sub, p.sub) && g2(r.obj, p.obj) && regexMatch(r.act, p.act) || g3(r.obj, "publicAction") || r.sub == "root"
As mentioned in the first blog,
request_definition is the syntax of our request. First we have the subject,
sub, then we have the object,
obj, and then the action,
In our example,
sub is the role,
obj is the url path/group of url paths, and
act is a HTTP method.
policy_definition should match with the
request_definition for things to not break.(think of this as a schema)
Now we have
role_definition, from where casbin reads what each role has access to(for example, let's say some
employee role has access to
e = some(where (p.eft == allow)) translates to - if the matching strategy result p.eft has the result of (some) allow, then the final result is true.
matchers, we are checking if the request and policy components are equal. We are using
regexMatch to check actions because here they are HTTP methods.
For example the final result is true when the request subject,
r.sub is equal to
root, in which case it has all the permissions. This entire expression
m = g(r.sub, p.sub) && g2(r.obj, p.obj) && regexMatch(r.act, p.act) || g3(r.obj, "publicAction") || r.sub == "root" means, that if the requested parameters match with those in the policy, i.e.,
act, return the policy result ,
p.eft, which is again rechecked in
That is all for this blog. Hope the concepts are explained well enough.
In the next blog, i.e., we will use this model in our actix-web app.
Comments below are always welcome.
And don't forget to star our repositories on Github.