accessly 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +24 -0
- data/lib/accessly/policy/base.rb +90 -75
- data/lib/accessly/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96505b522e737820634c4c02ab4c861880008a70
|
4
|
+
data.tar.gz: eee707f0a8667c4e9f383e827197f64db141412f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 504dd75a1ce9ae60c89dd3e335de18cb7ef46e45bc2a39d67e07407d94eec0daffbeedcf70ac8a045cdb26c5be2c584c3e756cbbca46757ac9826281b3ad00dd
|
7
|
+
data.tar.gz: 511e3129de53be6bb92c8519db2dd9fc29b392851337dfb38d0104116eb7d56cd0d85f4957465bfcb15b6817e1a602225b5a42e88df56d06aecaafc65ba81ae5
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -64,6 +64,18 @@ class ApplicationFeaturePolicy < Accessly::Policy::Base
|
|
64
64
|
end
|
65
65
|
```
|
66
66
|
|
67
|
+
#### ACTIONS
|
68
|
+
|
69
|
+
Accessly policies rely on a definition of `actions` and/or `actions_on_objects` for effective use. This example uses `actions` which represent a "permission" that can be granted to an actor for later validation within your app's business logic.
|
70
|
+
|
71
|
+
- `actions` map a symbol to an integer value.
|
72
|
+
- An `action` value should be a unique integer within each policy.
|
73
|
+
- removing/editing `actions` and values can have negative consequences if the underlying data is not migrated
|
74
|
+
|
75
|
+
Defined policy `actions` become part of the policy API. (see examples below)
|
76
|
+
|
77
|
+
#### Policy API Example
|
78
|
+
|
67
79
|
With this policy we can `grant` permissions to a user
|
68
80
|
|
69
81
|
```ruby
|
@@ -107,6 +119,18 @@ class UserPolicy < Accessly::Policy::Base
|
|
107
119
|
end
|
108
120
|
```
|
109
121
|
|
122
|
+
#### ACTIONS ON OBJECTS
|
123
|
+
|
124
|
+
Accessly policies rely on a definition of `actions` and/or `actions_on_objects` for effective use. This example uses `actions_on_objects` which associate a "permission" with an object in your system. The "object" is typically an ActiveRecord object.
|
125
|
+
|
126
|
+
- `actions_on_objects` map a symbol to an integer value.
|
127
|
+
- An `actions_on_objects` value should be a unique integer within each policy.
|
128
|
+
- removing/editing `actions_on_objects` and values can have negative consequences if the underlying data is not migrated
|
129
|
+
|
130
|
+
Defined policy `actions_on_objects` become part of the policy API. (see examples below)
|
131
|
+
|
132
|
+
#### Policy API Example
|
133
|
+
|
110
134
|
We differentiate permissions by a `namespace` which by default is the name of your policy class. However,
|
111
135
|
it may be necessary to override the default behavior represented in the above example.
|
112
136
|
|
data/lib/accessly/policy/base.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
module Accessly
|
2
2
|
module Policy
|
3
3
|
class Base
|
4
|
+
# Module that will hold our meta-programmed action methods just above
|
5
|
+
# the policy class in the inheritance hierarchy; allowing for them to
|
6
|
+
# be overridden in the policy.
|
7
|
+
ACTIONS_MODULE = :Actions
|
4
8
|
|
5
9
|
attr_reader :actor
|
6
10
|
|
@@ -8,17 +12,82 @@ module Accessly
|
|
8
12
|
@actor = actor
|
9
13
|
end
|
10
14
|
|
15
|
+
# Meta-programs action methods from actions supplied.
|
16
|
+
# Used in policies as a DSL to declare actions.
|
17
|
+
#
|
18
|
+
# This defines the actions on the `actions_module` so that they are
|
19
|
+
# positioned higher in the inheritance tree than methods defined on the
|
20
|
+
# class itself. This will allow us to define methods that override these
|
21
|
+
# base methods and call `super`.
|
22
|
+
#
|
23
|
+
# @param actions [Hash] the actions to define on the policy
|
24
|
+
#
|
25
|
+
# @example Define Actions
|
26
|
+
#
|
27
|
+
# # This example causes the following methods to be defined:
|
28
|
+
# # some_action? : Returns true if the actor has the some_action
|
29
|
+
# # permission, false otherwise
|
30
|
+
# # flip_the_flop? : Returns true if the actor has the flip_the_flop
|
31
|
+
# # permission, false otherwise
|
32
|
+
# # create? : Returns true if the actor has the create permission, false
|
33
|
+
# # otherwise
|
34
|
+
# actions(
|
35
|
+
# some_action: 1,
|
36
|
+
# flip_the_flop: 2,
|
37
|
+
# create: 3
|
38
|
+
# )
|
39
|
+
#
|
40
|
+
# @return [Hash] actions
|
11
41
|
def self.actions(actions)
|
12
42
|
_actions.merge!(actions)
|
13
43
|
actions.each do |action, action_id|
|
14
|
-
|
44
|
+
actions_module.module_eval do
|
45
|
+
define_method(:"#{action}?") do |*args|
|
46
|
+
_can_do_action?(action, action_id, args.first)
|
47
|
+
end
|
48
|
+
end
|
15
49
|
end
|
16
50
|
end
|
17
51
|
|
52
|
+
# Meta-programs action_on_objects methods from the actions supplied.
|
53
|
+
# Used in policies as a DSL to declare actions on objects.
|
54
|
+
# It is different from actions in that it will also define a method
|
55
|
+
# for listing all objects authorized with this action for the given
|
56
|
+
# actor and that these actions will always be associated not only with
|
57
|
+
# an actor, but with an object of the action.
|
58
|
+
#
|
59
|
+
# @param actions_on_objects [Hash] the actions on objects to define
|
60
|
+
# on the policy
|
61
|
+
#
|
62
|
+
# @example Define Actions On Objects
|
63
|
+
#
|
64
|
+
# # This example causes the following methods to be defined:
|
65
|
+
# # edit : Returns an ActiveRecord::Relation of the objects on which
|
66
|
+
# # the actor has the edit permission
|
67
|
+
# # edit?(object) : Returns true if the actor has the edit permission
|
68
|
+
# # on the given object, false otherwise
|
69
|
+
# # show : Returns an ActiveRecord::Relation of the objects on which
|
70
|
+
# # the actor has the show permission
|
71
|
+
# # show?(object) : Returns true if the actor has the show permission
|
72
|
+
# # on the given object, false otherwise
|
73
|
+
# actions_on_objects(
|
74
|
+
# edit: 1,
|
75
|
+
# show: 2
|
76
|
+
# )
|
77
|
+
#
|
78
|
+
# @return [Hash] actions_on_objects
|
18
79
|
def self.actions_on_objects(actions_on_objects)
|
19
80
|
_actions_on_objects.merge!(actions_on_objects)
|
20
81
|
actions_on_objects.each do |action, action_id|
|
21
|
-
|
82
|
+
actions_module.module_eval do
|
83
|
+
define_method(:"#{action}?") do |*args|
|
84
|
+
_can_do_action?(action, action_id, args.first)
|
85
|
+
end
|
86
|
+
|
87
|
+
define_method(action) do |*args|
|
88
|
+
_list_for_action(action, action_id)
|
89
|
+
end
|
90
|
+
end
|
22
91
|
end
|
23
92
|
end
|
24
93
|
|
@@ -102,85 +171,31 @@ module Accessly
|
|
102
171
|
|
103
172
|
private
|
104
173
|
|
105
|
-
|
106
|
-
|
107
|
-
|
174
|
+
# Accessor for the actions module that will hold our meta-programmed
|
175
|
+
# methods.
|
176
|
+
# We put these methods in this module so that they are positioned
|
177
|
+
# above the policy in the inheritance chain. We can then override
|
178
|
+
# the methods in our policy as needed and call super to access the
|
179
|
+
# previous definition.
|
180
|
+
#
|
181
|
+
# @return [ACTIONS_MODULE] the module for holding actions currently
|
182
|
+
# defined on this class.
|
183
|
+
def self.actions_module
|
184
|
+
if const_defined?(ACTIONS_MODULE, _search_ancestors = false)
|
185
|
+
mod = const_get(ACTIONS_MODULE)
|
108
186
|
else
|
109
|
-
|
187
|
+
mod = const_set(ACTIONS_MODULE, Module.new)
|
188
|
+
include mod
|
110
189
|
end
|
111
|
-
end
|
112
190
|
|
113
|
-
|
114
|
-
# in the format `action_name?`. If so, this calls that method with
|
115
|
-
# the given arguments.
|
116
|
-
def method_missing(method_name, *args)
|
117
|
-
action_method_name = _resolve_action_method_name(method_name)
|
118
|
-
if action_method_name.nil?
|
119
|
-
super
|
120
|
-
else
|
121
|
-
send(action_method_name, *args)
|
122
|
-
end
|
191
|
+
mod
|
123
192
|
end
|
124
193
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
# one of those formats, this assumes the caller is not calling
|
129
|
-
# an action or list method and returns nil.
|
130
|
-
def _resolve_action_method_name(method_name)
|
131
|
-
action_method_match = /\A(\w+)(\??)\z/.match(method_name)
|
132
|
-
|
133
|
-
return nil if action_method_match.nil? || action_method_match[1].nil?
|
134
|
-
|
135
|
-
action_name = action_method_match[1].to_sym
|
136
|
-
is_predicate = action_method_match[2] == "?"
|
137
|
-
|
138
|
-
if !_action_defined?(action_name)
|
139
|
-
nil
|
140
|
-
elsif is_predicate
|
141
|
-
_action_method_name(action_name)
|
194
|
+
def _get_action_id(action, object_id = nil)
|
195
|
+
if object_id.nil?
|
196
|
+
_get_general_action_id!(action)
|
142
197
|
else
|
143
|
-
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
# The implementation for action methods follow the naming format
|
148
|
-
# `_resolve_action_name`. This is to allow child Policies to override
|
149
|
-
# the action method and still be able to call `super` when they
|
150
|
-
# need to call the base implementation of the action method.
|
151
|
-
def self._action_method_name(action_name)
|
152
|
-
"_resolve_#{action_name}"
|
153
|
-
end
|
154
|
-
|
155
|
-
def _action_method_name(action_name)
|
156
|
-
self.class._action_method_name(action_name)
|
157
|
-
end
|
158
|
-
|
159
|
-
# The implementation for list methods follow the naming format
|
160
|
-
# `_list_action_name`. This is to allow child Policies to override
|
161
|
-
# the list method and still be able to call `super` when they
|
162
|
-
# need to call the base implementation of the lsit method.
|
163
|
-
def self._action_list_method_name(action_name)
|
164
|
-
"_list_#{action_name}"
|
165
|
-
end
|
166
|
-
|
167
|
-
def _action_list_method_name(action_name)
|
168
|
-
self.class._action_list_method_name(action_name)
|
169
|
-
end
|
170
|
-
|
171
|
-
# Defines the action method on the Policy class for the given
|
172
|
-
# action name.
|
173
|
-
def self._define_action_methods(action, action_id)
|
174
|
-
unless method_defined?(_action_method_name(action))
|
175
|
-
define_method(_action_method_name(action)) do |*args|
|
176
|
-
_can_do_action?(action, action_id, args.first)
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
unless method_defined?(_action_list_method_name(action))
|
181
|
-
define_method(_action_list_method_name(action)) do |*args|
|
182
|
-
_list_for_action(action, action_id)
|
183
|
-
end
|
198
|
+
_get_action_on_object_id!(action)
|
184
199
|
end
|
185
200
|
end
|
186
201
|
|
data/lib/accessly/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: accessly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Milam
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2018-
|
13
|
+
date: 2018-10-12 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|