actor User {
permissions = ["impersonate"];
"impersonate" if global "support";
}
global {
roles = ["support"];
}
resource Organization {
roles = ["admin", "member"];
permissions = ["read", "write"];
"member" if "admin";
"read" if "member";
"write" if "admin";
}
# a user can do anything some other user can do
# if they are allowed to impersonate that user and
# are currently impersonating them
allow(user: User, action: String, resource: Resource) if
other_user matches User and
has_permission(user, "impersonate", other_user) and
is_impersonating(user, other_user) and
has_permission(other_user, action, resource);
# we need to specify the default allow rule here
# because we added our own custom one above
allow(user: User, action: String, resource: Resource) if
has_permission(user, action, resource);
test "global support users can read user organizations via impersonation" {
setup {
has_role(User{"alice"}, "support");
has_role(User{"bob"}, "admin", Organization{"acme"});
has_role(User{"charlie"}, "member", Organization{"bar"});
is_impersonating(User{"alice"}, User{"bob"});
}
# bob can read as a member
assert allow(User{"bob"}, "read", Organization{"acme"});
# alice can impersonate bob
assert allow(User{"alice"}, "impersonate", User{"bob"});
# alice can read via Bob by impersonating bob
assert allow(User{"alice"}, "read", Organization{"acme"});
# charlie can read as a member
assert allow(User{"charlie"}, "read", Organization{"bar"});
# alice cannot read because alice is not impersonating charlie
assert_not allow(User{"alice"}, "read", Organization{"bar"});
}