ii_policy 1.0.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4b0ae3047d7ec960796e3bc2cb0fec29584717eb19e23035337121b17b0f66e
4
- data.tar.gz: 2d0e5696b4a5888f062ae7b9240eff50f7d94e5ee0f4bf49c461c037e4006619
3
+ metadata.gz: 62f7efd3ac2e7db1c4c9532e987e3ed592083cec2e00f5cca700c5c5a5bab4e6
4
+ data.tar.gz: e6df72f0fae98ff640ff6f87bc8bf3a1297c4470c64c45e5449b9ab439c96bdc
5
5
  SHA512:
6
- metadata.gz: caec6ed0fba367ae7f425afc1c427acef1ec1260e5e0b5057f106a95f237a65d598daadd75156875a4f282d7a606c0616fb7caeccc25b8147e4edc9f7e08adde
7
- data.tar.gz: a49b1a52334ce402ea35a11055a76823713564d84b9d6105e42ec931973acf67dd15d6a85f0e3c98c8d06631ac1369323b8b862883000300d275fef062fb33bf
6
+ metadata.gz: 928646d051e6296eff7dcb3330f8080c36fba6949ffd706165e598f8849d1cf5d6084a4eaf15daab013f289783087a1406c3417c6fb096c963ffd858e4f0c8dc
7
+ data.tar.gz: e21fbbf89718aa908b42acd332b85178cfe7ab8ca9c5b11525b1c0454f6475df77820e4604bc3c275f46359ac32ac9d800107444973b95bc785593d72a6d37a2
@@ -39,4 +39,4 @@ jobs:
39
39
  bundler-cache: true
40
40
  - name: Run test
41
41
  run: |
42
- bundle exec rspec
42
+ DEBUG=1 bundle exec rspec
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.1.0
4
+
5
+ * Support method and block for `chain`.
6
+ * Include `IIPolicy::Chain` by default.
7
+ * Add log subscriber.
8
+
3
9
  ## 1.0.0
4
10
 
5
11
  * First release.
data/README.md CHANGED
@@ -177,7 +177,7 @@ end
177
177
 
178
178
  #### Policy chain
179
179
 
180
- You can chain shared policies to base policy by including `IIPolicy::Chain` as follows:
180
+ You can chain shared policies to base policy by using `chain` as follows:
181
181
 
182
182
  ```ruby
183
183
  # shared policy
@@ -189,8 +189,6 @@ end
189
189
 
190
190
  # base policy
191
191
  class ItemPolicy < IIPolicy::Base
192
- include IIPolicy::Chain
193
-
194
192
  chain SharedPolicy
195
193
 
196
194
  def show?
@@ -205,6 +203,23 @@ policy.allowed(:show?)
205
203
 
206
204
  In this example, `policy.allowed(:show?)` is evaluated by `SharedPolicy#show? && ItemPolicy#show?`.
207
205
 
206
+ You can also use method or block to find policy class dynamically:
207
+
208
+ ```ruby
209
+ class ItemPolicy < IIPolicy::Base
210
+ chain -> { SharedPolicy }
211
+ end
212
+
213
+ class ItemPolicy < IIPolicy::Base
214
+ chain :chain_policy
215
+
216
+ def chain_policy
217
+ SharedPolicy
218
+ end
219
+ end
220
+ ```
221
+
222
+
208
223
  ### Lookup for policy
209
224
 
210
225
  `authorize` and `policy` lookups policy class if the first argument of them is not a policy class.
@@ -250,6 +265,21 @@ IIPolicy::Base.lookup(InheritedItem.new)
250
265
  #=> ItemPolicy
