Skip to content

Instantly share code, notes, and snippets.

@botimer
Created February 19, 2018 23:44
Show Gist options
  • Save botimer/64793200246d40c7f6a161466fc526b2 to your computer and use it in GitHub Desktop.
Save botimer/64793200246d40c7f6a161466fc526b2 to your computer and use it in GitHub Desktop.
Some Checkpoint scribbles

Resource and Zone inheritance (containers and cascading permissions)

What makes these problems challenging is that there are multiple reasonable approaches to the issues. Here are options, none better than the other, for dealing with inheriting permissions from a more 'powerful' resource/zone.

For Resources:

  1. Write it into the policy 1a. Check a property of the parent resource 1b. Check for a grant on the parent resource 1c. Delegate to a policy for the parent resource
  2. Write the inheritance rules into the Resource Resolver such that it returns a token for the resource as well as the parent resource

Note that writing it into the policy allows a different permission to determine the inheritance, but that mismatch is not necessarily good.

For Zones, the options are essentially the same:

  1. Check for a grant in a broader zone by name in the policy
  2. Build the inheritance rules into the ResourceResolver such that the token is checked in multiple zones

As an example:

Say that a Listing belongs to a Category. There is one specific zone, "umich.edu" and a system zone. Content can only be created in the "umich.edu" zone, as "system" serves only as a way to grant global permissions. Suppose some complex rules for whether a user may delete a Listing, where any one of these conditions would permit it:

  1. The user created/owns the Listing
  2. The user has been granted the "manage" permission on the Listing's Category
  3. The user has been granted the "admin" role in the "umich.edu" zone
  4. The user has been granted the "admin" role in the "system" zone

There are many combinations of the above options that could meet this particular scenario. Only rule number 2 would require specialization in the policy (by direct check or delegation), because it is not the same permission as being checked at the Listing level. The other aspects could be implemented within the rules of Resource resolution.

For now, my position is that these are design decisions for each project, but that that direct inheritance should be implemented in the Resource Resolver to avoid incidentally different implementations across policies. However, a small, standalone policy to implement the sub-rule would be an acceptable alternative, and may be preferable in some cases.

class ListingPolicy
  def initialize(authority: nil)
    @authority = authority
  end

  def destroy?
    return true if can_delete_own? && user == listing.owner
    return true if authority.permitted?(user, :destroy, listing)
    false
  end

  private

  def can_delete_own?
    Settings.delete_own
  end

  def authority
    @authority ||= Services.permit_authority
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment