action_policy 0.2.2 → 0.2.3

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: 5aa63f362aa8606be7d0ba77e1c78be9ed8c811eb57b06c38835ec4df24c9bf1
4
- data.tar.gz: 9c704fda90d4735827eddfb78be38a6f2ea2a293f71165df1955cdd78a3e803d
3
+ metadata.gz: c211ebea84e0d55fb6691b9abd897cfd2f594299cd72b1f346b904af99eb192c
4
+ data.tar.gz: b56a427246d7ebd7d5b96660791af5254880ada1c8dc29566ce4114f97f9aac7
5
5
  SHA512:
6
- metadata.gz: a0cd9a62e04d0dbf1263d5c30ba0e860930877e63dd5c3c93f0be327e204b5e66265b8d9ce264278e9b16bef1bff7924331c66f11f88012c0a26dca445ad51bd
7
- data.tar.gz: eb7b6b92a10869ab50f71656b446d26199d339891f5336ca28f87918cfd8dad467498e0262011703662944f82c49927e0c26dc24c871c456813ca87397cc4786
6
+ metadata.gz: 4f2deff9d0ff76e5966e0a4abafc75772730369ac46d033636c26a2cfa236b113c6544ccd2338cdd9813177905f58b97fa6111515b27a3ba7e862fbf7845953d
7
+ data.tar.gz: be2bc03196ac2de3e2ede2d3ea9c995e29352fdf269f9814d1bfe0d8dd9e9a1a4429a10e68631030fd749492888b30de607ebd1748a1656a6e12e0e7fb8ccb14
@@ -9,7 +9,6 @@ AllCops:
9
9
  Exclude:
10
10
  - 'bin/**/*'
11
11
  - 'gemfiles/**/*'
12
- - 'test/dummy/**/*'
13
12
  - 'vendor/**/*'
14
13
  - 'tmp/**/*'
15
14
  DisplayCopNames: true
@@ -1,9 +1,22 @@
1
1
  ## master
2
2
 
