checkpoint 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +15 -0
- data/.travis.yml +8 -0
- data/README.md +6 -0
- data/db/migrations/{1_create_permits.rb → 1_create_grants.rb} +1 -1
- data/docs/index.rst +6 -1
- data/lib/checkpoint/agent.rb +32 -31
- data/lib/checkpoint/agent/resolver.rb +45 -15
- data/lib/checkpoint/agent/token.rb +8 -3
- data/lib/checkpoint/authority.rb +126 -14
- data/lib/checkpoint/credential.rb +21 -8
- data/lib/checkpoint/credential/permission.rb +6 -5
- data/lib/checkpoint/credential/resolver.rb +63 -62
- data/lib/checkpoint/credential/role.rb +2 -3
- data/lib/checkpoint/credential/role_map_resolver.rb +65 -0
- data/lib/checkpoint/credential/token.rb +7 -2
- data/lib/checkpoint/db.rb +8 -1
- data/lib/checkpoint/db/cartesian_select.rb +71 -0
- data/lib/checkpoint/db/{permit.rb → grant.rb} +4 -4
- data/lib/checkpoint/db/params.rb +36 -0
- data/lib/checkpoint/db/query/ac.rb +47 -0
- data/lib/checkpoint/db/query/acr.rb +54 -0
- data/lib/checkpoint/db/query/ar.rb +47 -0
- data/lib/checkpoint/db/query/cr.rb +47 -0
- data/lib/checkpoint/grants.rb +116 -0
- data/lib/checkpoint/query/role_granted.rb +1 -1
- data/lib/checkpoint/resource.rb +16 -19
- data/lib/checkpoint/resource/all_of_any_type.rb +0 -8
- data/lib/checkpoint/resource/all_of_type.rb +0 -22
- data/lib/checkpoint/resource/resolver.rb +34 -11
- data/lib/checkpoint/resource/token.rb +7 -2
- data/lib/checkpoint/version.rb +1 -1
- metadata +12 -7
- data/docs/authentication.rst +0 -18
- data/lib/checkpoint/permission_mapper.rb +0 -29
- data/lib/checkpoint/permits.rb +0 -133
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a736e9a0fc810c9323dcd7612aee0cb27af02521c59ef448c62c4e5dac3e15c
|
4
|
+
data.tar.gz: b4ab5365b4cae8e5f0040af209bea2c6b9da1e1e19f856d2ae088081188df1b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9f4e9ddda32c366b2402333cf8e43f52da41ad4c7d5ec5a77b66ec524d43c9a9ed521f533e28a27c5c8a96a5382f08a3212db1b4ebe38c12d8b6ea3042b9151
|
7
|
+
data.tar.gz: ec1130f73c436b07751d09b7a7f74e9975da9ac2d6fdd29908878150e5053e9e15f9ba8916861b82a784aa8dafc28f0aee2bc1a7fb99046f68868a6f5dc1873d
|
data/.rubocop.yml
CHANGED
@@ -15,6 +15,9 @@ AllCops:
|
|
15
15
|
- 'bin/**/*'
|
16
16
|
- 'vendor/**/*'
|
17
17
|
|
18
|
+
Layout/EmptyLineAfterGuardClause:
|
19
|
+
Enabled: false
|
20
|
+
|
18
21
|
Layout/MultilineMethodDefinitionBraceLayout:
|
19
22
|
EnforcedStyle: same_line
|
20
23
|
|
@@ -26,5 +29,17 @@ Metrics/BlockLength:
|
|
26
29
|
- '*.gemspec'
|
27
30
|
ExcludedMethods: ['describe', 'context', 'xdescribe', 'xcontext']
|
28
31
|
|
32
|
+
Layout/SpaceInsideBlockBraces:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
Layout/IndentArray:
|
36
|
+
EnforcedStyle: consistent
|
37
|
+
|
38
|
+
Style/ClassAndModuleChildren:
|
39
|
+
Enabled: false
|
40
|
+
|
29
41
|
Style/StringLiterals:
|
30
42
|
Enabled: false
|
43
|
+
|
44
|
+
Style/SymbolArray:
|
45
|
+
EnforcedStyle: brackets
|
data/.travis.yml
CHANGED
@@ -3,3 +3,11 @@ language: ruby
|
|
3
3
|
rvm:
|
4
4
|
- 2.4.2
|
5
5
|
before_install: gem install bundler -v 1.16.0
|
6
|
+
before_script:
|
7
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
8
|
+
- chmod +x ./cc-test-reporter
|
9
|
+
- ./cc-test-reporter before-build
|
10
|
+
script:
|
11
|
+
- bin/rspec
|
12
|
+
after_script:
|
13
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
[](https://travis-ci.org/mlibrary/checkpoint?branch=master)
|
2
2
|
[](https://coveralls.io/github/mlibrary/checkpoint?branch=master)
|
3
|
+
[](https://checkpoint.readthedocs.io/en/latest/?badge=latest)
|
3
4
|
|
4
5
|
# Checkpoint
|
5
6
|
|
@@ -18,6 +19,11 @@ And then execute:
|
|
18
19
|
|
19
20
|
$ bundle
|
20
21
|
|
22
|
+
## Documentation
|
23
|
+
|
24
|
+
User documentation source is available in the `docs` directory, and in rendered format
|
25
|
+
on [readthedocs](https://checkpoint.readthedocs.io/en/latest/).
|
26
|
+
|
21
27
|
## License
|
22
28
|
|
23
29
|
Checkpoint is licensed under the BSD-3-Clause license. See [LICENSE.md](LICENSE.md).
|
data/docs/index.rst
CHANGED
@@ -17,12 +17,17 @@ where enterprise, legacy, and new systems must all interoperate.
|
|
17
17
|
Checkpoint emphasizes the use of policies and object-oriented design, giving
|
18
18
|
examples from very simple rules through complex group- and role-based scenarios.
|
19
19
|
|
20
|
+
Checkpoint does not handle authentication at all. See Keycard_ for a library
|
21
|
+
that does so and provides identity attributes that can be used as the basis for
|
22
|
+
grants and policies.
|
23
|
+
|
24
|
+
|
20
25
|
Table of Contents
|
21
26
|
-----------------
|
22
27
|
|
23
28
|
.. toctree::
|
24
29
|
:maxdepth: 2
|
25
30
|
|
26
|
-
authentication
|
27
31
|
policies
|
28
32
|
|
33
|
+
.. _Keycard: https://github.com/mlibrary/keycard
|
data/lib/checkpoint/agent.rb
CHANGED
@@ -5,43 +5,46 @@ require 'checkpoint/agent/token'
|
|
5
5
|
|
6
6
|
module Checkpoint
|
7
7
|
# An Agent is an any person or entity that might be granted various
|
8
|
-
#
|
8
|
+
# credentials, such as a user, group, or institution.
|
9
9
|
#
|
10
10
|
# The application objects that an agent represents may be of any type; this
|
11
11
|
# is more of an interface or role than a base class. The important concept is
|
12
|
-
# that
|
12
|
+
# that credentials are granted to agents, and that agents may be representative
|
13
13
|
# of multiple concrete actors, such as any person affiliated with a given
|
14
14
|
# institution or any member of a given group.
|
15
|
+
#
|
16
|
+
# In an application, agents will typically be created by the
|
17
|
+
# {Agent::Resolver} registered with an {Checkpoint::Authority}. This keeps
|
18
|
+
# most of the application code decoupled from the Agent type, allowing the
|
19
|
+
# binding to happen in an isolated component. It will also generally not be
|
20
|
+
# required to subclass Agent, since it delegates to the concrete actor in
|
21
|
+
# flexible, well-defined ways, detailed on the individual methods here.
|
15
22
|
class Agent
|
16
23
|
attr_accessor :actor
|
17
24
|
|
18
|
-
# Create an Agent
|
25
|
+
# Create an Agent, wrapping a concrete actor.
|
26
|
+
#
|
27
|
+
# When retrieving the ID or type, we will delegate to the the actor at that
|
28
|
+
# time. See the {#id} and {#type} methods for exact semantics.
|
19
29
|
def initialize(actor)
|
20
30
|
@actor = actor
|
21
31
|
end
|
22
32
|
|
23
|
-
#
|
33
|
+
# Convert this object to an Agent.
|
24
34
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
|
31
|
-
|
32
|
-
def self.from(actor)
|
33
|
-
if actor.respond_to?(:to_agent)
|
34
|
-
actor.to_agent
|
35
|
-
else
|
36
|
-
new(actor)
|
37
|
-
end
|
35
|
+
# For Checkpoint-supplied Agents, this is an identity operation,
|
36
|
+
# but it allows consistent handling of the built-in types and
|
37
|
+
# application-supplied types that will either implement this interface or
|
38
|
+
# convert themselves to a built-in type. This removes the requirement to
|
39
|
+
# extend Checkpoint types or bind to a specific conversion method.
|
40
|
+
def to_agent
|
41
|
+
self
|
38
42
|
end
|
39
43
|
|
40
|
-
# Get the
|
44
|
+
# Get the wrapped actor's type.
|
41
45
|
#
|
42
|
-
# If the
|
43
|
-
#
|
44
|
-
# will use that. Otherwise, we use the actors's class name.
|
46
|
+
# If the actor implements `#agent_type`, we will return that. Otherwise,
|
47
|
+
# we use the actors's class name.
|
45
48
|
#
|
46
49
|
# @return [String] the name of the actor's type after calling `#to_s` on it.
|
47
50
|
def type
|
@@ -52,14 +55,13 @@ module Checkpoint
|
|
52
55
|
end.to_s
|
53
56
|
end
|
54
57
|
|
55
|
-
# Get the
|
58
|
+
# Get the wrapped actor's ID.
|
56
59
|
#
|
57
|
-
# If the
|
58
|
-
#
|
59
|
-
#
|
60
|
-
# implement any of these methods, we raise a {NoIdentifierError}.
|
60
|
+
# If the actor implements `#agent_id`, we will call it and return that
|
61
|
+
# value. Otherwise, we call `#id`. If the the actor does not implement
|
62
|
+
# either of these methods, we raise a {NoIdentifierError}.
|
61
63
|
#
|
62
|
-
# @return [String] the
|
64
|
+
# @return [String] the actor's ID after calling `#to_s` on it.
|
63
65
|
def id
|
64
66
|
if actor.respond_to?(:agent_id)
|
65
67
|
actor.agent_id
|
@@ -82,12 +84,11 @@ module Checkpoint
|
|
82
84
|
other.is_a?(Agent) && actor.eql?(other.actor)
|
83
85
|
end
|
84
86
|
|
85
|
-
# Check whether two Agents refer to the same concrete actor.
|
87
|
+
# Check whether two Agents refer to the same concrete actor by type and id.
|
86
88
|
# @param other [Agent] Another Agent to compare with
|
87
|
-
# @return [Boolean] true when the other Agent's
|
88
|
-
# determined by comparing them with `==`.
|
89
|
+
# @return [Boolean] true when the other Agent's type and id are equal.
|
89
90
|
def ==(other)
|
90
|
-
other.is_a?(Agent) &&
|
91
|
+
other.is_a?(Agent) && type == other.type && id == other.id
|
91
92
|
end
|
92
93
|
end
|
93
94
|
end
|
@@ -2,16 +2,24 @@
|
|
2
2
|
|
3
3
|
module Checkpoint
|
4
4
|
class Agent
|
5
|
-
# An Agent Resolver
|
6
|
-
#
|
7
|
-
# effect of allowing a Permit to any of those agents to take effect when
|
8
|
-
# authorizing an action by this user.
|
5
|
+
# An Agent Resolver is the bridge between a concrete user (or other
|
6
|
+
# account/actor) and {Agent}s that the user represents.
|
9
7
|
#
|
10
|
-
#
|
11
|
-
# conversion.
|
8
|
+
# There are two basic operations:
|
12
9
|
#
|
13
|
-
#
|
14
|
-
#
|
10
|
+
# - Conversion maps an actor to a single Agent
|
11
|
+
# - Expansion maps an actor to all of the Agents it represents
|
12
|
+
#
|
13
|
+
# These allow credentials to be granted, matched, or revoked with the
|
14
|
+
# appropriate semantics, depending on the operation. In general, a Grant
|
15
|
+
# is given to or revoked from a single Agent, while matching is applied
|
16
|
+
# to all Agents the actor represents.
|
17
|
+
#
|
18
|
+
# This implementation does not implement any expansion semantics other
|
19
|
+
# than to convert the actor into an Agent and return it as a list.
|
20
|
+
#
|
21
|
+
# To extend the set of {Agent}s resolved, implement a subclass
|
22
|
+
# that returns an array of agents from #expand. This customized
|
15
23
|
# implementation would typically be injected to an application-wide
|
16
24
|
# {Checkpoint::Authority}, rather than being used directly.
|
17
25
|
#
|
@@ -19,14 +27,36 @@ module Checkpoint
|
|
19
27
|
# the user is a member of, or IP address-based geographical regions or
|
20
28
|
# organizational affiliations.
|
21
29
|
class Resolver
|
22
|
-
#
|
30
|
+
# Expand an actor to a list of Agents it represents.
|
31
|
+
#
|
32
|
+
# This implementation simply converts the actor and wraps the resulting
|
33
|
+
# Agent in an array.
|
34
|
+
#
|
35
|
+
# If extending or overriding, you will likely want to call super or
|
36
|
+
# {#convert} on the concrete actor to make sure that the most specific
|
37
|
+
# Agent is included. It is acceptable to return subclasses of Agent,
|
38
|
+
# though that is generally unnecessary because of its design of
|
39
|
+
# delegating to actor methods.
|
40
|
+
#
|
41
|
+
# @return [Agent] an array of agents for this actor
|
42
|
+
def expand(actor)
|
43
|
+
[convert(actor)]
|
44
|
+
end
|
45
|
+
|
46
|
+
# Default conversion from an actor to an {Agent}.
|
47
|
+
#
|
48
|
+
# If the actor implements #to_agent, we will delegate to it. Otherwise,
|
49
|
+
# we will instantiate an {Agent} with the supplied actor.
|
50
|
+
#
|
51
|
+
# Override this method to use a different or conditional Agent type.
|
23
52
|
#
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
53
|
+
# @return [Agent] the actor converted to an agent
|
54
|
+
def convert(actor)
|
55
|
+
if actor.respond_to?(:to_agent)
|
56
|
+
actor.to_agent
|
57
|
+
else
|
58
|
+
Agent.new(actor)
|
59
|
+
end
|
30
60
|
end
|
31
61
|
end
|
32
62
|
end
|
@@ -3,9 +3,9 @@
|
|
3
3
|
module Checkpoint
|
4
4
|
class Agent
|
5
5
|
# An Agent::Token is an identifier object for an Agent. It
|
6
|
-
# includes a type and an identifier. A {
|
6
|
+
# includes a type and an identifier. A {Grant} can be created for a Token.
|
7
7
|
# Concrete actors are resolved into a number of agents, and those agents'
|
8
|
-
# tokens will be checked for matching
|
8
|
+
# tokens will be checked for matching grants.
|
9
9
|
class Token
|
10
10
|
attr_reader :type, :id
|
11
11
|
|
@@ -34,7 +34,7 @@ module Checkpoint
|
|
34
34
|
self
|
35
35
|
end
|
36
36
|
|
37
|
-
# @return [String] a token string suitable for granting or matching
|
37
|
+
# @return [String] a token string suitable for granting or matching grants for this agent
|
38
38
|
def to_s
|
39
39
|
"#{type}:#{id}"
|
40
40
|
end
|
@@ -45,6 +45,11 @@ module Checkpoint
|
|
45
45
|
other.is_a?(Token) && type == other.type && id == other.id
|
46
46
|
end
|
47
47
|
|
48
|
+
# @return [Integer] hash code based on to_s
|
49
|
+
def hash
|
50
|
+
to_s.hash
|
51
|
+
end
|
52
|
+
|
48
53
|
alias == eql?
|
49
54
|
alias inspect uri
|
50
55
|
end
|
data/lib/checkpoint/authority.rb
CHANGED
@@ -3,36 +3,52 @@
|
|
3
3
|
require 'checkpoint/agent/resolver'
|
4
4
|
require 'checkpoint/credential/resolver'
|
5
5
|
require 'checkpoint/resource/resolver'
|
6
|
-
require 'checkpoint/
|
6
|
+
require 'checkpoint/grants'
|
7
7
|
|
8
8
|
module Checkpoint
|
9
9
|
# An Authority is the central point of contact for authorization questions in
|
10
|
-
# Checkpoint. It checks whether there are
|
10
|
+
# Checkpoint. It checks whether there are grants that would allow a given
|
11
11
|
# action to be taken.
|
12
12
|
class Authority
|
13
13
|
def initialize(
|
14
14
|
agent_resolver: Agent::Resolver.new,
|
15
15
|
credential_resolver: Credential::Resolver.new,
|
16
16
|
resource_resolver: Resource::Resolver.new,
|
17
|
-
|
17
|
+
grants: Grants.new)
|
18
18
|
|
19
19
|
@agent_resolver = agent_resolver
|
20
20
|
@credential_resolver = credential_resolver
|
21
21
|
@resource_resolver = resource_resolver
|
22
|
-
@
|
22
|
+
@grants = grants
|
23
23
|
end
|
24
24
|
|
25
|
-
|
25
|
+
# Check whether there are any matching grants that would allow this actor
|
26
|
+
# to take the action on the target entity.
|
27
|
+
#
|
28
|
+
# The parameters are generally intended to be the most convenient forms for
|
29
|
+
# the application. For example, user and resource model objects would be
|
30
|
+
# typical in a Rails application, for the actor and entity, respectively.
|
31
|
+
# Using a symbol for a named action is typical.
|
32
|
+
#
|
33
|
+
# Each of these will be converted and expanded by the corresponding
|
34
|
+
# resolver to sets of {Agent}s, {Credential}s, and {Resource}s. In the case
|
35
|
+
# where you already have an Agent, Credential, or Resource, it can be
|
36
|
+
# passed; the expectation is that those types have an identity conversion.
|
37
|
+
#
|
38
|
+
# @param actor [Object|Agent] The person/account taking the action.
|
39
|
+
# @param action [Symbol|String|Credential] The action to authorize or
|
40
|
+
# Credential to check for.
|
41
|
+
# @param entity [Object|Resource] The entity/resource to be acted upon.
|
42
|
+
def permits?(actor, action, entity)
|
26
43
|
# Conceptually equivalent to:
|
27
|
-
# can?(
|
28
|
-
# can?(current_user, 'edit', @listing)
|
44
|
+
# can?(current_user, :edit, @listing)
|
29
45
|
|
30
46
|
# user => agent tokens
|
31
47
|
# action => credential tokens
|
32
48
|
# target => resource tokens
|
33
49
|
|
34
|
-
#
|
35
|
-
# SELECT * FROM
|
50
|
+
# Grant.where(agent: agents, credential: credentials, resource: resources)
|
51
|
+
# SELECT * FROM grants
|
36
52
|
# WHERE agent IN('user:gkostin', 'account-type:umich', 'affiliation:lib-staff')
|
37
53
|
# AND credential IN('permission:edit', 'role:editor')
|
38
54
|
# AND resource IN('listing:17', 'type:listing')
|
@@ -46,13 +62,109 @@ module Checkpoint
|
|
46
62
|
# ^^^ ^^^^ ^^^^
|
47
63
|
# if current_user has at least one row in each of of these columns,
|
48
64
|
# they have been "granted permission"
|
49
|
-
|
50
|
-
agent_resolver.
|
51
|
-
credential_resolver.
|
52
|
-
resource_resolver.
|
65
|
+
grants.for(
|
66
|
+
agent_resolver.expand(actor),
|
67
|
+
credential_resolver.expand(action),
|
68
|
+
resource_resolver.expand(entity)
|
53
69
|
).any?
|
54
70
|
end
|
55
71
|
|
72
|
+
# Find agents who have grants to take an action on an entity.
|
73
|
+
#
|
74
|
+
# The action and entity are expanded for matching more general grants.
|
75
|
+
#
|
76
|
+
# @return [Array<Agent::Token>] The distinct set of tokens for agents permitted to
|
77
|
+
# take the given action on the given entity
|
78
|
+
def who(action, entity)
|
79
|
+
credentials = credential_resolver.expand(action)
|
80
|
+
resources = resource_resolver.expand(entity)
|
81
|
+
|
82
|
+
grants.who(credentials, resources).map do |grant|
|
83
|
+
Agent::Token.new(grant.agent_type, grant.agent_id)
|
84
|
+
end.uniq
|
85
|
+
end
|
86
|
+
|
87
|
+
# Find credentials granted to an actor on an entity.
|
88
|
+
#
|
89
|
+
# The actor and entity are expanded for matching more general grants.
|
90
|
+
#
|
91
|
+
# @return [Array<Credential::Token>] The distinct set of tokens for credentials
|
92
|
+
# that the actor is granted on the entity
|
93
|
+
def what(actor, entity)
|
94
|
+
agents = agent_resolver.expand(actor)
|
95
|
+
resources = resource_resolver.expand(entity)
|
96
|
+
|
97
|
+
grants.what(agents, resources).map do |grant|
|
98
|
+
Credential::Token.new(grant.credential_type, grant.credential_id)
|
99
|
+
end.uniq
|
100
|
+
end
|
101
|
+
|
102
|
+
# Find resources on which the actor is permitted to take the given action.
|
103
|
+
#
|
104
|
+
# The actor and action are expanded for matching more general grants.
|
105
|
+
#
|
106
|
+
# @return [Array<Resource::Token>] The distinct set of tokens for resources
|
107
|
+
# on which the actor is permitted to take the given action
|
108
|
+
def which(actor, action)
|
109
|
+
agents = agent_resolver.expand(actor)
|
110
|
+
credentials = credential_resolver.expand(action)
|
111
|
+
|
112
|
+
grants.which(agents, credentials).map do |grant|
|
113
|
+
Resource::Token.new(grant.resource_type, grant.resource_id)
|
114
|
+
end.uniq
|
115
|
+
end
|
116
|
+
|
117
|
+
# Grant a single credential to a specific actor on an entity.
|
118
|
+
#
|
119
|
+
# The parameters are converted to Agent, Credential, and Resource types,
|
120
|
+
# but not expanded. This allows very specific grants to be made. The
|
121
|
+
# default conversion of a symbol or string as the action is to a
|
122
|
+
# {Credential::Permission} of the same name.
|
123
|
+
#
|
124
|
+
# If you want to use more general grants (for example, for an account type
|
125
|
+
# rather than for a given user), you should pass a more general Agent or an
|
126
|
+
# object that will be converted to one. Another example would be using a
|
127
|
+
# wildcard Resource as the entity to grant the credential for all objects
|
128
|
+
# of some given type.
|
129
|
+
#
|
130
|
+
# @param actor [Object|Agent] The actor to whom the grant should be made.
|
131
|
+
# @param action [Symbol|String|Credential] The action or Credential to grant.
|
132
|
+
# @param entity [Object|Resource] The entity or Resource to which the
|
133
|
+
# grant will apply.
|
134
|
+
# @return [Boolean] True if the grant was made; false if it failed.
|
135
|
+
def grant!(actor, action, entity)
|
136
|
+
grant = grants.grant!(
|
137
|
+
agent_resolver.convert(actor),
|
138
|
+
credential_resolver.convert(action),
|
139
|
+
resource_resolver.convert(entity)
|
140
|
+
)
|
141
|
+
|
142
|
+
!grant.nil?
|
143
|
+
end
|
144
|
+
|
145
|
+
# Revoke a credential from a specific actor on an entity.
|
146
|
+
#
|
147
|
+
# Like {#permit!}, the parameters are converted to Agent, Credential, and
|
148
|
+
# Resource types, but not expanded. This means that specific grants can be
|
149
|
+
# revoked without revoking more general ones. For example, if a user was
|
150
|
+
# granted read permission on an object, and then granted the same credential
|
151
|
+
# on all objects of that type, the more specific grant could be revoked
|
152
|
+
# individually.
|
153
|
+
#
|
154
|
+
# @param actor [Object|Agent] The actor from whom the grant should be revoked.
|
155
|
+
# @param action [Symbol|String|Credential] The action or Credential to revoke.
|
156
|
+
# @param entity [Object|Resource] The entity or Resource upon which the
|
157
|
+
# @return [Boolean] True if any grants were revoked; false if none were revoked.
|
158
|
+
def revoke!(actor, action, entity)
|
159
|
+
revoked = grants.revoke!(
|
160
|
+
agent_resolver.convert(actor),
|
161
|
+
credential_resolver.convert(action),
|
162
|
+
resource_resolver.convert(entity)
|
163
|
+
)
|
164
|
+
|
165
|
+
revoked.positive?
|
166
|
+
end
|
167
|
+
|
56
168
|
# Dummy authority that rejects everything
|
57
169
|
class RejectAll
|
58
170
|
def permits?(*)
|
@@ -62,6 +174,6 @@ module Checkpoint
|
|
62
174
|
|
63
175
|
private
|
64
176
|
|
65
|
-
attr_reader :agent_resolver, :credential_resolver, :resource_resolver, :
|
177
|
+
attr_reader :agent_resolver, :credential_resolver, :resource_resolver, :grants
|
66
178
|
end
|
67
179
|
end
|