Skip to main content
Many companies need their authorization policy to correspond to their org chart. Human resources systems, recruiting and applicant tracking systems, and customer relationship management systems all require this pattern. To implement this, we want our authorization model to express authorization in terms of the relationship between two users.

Implementation

A common model for organization hierarchies is some concept of a manager or supervisor having access to the data of their direct reports. In this example, managers should be able to see the repositories of their direct reports, as well as those reports’ reports. We use relations in Oso Cloud to implement this directly: a user has the “viewer” role on a repository if they are the manager of the repository’s creator. We also define the “manager” role recursively, so everyone in a user’s direct chain of command is considered a “manager”.
actor User {
  relations = { direct_manager: User };
  roles = ["manager"];

  "manager" if "direct_manager";
  # This forms the recursive hierarchy; we could remove this line and simplify
  # the policy a bit if we only wanted a single-level of hierarchical
  # visibility.
  "manager" if "manager" on "direct_manager";
}

resource Repository {
  roles = ["viewer"];
  permissions = ["read"];
  relations = { creator: User };

  "viewer" if "creator";
  "viewer" if "manager" on "creator";
  "read" if "viewer";
}

test "manager can have viewer role on employees repos" {
  setup {
    has_relation(Repository{"acme"}, "creator", User{"alice"});
    has_relation(User{"alice"}, "direct_manager", User{"bhav"});
    has_relation(User{"bhav"}, "direct_manager", User{"crystal"});
    # fergie not in alice's direct hierarchy
    has_relation(User{"fergie"}, "direct_manager", User{"crystal"});
  }

  assert allow(User{"alice"}, "read", Repository{"acme"});
  assert allow(User{"bhav"}, "read", Repository{"acme"});
  assert allow(User{"crystal"}, "read", Repository{"acme"});
  # fergie not in alice's direct hierarchy, so cannot read
  assert_not allow(User{"fergie"}, "read", Repository{"acme"});
}
The test covers this case:
  1. Alice creates a repository.
  2. All managers in Alice;s chain of command inherit the viewer role on the repository.
  3. Fergie, who is not in Alice’s management chain, does not receive any permissions.

Next steps