Class: Checkpoint::Authority
- Inherits:
-
Object
- Object
- Checkpoint::Authority
- Defined in:
- lib/checkpoint/authority.rb
Overview
An Authority is the central point of contact for authorization questions in Checkpoint. It checks whether there are grants that would allow a given action to be taken.
Defined Under Namespace
Classes: RejectAll
Instance Method Summary collapse
-
#grant!(actor, action, entity) ⇒ Boolean
Grant a single credential to a specific actor on an entity.
-
#initialize(agent_resolver: Agent::Resolver.new, credential_resolver: Credential::Resolver.new, resource_resolver: Resource::Resolver.new, grants: Grants.new) ⇒ Authority
constructor
A new instance of Authority.
-
#permits?(actor, action, entity) ⇒ Boolean
Check whether there are any matching grants that would allow this actor to take the action on the target entity.
-
#revoke!(actor, action, entity) ⇒ Boolean
Revoke a credential from a specific actor on an entity.
-
#what(actor, entity) ⇒ Array<Credential::Token>
Find credentials granted to an actor on an entity.
-
#which(actor, action) ⇒ Array<Resource::Token>
Find resources on which the actor is permitted to take the given action.
-
#who(action, entity) ⇒ Array<Agent::Token>
Find agents who have grants to take an action on an entity.
Constructor Details
#initialize(agent_resolver: Agent::Resolver.new, credential_resolver: Credential::Resolver.new, resource_resolver: Resource::Resolver.new, grants: Grants.new) ⇒ Authority
Returns a new instance of Authority.
13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/checkpoint/authority.rb', line 13 def initialize( agent_resolver: Agent::Resolver.new, credential_resolver: Credential::Resolver.new, resource_resolver: Resource::Resolver.new, grants: Grants.new) @agent_resolver = agent_resolver @credential_resolver = credential_resolver @resource_resolver = resource_resolver @grants = grants end |
Instance Method Details
#grant!(actor, action, entity) ⇒ Boolean
Grant a single credential to a specific actor on an entity.
The parameters are converted to Agent, Credential, and Resource types, but not expanded. This allows very specific grants to be made. The default conversion of a symbol or string as the action is to a Credential::Permission of the same name.
If you want to use more general grants (for example, for an account type rather than for a given user), you should pass a more general Agent or an object that will be converted to one. Another example would be using a wildcard Resource as the entity to grant the credential for all objects of some given type.
135 136 137 138 139 140 141 142 143 |
# File 'lib/checkpoint/authority.rb', line 135 def grant!(actor, action, entity) grant = grants.grant!( agent_resolver.convert(actor), credential_resolver.convert(action), resource_resolver.convert(entity) ) !grant.nil? end |
#permits?(actor, action, entity) ⇒ Boolean
Check whether there are any matching grants that would allow this actor to take the action on the target entity.
The parameters are generally intended to be the most convenient forms for the application. For example, user and resource model objects would be typical in a Rails application, for the actor and entity, respectively. Using a symbol for a named action is typical.
Each of these will be converted and expanded by the corresponding resolver to sets of Checkpoint::Agents, Credentials, and Resources. In the case where you already have an Agent, Credential, or Resource, it can be passed; the expectation is that those types have an identity conversion.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/checkpoint/authority.rb', line 42 def permits?(actor, action, entity) # Conceptually equivalent to: # can?(current_user, :edit, @listing) # user => agent tokens # action => credential tokens # target => resource tokens # Grant.where(agent: agents, credential: credentials, resource: resources) # SELECT * FROM grants # WHERE agent IN('user:gkostin', 'account-type:umich', 'affiliation:lib-staff') # AND credential IN('permission:edit', 'role:editor') # AND resource IN('listing:17', 'type:listing') # agent_type, agent_id | cred_type, cred_id | resource_type, resource_id # ------------------------------------------------------------------------ # 'user:gkostin' | 'permission:edit' | 'listing:17' # 'account-type:umich' | 'role:editor' | 'type:listing' # 'affiliation:lib-staff' | | 'listing:*' # ^^^ ^^^^ ^^^^ # if current_user has at least one row in each of of these columns, # they have been "granted permission" grants.for( agent_resolver.(actor), credential_resolver.(action), resource_resolver.(entity) ).any? end |
#revoke!(actor, action, entity) ⇒ Boolean
Revoke a credential from a specific actor on an entity.
Like #permit!, the parameters are converted to Agent, Credential, and Resource types, but not expanded. This means that specific grants can be revoked without revoking more general ones. For example, if a user was granted read permission on an object, and then granted the same credential on all objects of that type, the more specific grant could be revoked individually.
158 159 160 161 162 163 164 165 166 |
# File 'lib/checkpoint/authority.rb', line 158 def revoke!(actor, action, entity) revoked = grants.revoke!( agent_resolver.convert(actor), credential_resolver.convert(action), resource_resolver.convert(entity) ) revoked.positive? end |
#what(actor, entity) ⇒ Array<Credential::Token>
Find credentials granted to an actor on an entity.
The actor and entity are expanded for matching more general grants.
93 94 95 96 97 98 99 100 |
# File 'lib/checkpoint/authority.rb', line 93 def what(actor, entity) agents = agent_resolver.(actor) resources = resource_resolver.(entity) grants.what(agents, resources).map do |grant| Credential::Token.new(grant.credential_type, grant.credential_id) end.uniq end |
#which(actor, action) ⇒ Array<Resource::Token>
Find resources on which the actor is permitted to take the given action.
The actor and action are expanded for matching more general grants.
108 109 110 111 112 113 114 115 |
# File 'lib/checkpoint/authority.rb', line 108 def which(actor, action) agents = agent_resolver.(actor) credentials = credential_resolver.(action) grants.which(agents, credentials).map do |grant| Resource::Token.new(grant.resource_type, grant.resource_id) end.uniq end |
#who(action, entity) ⇒ Array<Agent::Token>
Find agents who have grants to take an action on an entity.
The action and entity are expanded for matching more general grants.
78 79 80 81 82 83 84 85 |
# File 'lib/checkpoint/authority.rb', line 78 def who(action, entity) credentials = credential_resolver.(action) resources = resource_resolver.(entity) grants.who(credentials, resources).map do |grant| Agent::Token.new(grant.agent_type, grant.agent_id) end.uniq end |