critic 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +7 -1
- data/Appraisals +11 -0
- data/CHANGELOG.md +22 -0
- data/Gemfile +2 -1
- data/LICENSE.txt +7 -0
- data/README.md +76 -5
- data/critic.gemspec +3 -2
- data/lib/critic/authorization.rb +1 -0
- data/lib/critic/authorization_denied.rb +1 -0
- data/lib/critic/callbacks.rb +4 -4
- data/lib/critic/controller.rb +3 -2
- data/lib/critic/policy.rb +13 -11
- data/lib/critic/version.rb +1 -1
- metadata +14 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0119b15b73b4b634a8094d17b84a57d1a184a4ac'
|
4
|
+
data.tar.gz: 695b82b9e3aef373a73b23fa865e67ed4cd0e896
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e006d30bcdfced9e3eb957cc8ddb80418b894213eab82f3b8f0f520282eaf47e3c76b6120ff23da6ad153886476bf7b12b1833aba6f1924e42f9b9925b13d7ed
|
7
|
+
data.tar.gz: 7f8256287c97d17118eb0f33665602d63364657fd6b9dbe0fac96bd9cb6ad2221e0ede3a68bb50c7c488dc35b7c2b69c8ccddff8138c2edc7b80a5e2b07379ce
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -4,8 +4,14 @@ cache:
|
|
4
4
|
- bundler
|
5
5
|
rvm:
|
6
6
|
- 2.3.0
|
7
|
-
|
7
|
+
before_script:
|
8
|
+
- bundle install
|
9
|
+
script:
|
8
10
|
- bundle exec rake rubocop
|
9
11
|
- bundle exec rake spec
|
10
12
|
notifications:
|
11
13
|
email: false
|
14
|
+
gemfile:
|
15
|
+
- gemfiles/activesupport_5.gemfile
|
16
|
+
- gemfiles/activesupport_4.gemfile
|
17
|
+
- gemfiles/activesupport_3.gemfile
|
data/Appraisals
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Change Log
|
2
|
+
|
3
|
+
## [Unreleased](https://github.com/lanej/critic/tree/HEAD)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/lanej/critic/compare/v0.2.0...HEAD)
|
6
|
+
|
7
|
+
**Merged pull requests:**
|
8
|
+
|
9
|
+
- chore: loosen activesupport requirement and test versions [\#3](https://github.com/lanej/critic/pull/3) ([lanej](https://github.com/lanej))
|
10
|
+
- add MIT license [\#2](https://github.com/lanej/critic/pull/2) ([thommahoney](https://github.com/thommahoney))
|
11
|
+
|
12
|
+
## [v0.2.0](https://github.com/lanej/critic/tree/v0.2.0) (2016-06-22)
|
13
|
+
[Full Changelog](https://github.com/lanej/critic/compare/v0.1.1...v0.2.0)
|
14
|
+
|
15
|
+
**Merged pull requests:**
|
16
|
+
|
17
|
+
- add callbacks to `Critic::Policy\#authorize` [\#1](https://github.com/lanej/critic/pull/1) ([lanej](https://github.com/lanej))
|
18
|
+
|
19
|
+
## [v0.1.1](https://github.com/lanej/critic/tree/v0.1.1) (2016-06-07)
|
20
|
+
|
21
|
+
|
22
|
+
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
data/Gemfile
CHANGED
data/LICENSE.txt
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2016 Joshua Lane
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -46,7 +46,7 @@ The most basic actions return `true` or `false` to indicate the authorization st
|
|
46
46
|
class PostPolicy
|
47
47
|
include Critic::Policy
|
48
48
|
|
49
|
-
def update
|
49
|
+
def update?
|
50
50
|
!resource.locked
|
51
51
|
end
|
52
52
|
end
|
@@ -60,15 +60,15 @@ Verify authorization using `#authorize`.
|
|
60
60
|
Post = Struct.new(:locked)
|
61
61
|
User = Struct.new
|
62
62
|
|
63
|
-
PostPolicy.authorize(:update
|
64
|
-
PostPolicy.authorize(:update
|
63
|
+
PostPolicy.authorize(:update?, User.new, Post.new(false)).granted? #=> true
|
64
|
+
PostPolicy.authorize(:update?, User.new, Post.new(true)).granted? #=> false
|
65
65
|
```
|
66
66
|
|
67
67
|
#### Scopes
|
68
68
|
|
69
69
|
Scopes treat `resource` as a starting point and return a restricted set of associated resources. Policies can have any number of scopes. The default scope is `#index`.
|
70
70
|
|
71
|
-
```
|
71
|
+
```ruby
|
72
72
|
# app/policies/post_policy.rb
|
73
73
|
class PostPolicy
|
74
74
|
include Critic::Policy
|
@@ -79,6 +79,40 @@ class PostPolicy
|
|
79
79
|
end
|
80
80
|
```
|
81
81
|
|
82
|
+
#### Convention
|
83
|
+
|
84
|
+
It can be a useful convention to add a `?` suffix to your action methods. This allows a clear separation between actions and scopes. All other methods should be `protected`, similar to Rails controller.
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
# app/policies/post_policy.rb
|
88
|
+
class PostPolicy
|
89
|
+
include Critic::Policy
|
90
|
+
|
91
|
+
# default scope
|
92
|
+
def index
|
93
|
+
Post.where(published: true)
|
94
|
+
end
|
95
|
+
|
96
|
+
# custom scope
|
97
|
+
def author_index
|
98
|
+
Post.where(author_id: subject.id)
|
99
|
+
end
|
100
|
+
|
101
|
+
# action
|
102
|
+
def show?
|
103
|
+
(post.draft? && authored_post?) || post.published?
|
104
|
+
end
|
105
|
+
|
106
|
+
protected
|
107
|
+
|
108
|
+
alias post resource
|
109
|
+
|
110
|
+
def authored_post?
|
111
|
+
subject == post.author
|
112
|
+
end
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
82
116
|
### Controller
|
83
117
|
|
84
118
|
Controllers are the primary consumer of policies. Controllers ask the policy if an authenticated subject is authorized to perform a specific action on a specific resource.
|
@@ -127,8 +161,12 @@ class PostController < Sinatra::Base
|
|
127
161
|
post.to_json
|
128
162
|
end
|
129
163
|
end
|
164
|
+
|
165
|
+
|
130
166
|
```
|
131
167
|
|
168
|
+
#### Custom subject
|
169
|
+
|
132
170
|
By default, the policy's subject is referenced by `current_user`. Override `critic` to customize.
|
133
171
|
|
134
172
|
```ruby
|
@@ -144,9 +182,43 @@ class ApplicationController < ActionController::Base
|
|
144
182
|
end
|
145
183
|
```
|
146
184
|
|
185
|
+
#### Custom policy
|
186
|
+
|
187
|
+
The default policy for a resource is referenced by the resoure class name. For instance, Critic will look for a `PostPolicy` for a `Post.new` object. You can set a custom policy for the entire controller by overriding the `policy` method.
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
# app/controllers/post_controller.rb
|
191
|
+
class PostController < ActionController::Base
|
192
|
+
include Critic::Controller
|
193
|
+
|
194
|
+
protected
|
195
|
+
|
196
|
+
def policy(_resource)
|
197
|
+
V2::PostPolicy
|
198
|
+
end
|
199
|
+
end
|
200
|
+
```
|
201
|
+
|
202
|
+
You can also provide a specific policy when calling `authorize`
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
# app/controllers/post_controller.rb
|
206
|
+
class PostController < ActionController::Base
|
207
|
+
include Critic::Controller
|
208
|
+
|
209
|
+
def show
|
210
|
+
post = Post.find(params[:id])
|
211
|
+
authorize post, policy: V2::PostPolicy
|
212
|
+
|
213
|
+
render json: post
|
214
|
+
end
|
215
|
+
end
|
216
|
+
```
|
217
|
+
|
147
218
|
|
148
219
|
#### Testing
|
149
220
|
|
221
|
+
`bundle exec rake spec`
|
150
222
|
|
151
223
|
## Development
|
152
224
|
|
@@ -157,4 +229,3 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
157
229
|
## Contributing
|
158
230
|
|
159
231
|
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/critic.
|
160
|
-
|
data/critic.gemspec
CHANGED
@@ -18,10 +18,11 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.bindir = 'bin'
|
19
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ['lib']
|
21
|
+
spec.license = 'MIT'
|
21
22
|
|
22
23
|
spec.add_development_dependency 'bundler', '~> 1.10'
|
23
24
|
spec.add_development_dependency 'rake', '~> 10.0'
|
24
|
-
spec.add_development_dependency 'rspec'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 3.4'
|
25
26
|
|
26
|
-
spec.add_dependency 'activesupport', '> 3.0', '<
|
27
|
+
spec.add_dependency 'activesupport', '> 3.0', '< 6.0'
|
27
28
|
end
|
data/lib/critic/authorization.rb
CHANGED
data/lib/critic/callbacks.rb
CHANGED
@@ -58,10 +58,10 @@ module Critic::Callbacks
|
|
58
58
|
|
59
59
|
def _normalize_callback_option(options, from, to) # :nodoc:
|
60
60
|
from = options[from]
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
return unless from
|
62
|
+
|
63
|
+
from = Array(from).map { |o| "authorization.action.to_s == '#{o}'" }
|
64
|
+
options[to] = Array(options[to]).unshift(from).join(' || ')
|
65
65
|
end
|
66
66
|
|
67
67
|
# Skip before, after, and around action callbacks matching any of the names.
|
data/lib/critic/controller.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
# Sugar for accessing the authorization interface
|
2
3
|
module Critic::Controller
|
3
4
|
extend ActiveSupport::Concern
|
4
5
|
|
@@ -33,10 +34,10 @@ module Critic::Controller
|
|
33
34
|
authorize(scope, authorization_action, *args, policy: policy, **options)
|
34
35
|
end
|
35
36
|
|
36
|
-
protected
|
37
|
-
|
38
37
|
attr_reader :authorization
|
39
38
|
|
39
|
+
protected
|
40
|
+
|
40
41
|
def authorization_failed!
|
41
42
|
raise Critic::AuthorizationDenied, authorization
|
42
43
|
end
|
data/lib/critic/policy.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
# Represents the authorization policy interface
|
2
3
|
module Critic::Policy
|
3
4
|
extend ActiveSupport::Concern
|
4
5
|
|
@@ -39,21 +40,12 @@ module Critic::Policy
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
42
|
-
attr_reader :subject, :resource, :errors
|
43
|
-
attr_accessor :authorization
|
44
|
-
|
45
|
-
delegate :messages, :metadata, to: :authorization
|
46
|
-
|
47
43
|
def initialize(subject, resource)
|
48
44
|
@subject = subject
|
49
45
|
@resource = resource
|
50
46
|
@errors = []
|
51
47
|
end
|
52
48
|
|
53
|
-
def failure_message(action)
|
54
|
-
"#{subject} is not authorized to #{action} #{resource}"
|
55
|
-
end
|
56
|
-
|
57
49
|
def authorize(action, *args)
|
58
50
|
self.authorization = Critic::Authorization.new(self, action)
|
59
51
|
|
@@ -62,8 +54,8 @@ module Critic::Policy
|
|
62
54
|
authorization.result = result if authorization.result.nil?
|
63
55
|
|
64
56
|
case authorization.result
|
65
|
-
when Critic::Authorization
|
66
|
-
|
57
|
+
# when Critic::Authorization
|
58
|
+
# # user has accessed authorization directly
|
67
59
|
when String
|
68
60
|
authorization.granted = false
|
69
61
|
authorization.messages << result
|
@@ -77,8 +69,18 @@ module Critic::Policy
|
|
77
69
|
authorization
|
78
70
|
end
|
79
71
|
|
72
|
+
attr_accessor :authorization
|
73
|
+
|
80
74
|
protected
|
81
75
|
|
76
|
+
attr_reader :subject, :resource, :errors
|
77
|
+
|
78
|
+
delegate :messages, :metadata, to: :authorization
|
79
|
+
|
80
|
+
def failure_message(action)
|
81
|
+
"#{subject} is not authorized to #{action} #{resource}"
|
82
|
+
end
|
83
|
+
|
82
84
|
def halt(*response)
|
83
85
|
throw :halt, *response
|
84
86
|
end
|
data/lib/critic/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: critic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Lane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -42,16 +42,16 @@ dependencies:
|
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '3.4'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '3.4'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: activesupport
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -61,7 +61,7 @@ dependencies:
|
|
61
61
|
version: '3.0'
|
62
62
|
- - "<"
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
version: '
|
64
|
+
version: '6.0'
|
65
65
|
type: :runtime
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -71,7 +71,7 @@ dependencies:
|
|
71
71
|
version: '3.0'
|
72
72
|
- - "<"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '
|
74
|
+
version: '6.0'
|
75
75
|
description: Resource authorization via PORO
|
76
76
|
email:
|
77
77
|
- me@joshualane.com
|
@@ -85,7 +85,10 @@ files:
|
|
85
85
|
- ".rspec"
|
86
86
|
- ".rubocop.yml"
|
87
87
|
- ".travis.yml"
|
88
|
+
- Appraisals
|
89
|
+
- CHANGELOG.md
|
88
90
|
- Gemfile
|
91
|
+
- LICENSE.txt
|
89
92
|
- README.md
|
90
93
|
- Rakefile
|
91
94
|
- bin/console
|
@@ -99,7 +102,8 @@ files:
|
|
99
102
|
- lib/critic/policy.rb
|
100
103
|
- lib/critic/version.rb
|
101
104
|
homepage: http://lanej.io/critic
|
102
|
-
licenses:
|
105
|
+
licenses:
|
106
|
+
- MIT
|
103
107
|
metadata: {}
|
104
108
|
post_install_message:
|
105
109
|
rdoc_options: []
|
@@ -117,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
121
|
version: '0'
|
118
122
|
requirements: []
|
119
123
|
rubyforge_project:
|
120
|
-
rubygems_version: 2.5.
|
124
|
+
rubygems_version: 2.5.2
|
121
125
|
signing_key:
|
122
126
|
specification_version: 4
|
123
127
|
summary: Resource authorization
|