authority 2.9.0 → 2.10.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 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