User Groups
If your customers have lots of users, it'll be easier for them to manage access for entire groups of users rather than assigning roles individually.
With Oso Cloud, you model this with a rule that allows members of a group to inherit any role assigned to the group.
Implement the logic
The core idea of user groups is that a user inherits all roles from the groups that user belongs to. Assigning a user to a group is sufficient to grant them all roles assigned to that group.
We'll add a rule that expresses exactly that:
# `user` has `role` on `resource` ifhas_role(user: User, role: String, resource: Resource) if # there exists a `group` group matches Group and # `user` is in the group has_group(user, group) and # the `group` has `role` on `resource` has_role(group, role, resource);
Test it out
Here's a full example and test:
actor User { }# A group is a kind of actoractor Group { }resource Repository { roles = ["reader"]; permissions = ["read"]; "read" if "reader";}# users inherit roles from groupshas_role(user: User, role: String, resource: Resource) if group matches Group and has_group(user, group) and has_role(group, role, resource);test "group members can read repositories" { setup { has_role(Group{"anvil-readers"}, "reader", Repository{"anvil"}); has_group(User{"alice"}, Group{"anvil-readers"}); has_group(User{"bob"}, Group{"anvil-readers"}); has_group(User{"charlie"}, Group{"anvil-readers"}); } assert allow(User{"alice"}, "read", Repository{"anvil"}); assert allow(User{"bob"}, "read", Repository{"anvil"}); assert allow(User{"charlie"}, "read", Repository{"anvil"});}
We've assigned the reader
role to the anvil-readers
group, and then added
Alice, Bob, and Charlie to that group. Now they can all read the anvil
repository.
Extension: nested groups
We can extend this logic and let groups be members of other groups. This will allow us to create a hierarchy of groups, and users will inherit roles from all groups in the hierarchy.
We can do this be adding a recursive rule that says a user is a member of a group if they are a member of any of the groups that group is a member of:
has_group(user: User, group: Group) if g matches Group and has_group(user, g) and has_group(g, group);