actor User {}
resource Organization {
  roles = ["viewer", "owner"];
  permissions = ["view", "edit"];
  "view" if "viewer";
  "edit" if "owner";
  "viewer" if "owner";
}
# This is an example of a different resource block 
resource Repository {
  roles = ["viewer", "owner", "contributor"];
  permissions = ["view", "edit", "create"];
  relations = { parent: Organization };
  "view" if "viewer";
  "edit" if "contributor";
  "create" if "owner";
  "viewer" if "contributor";
  "contributor" if "owner";
  # roles are inherited from the parent organization
  "viewer" if "viewer" on "parent";
  "owner" if "owner" on "parent";
}
test "Organization roles and permissions" {
  # authorization decisions require data which we refer to as Facts. 
  setup {
    has_role(User{"alice"}, "viewer", Organization{"example"});
    has_role(User{"bob"}, "owner", Organization{"example"});
  }
  # This is how we assert that a user is authorized 
  # to perform a particular action or not
  assert     allow(User{"alice"}, "view", Organization{"example"});
  assert     allow(User{"bob"}, "view", Organization{"example"});
  assert_not allow(User{"alice"}, "edit", Organization{"example"});
  assert     allow(User{"bob"}, "edit", Organization{"example"});
}
test "Repository roles and permissions" {
  setup {
    has_role(User{"alice"}, "viewer", Repository{"example"});
    has_role(User{"bob"}, "owner", Repository{"example"});
    has_role(User{"charlie"}, "contributor", Repository{"example"});
  }
  assert     allow(User{"alice"}, "view", Repository{"example"});
  assert     allow(User{"bob"}, "view", Repository{"example"});
  assert     allow(User{"charlie"}, "view", Repository{"example"});
  assert_not allow(User{"alice"}, "edit", Repository{"example"});
  assert     allow(User{"bob"}, "edit", Repository{"example"});
  assert     allow(User{"charlie"}, "edit", Repository{"example"});
  assert_not allow(User{"alice"}, "create", Repository{"example"});
  assert     allow(User{"bob"}, "create", Repository{"example"});
  assert_not allow(User{"charlie"}, "create", Repository{"example"});
}
test "Repository parent relation" {
  setup {
    has_relation(Repository{"example"}, "parent", Organization{"parentOrganization"});
    has_role(User{"alice"}, "viewer", Organization{"parentOrganization"});
    has_role(User{"bob"}, "owner", Organization{"parentOrganization"});
  }
  assert     allow(User{"alice"}, "view", Repository{"example"});
  assert     allow(User{"bob"}, "view", Repository{"example"});
  assert_not allow(User{"charlie"}, "view", Repository{"example"});
  assert_not allow(User{"dave"}, "view", Repository{"example"});
  assert_not allow(User{"alice"}, "edit", Repository{"example"});
  assert     allow(User{"bob"}, "edit", Repository{"example"});
  assert_not allow(User{"charlie"}, "edit", Repository{"example"});
  assert_not allow(User{"dave"}, "edit", Repository{"example"});
  assert_not allow(User{"alice"}, "create", Repository{"example"});
  assert     allow(User{"bob"}, "create", Repository{"example"});
}