authority 2.9.0 → 2.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/CHANGELOG.markdown +5 -0
- data/README.markdown +5 -3
- data/lib/authority.rb +25 -1
- data/lib/authority/controller.rb +22 -9
- data/lib/authority/version.rb +1 -1
- data/spec/authority/controller_spec.rb +31 -27
- data/spec/authority_spec.rb +31 -16
- metadata +12 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdf6a52e9cb60311ecce6e69f4ee02cf0505596a
|
4
|
+
data.tar.gz: 89a0bca5f2c35bbc1983a11fd5e76906abe517dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 232f1fa7a9aa66327c3ebc955d5a9b4132762f0d4e484a12c8731428034fc07533a138a76ec7795fb282283fd2476dd9a1480747ea8291c6786a9ec06d8fcbc1
|
7
|
+
data.tar.gz: ad56524c7282089b1bd2fd49f7bf5b76ccddc9fdd6ae1043a4394227978ceeb7e302022af1db47b988eea1e33fcf1e937af856b87677aeb3cf3f88f7184ca5cd
|
data/.travis.yml
CHANGED
@@ -4,10 +4,10 @@ rvm:
|
|
4
4
|
- 1.9.2
|
5
5
|
- 1.9.3
|
6
6
|
- 2.0.0
|
7
|
+
- 2.1.0
|
7
8
|
- jruby-18mode # JRuby in 1.8 mode
|
8
9
|
- jruby-19mode # JRuby in 1.9 mode
|
9
|
-
- rbx
|
10
|
-
- rbx-19mode
|
10
|
+
- rbx
|
11
11
|
|
12
12
|
gemfile:
|
13
13
|
- gemfiles/3.0.gemfile
|
@@ -23,5 +23,5 @@ matrix:
|
|
23
23
|
gemfile: gemfiles/4.0.gemfile
|
24
24
|
- rvm: jruby-18mode
|
25
25
|
gemfile: gemfiles/4.0.gemfile
|
26
|
-
- rvm: rbx
|
26
|
+
- rvm: rbx
|
27
27
|
gemfile: gemfiles/4.0.gemfile
|
data/CHANGELOG.markdown
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
Authority does its best to use [semantic versioning](http://semver.org).
|
4
4
|
|
5
|
+
## v2.10.0
|
6
|
+
|
7
|
+
- Ability to return options when looking up a class for `authorize_actions_for`, thanks to [Adam Milligan](https://github.com/orchardadam)
|
8
|
+
- Small refactor in controller code, thanks to [Stacey Touset](https://github.com/capicue)
|
9
|
+
|
5
10
|
## v2.9.0
|
6
11
|
|
7
12
|
Add `all_actions` option for `authorize_actions_for`, thanks to [Igor Davydov](https://github.com/div).
|
data/README.markdown
CHANGED
@@ -250,7 +250,7 @@ class ApplicationAuthorizer < Authority::Authorizer
|
|
250
250
|
|
251
251
|
protected
|
252
252
|
|
253
|
-
def has_role_granting(user, able)
|
253
|
+
def has_role_granting?(user, able)
|
254
254
|
# Does the user have any of the roles which give this permission?
|
255
255
|
(roles_which_grant(able) & user.roles).any?
|
256
256
|
end
|
@@ -390,9 +390,11 @@ class LlamasController < ApplicationController
|
|
390
390
|
authorize_actions_for :llama_class
|
391
391
|
|
392
392
|
def llama_class
|
393
|
-
#
|
394
|
-
# much more carefully
|
393
|
+
# This method can simply return a class...
|
395
394
|
[StandardLlama, LludicrousLlama].sample
|
395
|
+
|
396
|
+
# ... or an array with a class and some options
|
397
|
+
[OptionLladenLlama, {country: 'Peru'}]
|
396
398
|
end
|
397
399
|
end
|
398
400
|
```
|
data/lib/authority.rb
CHANGED
@@ -37,10 +37,10 @@ module Authority
|
|
37
37
|
unless action_authorized?(action, resource, user, options)
|
38
38
|
raise SecurityViolation.new(user, action, resource)
|
39
39
|
end
|
40
|
-
resource
|
41
40
|
end
|
42
41
|
|
43
42
|
def self.action_authorized?(action, resource, user, options = {})
|
43
|
+
raise MissingUser if user.nil?
|
44
44
|
resource_and_maybe_options = [resource, options].tap {|args| args.pop if args.last == {}}
|
45
45
|
user.send("can_#{action}?", *resource_and_maybe_options)
|
46
46
|
end
|
@@ -69,6 +69,30 @@ module Authority
|
|
69
69
|
require 'authority/user_abilities'
|
70
70
|
end
|
71
71
|
|
72
|
+
class MissingUser < StandardError
|
73
|
+
def message
|
74
|
+
"You tried to check authorization on `nil`. Authority doesn't know what
|
75
|
+
`nil` is allowed to do. There are two ways you can fix this.
|
76
|
+
|
77
|
+
1. Authenticate before authorizing. If the user isn't signed in, force
|
78
|
+
them to sign in before they can attempt any action that requires
|
79
|
+
authorization.
|
80
|
+
|
81
|
+
2. When the user is not signed in, return a Null Object instead of
|
82
|
+
`nil`. (You could create an AnonymousUser class, for example.) It should
|
83
|
+
respond to the normal methods Authority will call (like `can_delete?`),
|
84
|
+
possibly by including `Authority::UserAbilities` and teaching your authorizers
|
85
|
+
what an anonymous user can do.
|
86
|
+
|
87
|
+
The downside of solution #2 is that a user who forgot to sign in will be
|
88
|
+
told they are not authorized for an action they could normally do. This might
|
89
|
+
be confusing.
|
90
|
+
|
91
|
+
However, you might use both strategies in different parts of your application.
|
92
|
+
"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
72
96
|
end
|
73
97
|
|
74
98
|
require 'authority/configuration'
|
data/lib/authority/controller.rb
CHANGED
@@ -43,7 +43,8 @@ module Authority
|
|
43
43
|
# ones and any other options applicable to a before_filter
|
44
44
|
def authorize_actions_for(resource_or_finder, options = {})
|
45
45
|
self.authority_resource = resource_or_finder
|
46
|
-
|
46
|
+
add_actions(options.fetch(:actions, {}))
|
47
|
+
force_action(options[:all_actions]) if options[:all_actions]
|
47
48
|
before_filter :run_authorization_check, options
|
48
49
|
end
|
49
50
|
|
@@ -51,8 +52,9 @@ module Authority
|
|
51
52
|
#
|
52
53
|
# @param [Hash] action_map - controller actions and methods, to be merged with existing action_map
|
53
54
|
def authority_actions(action_map)
|
54
|
-
|
55
|
-
|
55
|
+
forced_action = action_map.delete(:all_actions)
|
56
|
+
add_actions(action_map)
|
57
|
+
force_action(forced_action) if forced_action
|
56
58
|
end
|
57
59
|
|
58
60
|
def authority_action(action_map)
|
@@ -78,13 +80,24 @@ module Authority
|
|
78
80
|
@authority_action_map ||= Authority.configuration.controller_action_map.dup
|
79
81
|
end
|
80
82
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
83
|
+
# Adds the passed in actions to the current action map.
|
84
|
+
#
|
85
|
+
# @param [Hash] action_map - controller actions and methods to be merged
|
86
|
+
# with the existing action map
|
87
|
+
def add_actions(action_map)
|
88
|
+
authority_action_map.merge!(action_map)
|
86
89
|
end
|
87
90
|
|
91
|
+
# Updates the current action map to use the forced action for all of it's
|
92
|
+
# actions.
|
93
|
+
#
|
94
|
+
# @param [String OR Symbol] forced_action - the authority action to use
|
95
|
+
# for all Rails actions in the action map
|
96
|
+
def force_action(forced_action)
|
97
|
+
add_actions(
|
98
|
+
Hash[authority_action_map.map {|key, _| [key, forced_action] }]
|
99
|
+
)
|
100
|
+
end
|
88
101
|
end
|
89
102
|
|
90
103
|
protected
|
@@ -120,7 +133,7 @@ module Authority
|
|
120
133
|
# The `before_filter` that will be setup to run when the class method
|
121
134
|
# `authorize_actions_for` is called
|
122
135
|
def run_authorization_check
|
123
|
-
authorize_action_for
|
136
|
+
authorize_action_for(*instance_authority_resource)
|
124
137
|
end
|
125
138
|
|
126
139
|
def instance_authority_resource
|
data/lib/authority/version.rb
CHANGED
@@ -109,16 +109,24 @@ describe Authority::Controller do
|
|
109
109
|
it "if :all_actions option is given, it overrides the action hash to use the action given" do
|
110
110
|
overridden_action_map = controller_class.authority_action_map
|
111
111
|
overridden_action_map.update(overridden_action_map) {|k,v| v = :annihilate}
|
112
|
-
child_controller.should_receive(:authority_actions).with(overridden_action_map)
|
113
112
|
child_controller.authorize_actions_for(resource_class, :all_actions => :annihilate)
|
113
|
+
child_controller.authority_action_map.should eq(overridden_action_map)
|
114
114
|
end
|
115
115
|
|
116
|
-
it "passes the action hash to the `
|
116
|
+
it "passes the action hash to the `add_actions` method" do
|
117
117
|
new_actions = {:synthesize => :create, :annihilate => 'delete'}
|
118
|
-
child_controller.should_receive(:
|
118
|
+
child_controller.should_receive(:add_actions).with(new_actions)
|
119
119
|
child_controller.authorize_actions_for(resource_class, :actions => new_actions)
|
120
120
|
end
|
121
121
|
|
122
|
+
it "updates the action map if :actions option is given" do
|
123
|
+
updated_map = child_controller.authority_action_map
|
124
|
+
updated_map[:synthesize] = :create
|
125
|
+
new_actions = {:synthesize => :create}
|
126
|
+
child_controller.authorize_actions_for(resource_class, :actions => new_actions)
|
127
|
+
expect(child_controller.authority_action_map).to eq(updated_map)
|
128
|
+
end
|
129
|
+
|
122
130
|
end
|
123
131
|
|
124
132
|
describe "authority_resource" do
|
@@ -178,25 +186,6 @@ describe Authority::Controller do
|
|
178
186
|
|
179
187
|
end
|
180
188
|
|
181
|
-
describe "overridden_actions" do
|
182
|
-
|
183
|
-
it "overrides authority action map if option :all_actions is present" do
|
184
|
-
options = { :all_actions => :display, :actions => {:show => :display, :synthesize => :create} }
|
185
|
-
expect(controller_class.overridden_actions(options).values.uniq).to eq([:display])
|
186
|
-
end
|
187
|
-
|
188
|
-
it "returns :actions hash if option :all_actions is not present" do
|
189
|
-
options = { :actions => {:show => :display, :synthesize => :create, :annihilate => 'delete'} }
|
190
|
-
expect(controller_class.overridden_actions(options)).to eq(options[:actions])
|
191
|
-
end
|
192
|
-
|
193
|
-
it "returns an empty hash if no :all_actions nor :actions options present" do
|
194
|
-
options = { :show => :display, :synthesize => :create, :annihilate => 'delete' }
|
195
|
-
expect(controller_class.overridden_actions(options)).to eq({})
|
196
|
-
end
|
197
|
-
|
198
|
-
end
|
199
|
-
|
200
189
|
describe "ensure_authorization_performed" do
|
201
190
|
|
202
191
|
let(:controller_instance) { controller_class.new }
|
@@ -294,13 +283,28 @@ describe Authority::Controller do
|
|
294
283
|
|
295
284
|
context "if the controller has such an instance method" do
|
296
285
|
|
297
|
-
|
298
|
-
|
286
|
+
context "and the method returns a class" do
|
287
|
+
before :each do
|
288
|
+
controller_instance.stub(:method_to_find_class).and_return(resource_class)
|
289
|
+
end
|
290
|
+
|
291
|
+
it "checks authorization on that class" do
|
292
|
+
controller_instance.should_receive(:authorize_action_for).with(resource_class)
|
293
|
+
controller_instance.send(:run_authorization_check)
|
294
|
+
end
|
299
295
|
end
|
300
296
|
|
301
|
-
|
302
|
-
|
303
|
-
|
297
|
+
context "and the method returns an array containing a class and some options" do
|
298
|
+
let(:some_options) { { :a => 1, :b => 2 } }
|
299
|
+
|
300
|
+
before :each do
|
301
|
+
controller_instance.stub(:method_to_find_class).and_return([resource_class, some_options])
|
302
|
+
end
|
303
|
+
|
304
|
+
it "checks authorization on that class and passes the options" do
|
305
|
+
controller_instance.should_receive(:authorize_action_for).with(resource_class, some_options)
|
306
|
+
controller_instance.send(:run_authorization_check)
|
307
|
+
end
|
304
308
|
end
|
305
309
|
|
306
310
|
end
|
data/spec/authority_spec.rb
CHANGED
@@ -39,34 +39,49 @@ describe Authority do
|
|
39
39
|
|
40
40
|
describe "enforcement" do
|
41
41
|
|
42
|
-
let(:user) { ExampleUser.new }
|
43
42
|
let(:resource_class) { ExampleResource }
|
44
43
|
|
45
|
-
describe "when given
|
44
|
+
describe "when given a user object" do
|
45
|
+
|
46
|
+
let(:user) { ExampleUser.new }
|
47
|
+
|
48
|
+
describe "when given options" do
|
49
|
+
|
50
|
+
it "checks the user's authorization, passing along the options" do
|
51
|
+
options = { :for => 'context' }
|
52
|
+
user.should_receive(:can_delete?).with(resource_class, options).and_return(true)
|
53
|
+
Authority.enforce(:delete, resource_class, user, options)
|
54
|
+
end
|
46
55
|
|
47
|
-
it "checks the user's authorization, passing along the options" do
|
48
|
-
options = { :for => 'context' }
|
49
|
-
user.should_receive(:can_delete?).with(resource_class, options).and_return(true)
|
50
|
-
Authority.enforce(:delete, resource_class, user, options)
|
51
56
|
end
|
52
57
|
|
53
|
-
|
58
|
+
describe "when not given options" do
|
54
59
|
|
55
|
-
|
60
|
+
it "checks the user's authorization, passing no options" do
|
61
|
+
user.should_receive(:can_delete?).with(resource_class).and_return(true)
|
62
|
+
Authority.enforce(:delete, resource_class, user)
|
63
|
+
end
|
56
64
|
|
57
|
-
it "checks the user's authorization, passing no options" do
|
58
|
-
user.should_receive(:can_delete?).with(resource_class).and_return(true)
|
59
|
-
Authority.enforce(:delete, resource_class, user)
|
60
65
|
end
|
61
66
|
|
62
|
-
|
67
|
+
it "raises a SecurityViolation if the action is unauthorized" do
|
68
|
+
expect { Authority.enforce(:update, resource_class, user) }.to raise_error(Authority::SecurityViolation)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "doesn't raise a SecurityViolation if the action is authorized" do
|
72
|
+
expect { Authority.enforce(:read, resource_class, user) }.not_to raise_error()
|
73
|
+
end
|
63
74
|
|
64
|
-
it "raises a SecurityViolation if the action is unauthorized" do
|
65
|
-
expect { Authority.enforce(:update, resource_class, user) }.to raise_error(Authority::SecurityViolation)
|
66
75
|
end
|
67
76
|
|
68
|
-
|
69
|
-
|
77
|
+
describe "when given a nil user" do
|
78
|
+
|
79
|
+
let(:user) { nil }
|
80
|
+
|
81
|
+
it "raises a helpful error" do
|
82
|
+
expect { Authority.enforce(:update, resource_class, user) }.to raise_error(Authority::MissingUser)
|
83
|
+
end
|
84
|
+
|
70
85
|
end
|
71
86
|
|
72
87
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authority
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Long
|
@@ -9,34 +9,34 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-04-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- -
|
18
|
+
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: 3.0.0
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- -
|
25
|
+
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: 3.0.0
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: rake
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- -
|
32
|
+
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: 0.8.7
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- -
|
39
|
+
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: 0.8.7
|
42
42
|
description: Authority helps you authorize actions in your Rails app. It's ORM-neutral
|
@@ -49,9 +49,9 @@ executables: []
|
|
49
49
|
extensions: []
|
50
50
|
extra_rdoc_files: []
|
51
51
|
files:
|
52
|
-
- .gitignore
|
53
|
-
- .rspec
|
54
|
-
- .travis.yml
|
52
|
+
- ".gitignore"
|
53
|
+
- ".rspec"
|
54
|
+
- ".travis.yml"
|
55
55
|
- CHANGELOG.markdown
|
56
56
|
- CONTRIBUTING.markdown
|
57
57
|
- Gemfile
|
@@ -97,17 +97,17 @@ require_paths:
|
|
97
97
|
- lib
|
98
98
|
required_ruby_version: !ruby/object:Gem::Requirement
|
99
99
|
requirements:
|
100
|
-
- -
|
100
|
+
- - ">="
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '0'
|
103
103
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
104
|
requirements:
|
105
|
-
- -
|
105
|
+
- - ">="
|
106
106
|
- !ruby/object:Gem::Version
|
107
107
|
version: '0'
|
108
108
|
requirements: []
|
109
109
|
rubyforge_project:
|
110
|
-
rubygems_version: 2.0
|
110
|
+
rubygems_version: 2.2.0
|
111
111
|
signing_key:
|
112
112
|
specification_version: 4
|
113
113
|
summary: Authority helps you authorize actions in your Rails app using plain Ruby
|