251
266
  ```
252
267
 
268
+ ### Logging
269
+
270
+ Policy supports instrumentation hook supplied by `ActiveSupport::Notifications`.
271
+ You can enable log subscriber as follows:
272
+
273
+ ```ruby
274
+ IIPolicy::LogSubscriber.attach_to :ii_policy
275
+ ```
276
+
277
+ This subscriber will write logs in debug mode as the following example:
278
+
279
+ ```
280
+ Called ItemPolicy#index? for Item#1 and return true (Duration: 0.1ms, Allocations: 9)
281
+ ```
282
+
253
283
  ## Contributing
254
284
 
255
285
  Bug reports and pull requests are welcome at https://github.com/kanety/ii_policy.
data/lib/ii_policy.rb CHANGED
@@ -6,6 +6,7 @@ require 'ii_policy/errors'
6
6
  require 'ii_policy/base'
7
7
  require 'ii_policy/controller'
8
8
  require 'ii_policy/helper'
9
+ require 'ii_policy/log_subscriber'
9
10
  require 'ii_policy/railtie' if defined?(Rails)
10
11
 
11
12
  module IIPolicy
@@ -1,42 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'context'
4
+ require_relative 'core'
4
5
  require_relative 'callbacks'
6
+ require_relative 'instrumentation'
5
7
  require_relative 'lookup'
6
8
  require_relative 'chain'
7
9
 
8
10
  module IIPolicy
9
11
  class Base
12
+ include Core
10
13
  include Callbacks
14
+ include Instrumentation
11
15
  include Lookup
12
-
13
- attr_reader :context, :user, :item
14
-
15
- def initialize(context = {})
16
- @context = if context.is_a?(IIPolicy::Context)
17
- context
18
- else
19
- IIPolicy::Context.new(context)
20
- end
21
- @item = @context.item
22
- @user = @context.user
23
- end
24
-
25
- def call(action)
26
- run_callbacks(:call) do
27
- return false if respond_to?(action) && !send(action)
28
- end
29
- return true
30
- end
31
-
32
- def allowed(action)
33
- call(action)
34
- end
35
-
36
- def policy(item)
37
- context = @context.dup
38
- context.item = item
39
- self.class.lookup(item).new(context)
40
- end
16
+ include Chain
41
17
  end
42
18
  end
@@ -9,6 +9,12 @@ module IIPolicy
9
9
  define_callbacks :call
10
10
  end
11
11
 
12
+ def call(action)
13
+ run_callbacks(:call) do
14
+ super
15
+ end
16
+ end
17
+
12
18
  class_methods do
13
19
  def before_call(*args, &block)
14
20
  set_callback(:call, :before, *args, &block)
@@ -10,15 +10,28 @@ module IIPolicy
10
10
  end
11
11
 
12
12
  def call(action)
13
- self.class._chains.each do |policy|
13
+ lookup.each do |policy|
14
14
  return false unless policy.new(@context).call(action)
15
15
  end
16
16
  super
17
17
  end
18
18
 
19
+ def lookup
20
+ self.class._chains.map do |policy|
21
+ if policy.is_a?(Symbol) && respond_to?(policy, true)
22
+ send(policy)
23
+ elsif policy.is_a?(Proc)
24
+ instance_exec(&policy)
25
+ else
26
+ policy
27
+ end
28
+ end.flatten.compact
29
+ end
30
+
19
31
  class_methods do
20
- def chain(*policies)
32
+ def chain(*policies, &block)
21
33
  self._chains = _chains + policies
34
+ self._chains << block if block
22
35
  end
23
36
  end
24
37
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IIPolicy
4
+ module Core
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ attr_reader :context, :user, :item, :_result
9
+ end
10
+
11
+ def initialize(context = {})
12
+ @context = if context.is_a?(IIPolicy::Context)
13
+ context
14
+ else
15
+ IIPolicy::Context.new(context)
16
+ end
17
+ @item = @context.item
18
+ @user = @context.user
19
+ end
20
+
21
+ def call(action)
22
+ if respond_to?(action) && !send(action)
23
+ @_result = false
24
+ else
25
+ @_result = true
26
+ end
27
+ end
28
+
29
+ def allowed(action)
30
+ call(action)
31
+ end
32
+
33
+ def policy(item)
34
+ context = @context.dup
35
+ context.item = item
36
+ self.class.lookup(item).new(context)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IIPolicy
4
+ module Instrumentation
5
+ extend ActiveSupport::Concern
6
+
7
+ def call(action)
8
+ ActiveSupport::Notifications.instrument 'call.ii_policy', policy: self, action: action do
9
+ super
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IIPolicy
4
+ class LogSubscriber < ActiveSupport::LogSubscriber
5
+ def call(event)
6
+ debug do
7
+ policy = event.payload[:policy]
8
+ action = event.payload[:action]
9
+ item = " for #{policy.item.class}##{policy.item.id}" if policy.item
10
+ "Called #{policy.class}##{action}#{item} and return #{policy._result} (#{additional_log(event)})"
11
+ end
12
+ end
13
+
14
+ def additional_log(event)
15
+ additions = ["Duration: %.1fms" % event.duration]
16
+ additions << "Allocations: %d" % event.allocations if event.respond_to?(:allocations)
17
+ additions.join(', ')
18
+ end
19
+ end
20
+ end
@@ -11,14 +11,14 @@ module IIPolicy
11
11
  end
12
12
 
13
13
  class << self
14
- class_attribute :_cache
15
- self._cache = {}
14
+ class_attribute :cache
15
+ self.cache = {}
16
16
 
17
17
  def call(klass)
18
18
  klass = klass.class unless klass.is_a?(Module)
19
19
  return if terminate?(klass)
20
20
 
21
- cache(klass) do
21
+ with_cache(klass) do
22
22
  if klass.name && (policy = resolve(klass))
23
23
  policy
24
24
  elsif klass.superclass
@@ -29,9 +29,9 @@ module IIPolicy
29
29
 
30
30
  private
31
31
 
32
- def cache(klass)
32
+ def with_cache(klass)
33
33
  if Config.lookup_cache
34
- self._cache[klass] ||= yield
34
+ self.cache[klass] ||= yield
35
35
  else
36
36
  yield
37
37
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IIPolicy
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ii_policy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoshikazu Kaneta
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-06 00:00:00.000000000 Z
11
+ date: 2021-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -124,8 +124,11 @@ files:
124
124
  - lib/ii_policy/config.rb
125
125
  - lib/ii_policy/context.rb
126
126
  - lib/ii_policy/controller.rb
127
+ - lib/ii_policy/core.rb
127
128
  - lib/ii_policy/errors.rb
128
129
  - lib/ii_policy/helper.rb
130
+ - lib/ii_policy/instrumentation.rb
131
+ - lib/ii_policy/log_subscriber.rb
129
132
  - lib/ii_policy/lookup.rb
130
133
  - lib/ii_policy/railtie.rb
131
134
  - lib/ii_policy/version.rb