3
+ ## 0.2.3 (2018-07-03)
4
+
5
+ - [Fix [#16](https://github.com/palkan/action_policy/issues/16)] Add ability to disable namespace resolution cache. ([@palkan][])
6
+
7
+ We cache namespaced policy resolution for better performance (it could affect performance when we look up a policy from a deeply nested module context).
8
+
9
+ It could be disabled by setting `ActionPolicy::LookupChain.namespace_cache_enabled = false`. It's enabled by default unless `RACK_ENV` env var is specified and is not equal to `"production"` (e.g. when `RACK_ENV=test` the cache is disabled).
10
+
11
+ When using Rails it's enabled only in production mode but could be configured through setting the `config.config.action_policy.namespace_cache_enabled` parameter.
12
+
13
+ - [Fix [#18](https://github.com/palkan/action_policy/issues/18)] Clarify documentation around, and fix the way `resolve_rule` resolves rules and rule aliases when subclasses are involved. ([@brendon][])
14
+
3
15
  ## 0.2.2 (2018-07-01)
4
16
 
5
17
  - [Fix [#29](https://github.com/palkan/action_policy/issues/29)] Fix loading cache middleware. ([@palkan][])
6
18
 
19
+
7
20
  - Use `send` instead of `public_send` to get the `authorization_context` so that contexts such as
8
21
  `current_user` can be `private` in the controller. ([@brendon][])
9
22
 
@@ -52,3 +52,63 @@ end
52
52
  Now when you call `authorize! post` with any rule not explicitly defined in policy class, the `manage?` rule is applied.
53
53
 
54
54
  By default, `ActionPolicy::Base` sets `manage?` as a default rule.
55
+
56
+ ## Aliases and Private Methods
57
+
58
+ Rules in `action_policy` can only be public methods. Trying to use a private method as a rule will raise an error. Thus, aliases can also only point to public methods.
59
+
60
+ ## Rule resolution with subclasses
61
+
62
+ Here's the order in which aliases and concrete rule methods are resolved in regards to subclasses:
63
+
64
+ 1. If there is a concrete rule method on the subclass, this is called, else
65
+ 2. If there is a matching alias then this is called, else
66
+ * When aliases are defined on the subclass they will overwrite matching aliases on the superclass.
67
+ 3. If there is a concrete rule method on the superclass, then this is called, else
68
+ 4. If there is a default rule defined, then this is called, else
69
+ 5. `ActionPolicy::UnknownRule` is raised.
70
+
71
+ Here's an example with the expected results:
72
+
73
+ ```ruby
74
+ class SuperPolicy < ApplicationPolicy
75
+ default_rule :manage?
76
+
77
+ alias_rule :update?, :destroy?, :create?, to: :edit?
78
+
79
+ def manage?; end
80
+
81
+ def edit?; end
82
+
83
+ def index?; end
84
+ end
85
+
86
+ class SubPolicy < AbstractPolicy
87
+ default_rule nil
88
+
89
+ alias_rule :index?, :update?, to: :manage?
90
+
91
+ def create?; end
92
+ end
93
+ ```
94
+
95
+ Authorizing against the SuperPolicy:
96
+
97
+ * `update?` will resolve to `edit?`
98
+ * `destroy?` will resolve to `edit?`
99
+ * `create?` will resolve to `edit?`
100
+ * `manage?` will resolve to `manage?`
101
+ * `edit?` will resolve to `edit?`
102
+ * `index?` will resolve to `index?`
103
+ * `something?` will resolve to `manage?`
104
+
105
+ Authorizing against the SuBPolicy:
106
+
107
+ * `index?` will resolve to `manage?`
108
+ * `update?` will resolve to `manage?`
109
+ * `create?` will resolve to `create?`
110
+ * `destroy?` will resolve to `edit?`
111
+ * `manage?` will resolve to `manage?`
112
+ * `edit?` will resolve to `edit?`
113
+ * `index?` will resolve to `manage?`
114
+ * `something?` will raise `ActionPolicy::UnknownRule`
@@ -67,3 +67,11 @@ end
67
67
  ```
68
68
 
69
69
  **NOTE**: namespace support is an extension for `ActionPolicy::Behaviour` and could be included with `ActionPolicy::Behaviours::Namespaced` (included into Rails controllers and channel integrations by default).
70
+
71
+ ## Namespace resultion cache
72
+
73
+ We cache namespaced policy resolution for better performance (it could affect performance when we look up a policy from a deeply nested module context, see the [benchmark](https://github.com/palkan/action_policy/blob/master/benchmarks/namespaced_lookup_cache.rb)).
74
+
75
+ It could be disabled by setting `ActionPolicy::LookupChain.namespace_cache_enabled = false`. It's enabled by default unless `RACK_ENV` env var is specified and is not equal to `"production"` (e.g. when `RACK_ENV=test` the cache is disabled).
76
+
77
+ When using Rails it's enabled only in production mode but could be configured through setting the `config.config.action_policy.namespace_cache_enabled` parameter.
@@ -36,6 +36,8 @@ end
36
36
 
37
37
  **NOTE:** it is not necessary to inherit from `ActionPolicy::Base`; instead, you can [construct basic policy](custom_policy.md) choosing only the components you need.
38
38
 
39
+ Rules must be public methods on the class. Using private methods as rules will raise an error.
40
+
39
41
  Consider a simple example:
40
42
 
41
43
  ```ruby
@@ -22,7 +22,7 @@ module ActionPolicy
22
22
  attr_reader :store
23
23
 
24
24
  def fetch(namespace, policy)
25
- return yield unless LookupChain.namespace_cache_enabled
25
+ return yield unless LookupChain.namespace_cache_enabled?
26
26
  return store[namespace][policy] if store[namespace].key?(policy)
27
27
  store[namespace][policy] ||= yield
28
28
  end
@@ -38,6 +38,8 @@ module ActionPolicy
38
38
  class << self
39
39
  attr_accessor :chain, :namespace_cache_enabled
40
40
 
41
+ alias namespace_cache_enabled? namespace_cache_enabled
42
+
41
43
  def call(record, **opts)
42
44
  chain.each do |probe|
43
45
  val = probe.call(record, opts)
@@ -76,8 +78,10 @@ module ActionPolicy
76
78
  end
77
79
  end
78
80
 
79
- # Enable namespace cache by default
80
- self.namespace_cache_enabled = true
81
+ # Enable namespace cache by default or
82
+ # if RACK_ENV provided and equal to "production"
83
+ self.namespace_cache_enabled =
84
+ !ENV["RACK_ENV"].nil? ? ENV["RACK_ENV"] == "production" : true
81
85
 
82
86
  # By self `policy_class` method
83
87
  INSTANCE_POLICY_CLASS = ->(record, _) {
@@ -29,8 +29,10 @@ module ActionPolicy
29
29
  end
30
30
 
31
31
  def resolve_rule(activity)
32
- return activity if respond_to?(activity)
33
- self.class.lookup_alias(activity) || super
32
+ self.class.lookup_alias(activity) ||
33
+ (activity if respond_to?(activity)) ||
34
+ self.class.lookup_default_rule ||
35
+ super
34
36
  end
35
37
 
36
38
  module ClassMethods # :nodoc:
@@ -45,7 +47,11 @@ module ActionPolicy
45
47
  end
46
48
 
47
49
  def lookup_alias(rule)
48
- rules_aliases.fetch(rule, rules_aliases[DEFAULT])
50
+ rules_aliases[rule]
51
+ end
52
+
53
+ def lookup_default_rule
54
+ rules_aliases[DEFAULT]
49
55
  end
50
56
 
51
57
  def rules_aliases
@@ -58,6 +64,10 @@ module ActionPolicy
58
64
  {}
59
65
  end
60
66
  end
67
+
68
+ def method_added(name)
69
+ rules_aliases.delete(name) if public_method_defined?(name)
70
+ end
61
71
  end
62
72
  end
63
73
  end
@@ -25,6 +25,11 @@ module ActionPolicy # :nodoc:
25
25
  # the default authorization context in channels
26
26
  attr_accessor :channel_authorize_current_user
27
27
 
28
+ # Define whether to cache namespaced policy resolution
29
+ # result (e.g. in controllers).
30
+ # Enabled only in production by default.
31
+ attr_accessor :namespace_cache_enabled
32
+
28
33
  def cache_store=(store, *args)
29
34
  if store.is_a?(Symbol)
30
35
  store = ActiveSupport::Cache.lookup_store(
@@ -40,6 +45,7 @@ module ActionPolicy # :nodoc:
40
45
  self.controller_authorize_current_user = true
41
46
  self.auto_inject_into_channel = true
42
47
  self.channel_authorize_current_user = true
48
+ self.namespace_cache_enabled = Rails.env.production?
43
49
  end
44
50
 
45
51
  config.action_policy = Config
@@ -50,11 +56,14 @@ module ActionPolicy # :nodoc:
50
56
  app.executor.to_complete { ActionPolicy::PerThreadCache.clear_all }
51
57
  else
52
58
  require "action_policy/cache_middleware"
53
- app_middleware.use ActionPolicy::CacheMiddleware
59
+ app.middleware.use ActionPolicy::CacheMiddleware
54
60
  end
55
61
  end
56
62
 
57
63
  config.to_prepare do |_app|
64
+ ActionPolicy::LookupChain.namespace_cache_enabled =
65
+ Rails.application.config.action_policy.namespace_cache_enabled
66
+
58
67
  ActiveSupport.on_load(:action_controller) do
59
68
  next unless Rails.application.config.action_policy.auto_inject_into_controller
60
69
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionPolicy
4
- VERSION = "0.2.2"
4
+ VERSION = "0.2.3"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: action_policy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-01 00:00:00.000000000 Z
11
+ date: 2018-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler