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 -
subject
, object
and action
. Here they can be understood as user role
, path
and request method
.
Furthermore, we can assign a group
to our object
or as used here, path
.
For example,
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 POST
and 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 DELETE
and POST
requests on url paths in the user_group
group. These url paths are /api/user/logout
and /api/user
.
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.
Next, the .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, act
.
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 /api/tasks/:userId/today
).
In policy_effect
here, 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.
In 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., sub
, obj
and act
, return the policy result ,p.eft
, which is again rechecked in policy_effect
.
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.
Top comments (0)