ii_policy 1.0.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 +7 -0
- data/.github/workflows/ci.yml +42 -0
- data/.gitignore +10 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +259 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/gemfiles/rails50.gemfile +6 -0
- data/gemfiles/rails51.gemfile +6 -0
- data/gemfiles/rails52.gemfile +6 -0
- data/gemfiles/rails60.gemfile +5 -0
- data/gemfiles/rails61.gemfile +5 -0
- data/ii_policy.gemspec +27 -0
- data/lib/ii_policy.rb +21 -0
- data/lib/ii_policy/base.rb +42 -0
- data/lib/ii_policy/callbacks.rb +26 -0
- data/lib/ii_policy/chain.rb +25 -0
- data/lib/ii_policy/config.rb +21 -0
- data/lib/ii_policy/context.rb +6 -0
- data/lib/ii_policy/controller.rb +27 -0
- data/lib/ii_policy/errors.rb +9 -0
- data/lib/ii_policy/helper.rb +7 -0
- data/lib/ii_policy/lookup.rb +55 -0
- data/lib/ii_policy/railtie.rb +13 -0
- data/lib/ii_policy/version.rb +5 -0
- metadata +154 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f4b0ae3047d7ec960796e3bc2cb0fec29584717eb19e23035337121b17b0f66e
|
4
|
+
data.tar.gz: 2d0e5696b4a5888f062ae7b9240eff50f7d94e5ee0f4bf49c461c037e4006619
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: caec6ed0fba367ae7f425afc1c427acef1ec1260e5e0b5057f106a95f237a65d598daadd75156875a4f282d7a606c0616fb7caeccc25b8147e4edc9f7e08adde
|
7
|
+
data.tar.gz: a49b1a52334ce402ea35a11055a76823713564d84b9d6105e42ec931973acf67dd15d6a85f0e3c98c8d06631ac1369323b8b862883000300d275fef062fb33bf
|
@@ -0,0 +1,42 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
runs-on: ubuntu-18.04
|
8
|
+
strategy:
|
9
|
+
fail-fast: false
|
10
|
+
matrix:
|
11
|
+
ruby: [2.3, 2.4, 2.5, 2.6, 2.7, 3.0]
|
12
|
+
gemfile: ['rails50', 'rails51', 'rails52', 'rails60', 'rails61']
|
13
|
+
exclude:
|
14
|
+
- ruby: 2.3
|
15
|
+
gemfile: rails60
|
16
|
+
- ruby: 2.3
|
17
|
+
gemfile: rails61
|
18
|
+
- ruby: 2.4
|
19
|
+
gemfile: rails60
|
20
|
+
- ruby: 2.4
|
21
|
+
gemfile: rails61
|
22
|
+
- ruby: 3.0
|
23
|
+
gemfile: rails50
|
24
|
+
- ruby: 3.0
|
25
|
+
gemfile: rails51
|
26
|
+
- ruby: 3.0
|
27
|
+
gemfile: rails52
|
28
|
+
|
29
|
+
name: ruby ${{ matrix.ruby }}, ${{ matrix.gemfile }}
|
30
|
+
|
31
|
+
env:
|
32
|
+
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
|
33
|
+
|
34
|
+
steps:
|
35
|
+
- uses: actions/checkout@v2
|
36
|
+
- uses: ruby/setup-ruby@v1
|
37
|
+
with:
|
38
|
+
ruby-version: ${{ matrix.ruby }}
|
39
|
+
bundler-cache: true
|
40
|
+
- name: Run test
|
41
|
+
run: |
|
42
|
+
bundle exec rspec
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2021 Yoshikazu Kaneta
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
# IIPolicy
|
2
|
+
|
3
|
+
A base policy to support management of authorization logic.
|
4
|
+
|
5
|
+
This gem is inspired by [pundit](https://github.com/varvet/pundit) specs.
|
6
|
+
|
7
|
+
## Dependencies
|
8
|
+
|
9
|
+
* ruby 2.3+
|
10
|
+
* activesupport 5.0+
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'ii_policy'
|
18
|
+
```
|
19
|
+
|
20
|
+
Then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
Prepare model:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
class Item < ActiveRecord::Base
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
Prepare controller with `current_user` and call `authorize`:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
class ItemsController < ActionController::Base
|
37
|
+
def index
|
38
|
+
@policy = authorize(ItemPolicy)
|
39
|
+
@items = Item.all
|
40
|
+
end
|
41
|
+
|
42
|
+
def show
|
43
|
+
@item = Item.find(params[:id])
|
44
|
+
@policy = authorize(@item)
|
45
|
+
end
|
46
|
+
|
47
|
+
def current_user
|
48
|
+
User.find(session[:login_user_id])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
Create policy that has methods corresponding with actions of controller:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
class ItemPolicy < IIPolicy::Base
|
57
|
+
def index?
|
58
|
+
@user.admin?
|
59
|
+
end
|
60
|
+
|
61
|
+
def show?
|
62
|
+
@user.admin? && @item.status != 'deleted'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
### Controller
|
68
|
+
|
69
|
+
`authorize` lookups policy and calls it's method corresponding with current action.
|
70
|
+
`authorize` takes following arguments:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
# no argument (policy class is looked up using the name of controller class)
|
74
|
+
authorize
|
75
|
+
|
76
|
+
# instance (policy class is looked up using the name of instance's class)
|
77
|
+
authorize(@item)
|
78
|
+
|
79
|
+
# policy class
|
80
|
+
authorize(ItemPolicy)
|
81
|
+
|
82
|
+
# with extra context as second argument
|
83
|
+
authorize(@item, something: 'something')
|
84
|
+
```
|
85
|
+
|
86
|
+
Context is set to `{ user: current_user }` in the controller by default.
|
87
|
+
You can set other context you want by overriding `policy_context`:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
class ItemsController < ActionController::Base
|
91
|
+
def policy_context
|
92
|
+
super.merge(something: 'something')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
When current user is not authoized, `IIPolicy::AuthorizationError` is raised.
|
98
|
+
You can catch the error and render a special page using `rescue_from`:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
class ItemsController < ActionController::Base
|
102
|
+
rescue_from IIPolicy::AuthorizationError, with: -> { ... }
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
You can also create policy instance by yourself and check authorization using `allowed` method as follows:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
# policy class
|
110
|
+
policy(ItemPolicy).allowed(:index?)
|
111
|
+
|
112
|
+
# instance
|
113
|
+
policy(@item).allowed(:index?)
|
114
|
+
```
|
115
|
+
|
116
|
+
### Policy
|
117
|
+
|
118
|
+
Policy has following attributes:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
class ItemPolicy < IIPolicy::Base
|
122
|
+
def index?
|
123
|
+
puts "user: #{@user}"
|
124
|
+
puts "item: #{@item}"
|
125
|
+
puts "context: #{@context}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
policy = ItemPolicy.new(user: User.find(1), item: Item.find(1), something: 'something')
|
130
|
+
policy.allowed(:index?)
|
131
|
+
#=> user: #<User: ...>
|
132
|
+
# item: #<Item: ...>
|
133
|
+
# context: #<IIPolicy::Context user=..., item=..., something="something">
|
134
|
+
```
|
135
|
+
|
136
|
+
You can call another policy method in the same context:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
class ItemPolicy < IIPolicy::Base
|
140
|
+
def another_show?
|
141
|
+
allowed(:show?)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
```
|
145
|
+
|
146
|
+
You can use policy for another instance by using `policy`:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
class ItemPolicy < IIPolicy::Base
|
150
|
+
def another_show?
|
151
|
+
policy(@context.another_item).allowed(:show?)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
```
|
155
|
+
|
156
|
+
#### Callbacks
|
157
|
+
|
158
|
+
Following callbacks are available:
|
159
|
+
|
160
|
+
* `before_call`
|
161
|
+
* `around_call`
|
162
|
+
* `after_call`
|
163
|
+
|
164
|
+
For example:
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
class ItemPolicy < IIPolicy::Base
|
168
|
+
before_call do
|
169
|
+
@something = @context.something
|
170
|
+
end
|
171
|
+
|
172
|
+
def index?
|
173
|
+
@something == 'something'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
```
|
177
|
+
|
178
|
+
#### Policy chain
|
179
|
+
|
180
|
+
You can chain shared policies to base policy by including `IIPolicy::Chain` as follows:
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
# shared policy
|
184
|
+
class SharedPolicy < IIPolicy::Base
|
185
|
+
def show?
|
186
|
+
@user.admin?
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# base policy
|
191
|
+
class ItemPolicy < IIPolicy::Base
|
192
|
+
include IIPolicy::Chain
|
193
|
+
|
194
|
+
chain SharedPolicy
|
195
|
+
|
196
|
+
def show?
|
197
|
+
@item.status != 'deleted'
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
policy = ItemPolicy.new(user: User.find(1), item: Item.find(1))
|
202
|
+
policy.allowed(:show?)
|
203
|
+
#=> true
|
204
|
+
```
|
205
|
+
|
206
|
+
In this example, `policy.allowed(:show?)` is evaluated by `SharedPolicy#show? && ItemPolicy#show?`.
|
207
|
+
|
208
|
+
### Lookup for policy
|
209
|
+
|
210
|
+
`authorize` and `policy` lookups policy class if the first argument of them is not a policy class.
|
211
|
+
So the name of policy class should be composed of the base name of model or controller.
|
212
|
+
For example:
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
class ItemPolicy < IIPolicy::Base
|
216
|
+
end
|
217
|
+
|
218
|
+
class Item
|
219
|
+
end
|
220
|
+
|
221
|
+
class ItemsController < ActionController::Base
|
222
|
+
end
|
223
|
+
|
224
|
+
IIPolicy::Base.lookup(Item)
|
225
|
+
#=> ItemPolicy
|
226
|
+
|
227
|
+
IIPolicy::Base.lookup(Item.new)
|
228
|
+
#=> ItemPolicy
|
229
|
+
|
230
|
+
IIPolicy::Base.lookup(ItemsController)
|
231
|
+
#=> ItemPolicy
|
232
|
+
```
|
233
|
+
|
234
|
+
Note that superclass of model or controller is also looked up until policy is found.
|
235
|
+
|
236
|
+
```ruby
|
237
|
+
class ItemPolicy < IIPolicy::Base
|
238
|
+
end
|
239
|
+
|
240
|
+
class Item
|
241
|
+
end
|
242
|
+
|
243
|
+
class InheritedItem < Item
|
244
|
+
end
|
245
|
+
|
246
|
+
IIPolicy::Base.lookup(InheritedItem)
|
247
|
+
#=> ItemPolicy
|
248
|
+
|
249
|
+
IIPolicy::Base.lookup(InheritedItem.new)
|
250
|
+
#=> ItemPolicy
|
251
|
+
```
|
252
|
+
|
253
|
+
## Contributing
|
254
|
+
|
255
|
+
Bug reports and pull requests are welcome at https://github.com/kanety/ii_policy.
|
256
|
+
|
257
|
+
## License
|
258
|
+
|
259
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "ii_policy"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
# require "irb"
|
14
|
+
# IRB.start
|
data/bin/setup
ADDED
data/ii_policy.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ii_policy/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ii_policy"
|
8
|
+
spec.version = IIPolicy::VERSION
|
9
|
+
spec.authors = ["Yoshikazu Kaneta"]
|
10
|
+
spec.email = ["kaneta@sitebridge.co.jp"]
|
11
|
+
spec.summary = %q{A base policy to support management of authorization logic}
|
12
|
+
spec.description = %q{A base policy to support management of authorization logic}
|
13
|
+
spec.homepage = "https://github.com/kanety/ii_policy"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
|
+
spec.bindir = "exe"
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "activesupport", ">= 5.0"
|
21
|
+
|
22
|
+
spec.add_development_dependency "rails", ">= 5.0"
|
23
|
+
spec.add_development_dependency "sqlite3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec-rails"
|
26
|
+
spec.add_development_dependency "simplecov"
|
27
|
+
end
|
data/lib/ii_policy.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
require 'ii_policy/version'
|
4
|
+
require 'ii_policy/config'
|
5
|
+
require 'ii_policy/errors'
|
6
|
+
require 'ii_policy/base'
|
7
|
+
require 'ii_policy/controller'
|
8
|
+
require 'ii_policy/helper'
|
9
|
+
require 'ii_policy/railtie' if defined?(Rails)
|
10
|
+
|
11
|
+
module IIPolicy
|
12
|
+
class << self
|
13
|
+
def configure
|
14
|
+
yield Config
|
15
|
+
end
|
16
|
+
|
17
|
+
def config
|
18
|
+
Config
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'context'
|
4
|
+
require_relative 'callbacks'
|
5
|
+
require_relative 'lookup'
|
6
|
+
require_relative 'chain'
|
7
|
+
|
8
|
+
module IIPolicy
|
9
|
+
class Base
|
10
|
+
include Callbacks
|
11
|
+
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
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IIPolicy
|
4
|
+
module Callbacks
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
include ActiveSupport::Callbacks
|
7
|
+
|
8
|
+
included do
|
9
|
+
define_callbacks :call
|
10
|
+
end
|
11
|
+
|
12
|
+
class_methods do
|
13
|
+
def before_call(*args, &block)
|
14
|
+
set_callback(:call, :before, *args, &block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def after_call(*args, &block)
|
18
|
+
set_callback(:call, :after, *args, &block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def around_call(*args, &block)
|
22
|
+
set_callback(:call, :around, *args, &block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IIPolicy
|
4
|
+
module Chain
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :_chains
|
9
|
+
self._chains = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(action)
|
13
|
+
self.class._chains.each do |policy|
|
14
|
+
return false unless policy.new(@context).call(action)
|
15
|
+
end
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
class_methods do
|
20
|
+
def chain(*policies)
|
21
|
+
self._chains = _chains + policies
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IIPolicy
|
4
|
+
class Config
|
5
|
+
class_attribute :data
|
6
|
+
|
7
|
+
self.data = {
|
8
|
+
lookup_cache: true
|
9
|
+
}
|
10
|
+
|
11
|
+
data.keys.each do |key|
|
12
|
+
define_singleton_method "#{key}" do
|
13
|
+
data[key]
|
14
|
+
end
|
15
|
+
|
16
|
+
define_singleton_method "#{key}=" do |val|
|
17
|
+
data[key] = val
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IIPolicy
|
4
|
+
module Controller
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def policy_context
|
8
|
+
{ user: current_user }
|
9
|
+
end
|
10
|
+
|
11
|
+
def policy(item, context = {})
|
12
|
+
if item.is_a?(Class) && item < IIPolicy::Base
|
13
|
+
item.new(policy_context.merge(context))
|
14
|
+
else
|
15
|
+
klass = IIPolicy::Base.lookup(item)
|
16
|
+
raise IIPolicy::Error.new("could not find policy for #{item}") unless klass
|
17
|
+
klass.new(policy_context.merge(context.merge(item: item)))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def authorize(item, context = {})
|
22
|
+
instance = policy(item, context)
|
23
|
+
raise IIPolicy::AuthorizationError.new('Not Authorized') unless instance.call("#{action_name}?")
|
24
|
+
instance
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IIPolicy
|
4
|
+
module Lookup
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
class_methods do
|
8
|
+
def lookup(klass)
|
9
|
+
Lookup.call(klass)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
class_attribute :_cache
|
15
|
+
self._cache = {}
|
16
|
+
|
17
|
+
def call(klass)
|
18
|
+
klass = klass.class unless klass.is_a?(Module)
|
19
|
+
return if terminate?(klass)
|
20
|
+
|
21
|
+
cache(klass) do
|
22
|
+
if klass.name && (policy = resolve(klass))
|
23
|
+
policy
|
24
|
+
elsif klass.superclass
|
25
|
+
call(klass.superclass)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def cache(klass)
|
33
|
+
if Config.lookup_cache
|
34
|
+
self._cache[klass] ||= yield
|
35
|
+
else
|
36
|
+
yield
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def terminate?(klass)
|
41
|
+
klass.name.to_s.in?(['Object', 'ActiveRecord::Base', 'ActiveModel::Base', 'ActionController::Base'])
|
42
|
+
end
|
43
|
+
|
44
|
+
def resolve(klass)
|
45
|
+
policy_name = if klass < ActionController::Base
|
46
|
+
"#{klass.name.sub(/Controller$/, '').singularize}Policy"
|
47
|
+
else
|
48
|
+
"#{klass.name}Policy"
|
49
|
+
end
|
50
|
+
policy = policy_name.safe_constantize
|
51
|
+
return policy if policy && policy_name == policy.name
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IIPolicy
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
ActiveSupport.on_load :action_controller do
|
6
|
+
ActionController::Base.send :include, IIPolicy::Controller
|
7
|
+
end
|
8
|
+
|
9
|
+
ActiveSupport.on_load :action_view do
|
10
|
+
ActionView::Base.send :include, IIPolicy::Helper
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ii_policy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Yoshikazu Kaneta
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-07-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sqlite3
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-rails
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: A base policy to support management of authorization logic
|
98
|
+
email:
|
99
|
+
- kaneta@sitebridge.co.jp
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".github/workflows/ci.yml"
|
105
|
+
- ".gitignore"
|
106
|
+
- ".rspec"
|
107
|
+
- CHANGELOG.md
|
108
|
+
- Gemfile
|
109
|
+
- LICENSE
|
110
|
+
- README.md
|
111
|
+
- Rakefile
|
112
|
+
- bin/console
|
113
|
+
- bin/setup
|
114
|
+
- gemfiles/rails50.gemfile
|
115
|
+
- gemfiles/rails51.gemfile
|
116
|
+
- gemfiles/rails52.gemfile
|
117
|
+
- gemfiles/rails60.gemfile
|
118
|
+
- gemfiles/rails61.gemfile
|
119
|
+
- ii_policy.gemspec
|
120
|
+
- lib/ii_policy.rb
|
121
|
+
- lib/ii_policy/base.rb
|
122
|
+
- lib/ii_policy/callbacks.rb
|
123
|
+
- lib/ii_policy/chain.rb
|
124
|
+
- lib/ii_policy/config.rb
|
125
|
+
- lib/ii_policy/context.rb
|
126
|
+
- lib/ii_policy/controller.rb
|
127
|
+
- lib/ii_policy/errors.rb
|
128
|
+
- lib/ii_policy/helper.rb
|
129
|
+
- lib/ii_policy/lookup.rb
|
130
|
+
- lib/ii_policy/railtie.rb
|
131
|
+
- lib/ii_policy/version.rb
|
132
|
+
homepage: https://github.com/kanety/ii_policy
|
133
|
+
licenses: []
|
134
|
+
metadata: {}
|
135
|
+
post_install_message:
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
requirements: []
|
150
|
+
rubygems_version: 3.1.2
|
151
|
+
signing_key:
|
152
|
+
specification_version: 4
|
153
|
+
summary: A base policy to support management of authorization logic
|
154
|
+
test_files: []
|