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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 49f7f09d33ece9e1d0f128c629d5963fbcf55c5b
4
- data.tar.gz: 7978825534fc7412ed65cba9a531b0733d331100
3
+ metadata.gz: fdf6a52e9cb60311ecce6e69f4ee02cf0505596a
4
+ data.tar.gz: 89a0bca5f2c35bbc1983a11fd5e76906abe517dc
5
5
  SHA512:
6
- metadata.gz: dd93e0ddda2bec80acf414af069344af29ee3ee287b1143d9bd7fff623bbf3bcdee6d2ca582665c8f9e60ccbbf4c6a3e223fb0414d4ec99bd840543864455ea0
7
- data.tar.gz: a499cccc078b3777bf4543266976eb0d1df26951fca5a4419b7c7b813a1bbcae279b7ac4c0a03c03b3c54f4230fcb67d8c0d163deb16e9162579adeef39cab20
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-18mode
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-18mode
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
- # In a real application, you would choose your llama class
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'
@@ -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
- authority_actions(overridden_actions(options))
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
- authority_action_map.merge!(overridden_actions(action_map))
55
- authority_action_map.merge!(action_map.symbolize_keys)
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
- def overridden_actions(options = {})
82
- if forced_action = options.fetch(:all_actions, false)
83
- overridden_actions = authority_action_map.inject({}) { |hash, (key, val)| hash.tap { |h| h[key] = forced_action } }
84
- end
85
- overridden_actions || options.fetch(:actions, {})
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 instance_authority_resource
136
+ authorize_action_for(*instance_authority_resource)
124
137
  end
125
138
 
126
139
  def instance_authority_resource
@@ -1,3 +1,3 @@
1
1
  module Authority
2
- VERSION = "2.9.0"
2
+ VERSION = "2.10.0"
3
3
  end
@@ -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 `authority_actions` method" do
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(:authority_actions).with(new_actions)
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
- before :each do
298
- controller_instance.stub(:method_to_find_class).and_return(resource_class)
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
- it "checks authorization on class returned by that method" do
302
- controller_instance.should_receive(:authorize_action_for).with(resource_class)
303
- controller_instance.send(:run_authorization_check)
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
@@ -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 options" do
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
- end
58
+ describe "when not given options" do
54
59
 
55
- describe "when not given options" do
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
- end
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
- it "doesn't raise a SecurityViolation if the action is authorized" do
69
- expect { Authority.enforce(:read, resource_class, user) }.not_to raise_error()
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.9.0
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: 2013-10-03 00:00:00.000000000 Z
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.3
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