authority 3.0.0 → 3.1.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: ccacc3926200ff8ab74076d17004787bd6cd07a6
4
- data.tar.gz: 53db25b0cd740840535c40f0021603276874dd79
3
+ metadata.gz: 5d278f4f1f1672058635b280ec7a87a157c524a8
4
+ data.tar.gz: 8a71e78e7f76f8ae5a3d54c8dc16f1017c2bc6a6
5
5
  SHA512:
6
- metadata.gz: c5613d4189de8606773858b417a34c29f1ce894705a65a133692251f8d01882d9cff1711ef95e9861b9d9d86a15a519f072e9d98a296540d600c70d6251db2ce
7
- data.tar.gz: 59e4493c297af171339c56509808329be8dc5af60aa274cabbe033dc58eb6eb466b1cdfa6d02cb5cfb4683e432fab0c848c8918f0d1eb418bafff4924cbba2e1
6
+ metadata.gz: 9df1e4d9c065a21bb73555fa4839830b3407cd62603e0af3fd3c2532623c0d9744dba517e38578b62ad26e8b80fd310ba353e5e2c29bb639d08e0d5717282e5e
7
+ data.tar.gz: aa3af216a21af0d250831dcf643c8f171fa64b31a5cd374270693701dc5d98eb71527675f832bfd0f440a8a8f5c6a71ef5733cde22cd3e92bd0d1c5bd3c23a5a
@@ -1,15 +1,17 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- - 2.0.0
5
- - 2.1.0
4
+ - 2.0
5
+ - 2.1
6
+ - 2.2
6
7
  - jruby-19mode # JRuby in 1.9 mode
7
- - rbx
8
+ - rbx-2
8
9
 
9
10
  gemfile:
10
11
  - gemfiles/3.2.gemfile
11
12
  - gemfiles/4.0.gemfile
12
13
  - gemfiles/4.1.gemfile
14
+ - gemfiles/4.2.gemfile
13
15
 
14
16
  matrix:
15
17
  exclude:
@@ -2,6 +2,16 @@
2
2
 
3
3
  Authority does its best to use [semantic versioning](http://semver.org).
4
4
 
5
+ ## Unreleased
6
+
7
+ Nothing
8
+
9
+ ## 3.1.0
10
+
11
+ - Allow changing the logger by updating the configuration (see commit 0214d24), based on [a question](https://github.com/nathanl/authority/issues/101) from [Nate Bird](https://github.com/natebird)
12
+ - Authorizers can now have an instance default method (`def default`), thanks to [Pascal Friederich](https://github.com/paukul)
13
+ - Fix "wrong number of arguments" bug for Sequel users, reported by [Sebastian Porto](https://github.com/sporto) in [Issue 100](https://github.com/nathanl/authority/issues/100)
14
+
5
15
  ## v3.0.0
6
16
 
7
17
  Officially drop support for Ruby < 1.9.3 and Rails < 3.2.
data/Gemfile CHANGED
@@ -2,5 +2,3 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in authority.gemspec
4
4
  gemspec
5
-
6
- gem 'rspec', '>= 2.12.0'
@@ -10,6 +10,7 @@ If you're using it with Rails controllers, it requires that you already have som
10
10
  [![Build Status](https://secure.travis-ci.org/nathanl/authority.png?branch=master)](http://travis-ci.org/nathanl/authority)
11
11
  [![Code Climate](https://codeclimate.com/github/nathanl/authority.png)](https://codeclimate.com/github/nathanl/authority)
12
12
  [![Dependency Status](https://gemnasium.com/nathanl/authority.png)](https://gemnasium.com/nathanl/authority)
13
+ [![Join the chat at https://gitter.im/nathanl/authority](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/nathanl/authority?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
13
14
 
14
15
  ## Contents
15
16
 
@@ -121,6 +122,8 @@ The authorization process generally flows like this:
121
122
 
122
123
  If the answer is `false` and the original caller was a controller, this is treated as a `SecurityViolation`. If it was a view, maybe you just don't show a link.
123
124
 
125
+ The authorization process for instances is different in that it calls the instance's `default` method before calling the class `default` method. This allows you to define default behaviour that requires access to the model instance to be determined (eg, assume any action on a blog post is allowed if that post is marked 'wiki').
126
+
124
127
  (Diagrams made with [AsciiFlow](http://asciiflow.com))
125
128
 
126
129
  <a name="installation">
@@ -169,7 +172,8 @@ class Article
169
172
  # Adds `creatable_by?(user)`, etc
170
173
  include Authority::Abilities
171
174
 
172
- # Without this, 'ApplicationAuthorizer' is assumed
175
+ # Without this, 'ArticleAuthorizer' is assumed;
176
+ # if that doesn't exist, 'ApplicationAuthorizer'
173
177
  self.authorizer_name = 'AdminAuthorizer'
174
178
  ...
175
179
  end
@@ -279,12 +283,12 @@ describe AdminAuthorizer do
279
283
  end
280
284
 
281
285
  describe "class" do
282
- it "lets admins update in bulk" do
283
- expect(AdminAuthorizer).to be_bulk_updatable_by(@admin)
286
+ it "lets admins update" do
287
+ expect(AdminAuthorizer).to be_updatable_by(@admin)
284
288
  end
285
289
 
286
- it "doesn't let users update in bulk" do
287
- expect(AdminAuthorizer).not_to be_bulk_updatable_by(@user)
290
+ it "doesn't let users update" do
291
+ expect(AdminAuthorizer).not_to be_updatable_by(@user)
288
292
  end
289
293
  end
290
294
 
@@ -313,12 +317,14 @@ end
313
317
 
314
318
  If you're using Rails, ActionController support will be loaded in through a Railtie. Otherwise, you'll want to integrate it into your framework yourself. [Authority's controller](https://github.com/nathanl/authority/blob/master/lib/authority/controller.rb) is an excellent starting point.
315
319
 
316
- Anytime a controller finds a user attempting something they're not authorized to do, a [Security Violation](#security_violations_and_logging) will result. Controllers get two ways to check authorization:
320
+ You can check authorization in your controllers in one of two ways:
317
321
 
318
322
  - `authorize_actions_for Llama` protects multiple controller actions with a `before_filter`, which performs a **class-level** check. If the current user is never allowed to delete a `Llama`, they'll never even get to the controller's `destroy` method.
319
323
  - `authorize_action_for @llama` can be called inside a single controller action, and performs an **instance-level** check. If called inside `update`, it will check whether the current user is allowed to update this particular `@llama` instance.
320
324
 
321
- How does Authority know to check `deletable_by?` before the controller's `destroy` action? It checks your configuration. These mappings are configurable globally from the initializer file. Defaults are as follows:
325
+ If either method finds a user attempting something they're not authorized to do, a [Security Violation](#security_violations_and_logging) will result.
326
+
327
+ How does `authorize_actions_for` know to check `deletable_by?` before the controller's `destroy` action? It checks your configuration. These mappings are configurable globally from the initializer file. Defaults are as follows:
322
328
 
323
329
  ```ruby
324
330
  config.controller_action_map = {
@@ -12,6 +12,8 @@ Gem::Specification.new do |gem|
12
12
  gem.add_dependency "activesupport", ">= 3.0.0"
13
13
  gem.add_dependency "rake", ">= 0.8.7"
14
14
 
15
+ gem.add_development_dependency "rspec", "~> 3.3.0"
16
+
15
17
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
18
  gem.files = `git ls-files`.split("\n")
17
19
  gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -1,6 +1,6 @@
1
- source "http://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- gem "rails", "~> 3.2.3"
4
- gem 'rspec', '>= 2.8.0'
3
+ gem 'rails', '~> 3.2.3'
4
+ gem 'rspec', '~> 2.14.0'
5
5
 
6
- gemspec :path=>"../"
6
+ gemspec path: '../'
@@ -1,6 +1,6 @@
1
- source "http://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- gem "rails", "~> 4.0"
4
- gem 'rspec', '~> 2.14'
3
+ gem 'rails', '~> 4.0.0'
4
+ gem 'rspec', '~> 2.14.0'
5
5
 
6
- gemspec :path=>"../"
6
+ gemspec path: '../'
@@ -1,6 +1,6 @@
1
- source "http://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- gem "rails", "~> 4.1"
4
- gem 'rspec', '~> 2.14'
3
+ gem 'rails', '~> 4.1.0'
4
+ gem 'rspec', '~> 2.14.0'
5
5
 
6
- gemspec :path=>"../"
6
+ gemspec path: '../'
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rails', '~> 4.2.0'
4
+ gem 'rspec', '~> 2.14.0'
5
+
6
+ gemspec path: '../'
@@ -58,7 +58,7 @@ module Authority
58
58
  end
59
59
 
60
60
  def self.logger
61
- @logger ||= configuration.logger
61
+ configuration.logger
62
62
  end
63
63
 
64
64
  private
@@ -1,7 +1,5 @@
1
1
  module Authority
2
2
  class Authorizer
3
- extend Forwardable
4
-
5
3
  # The base Authorizer class, from which all the authorizers in an app will
6
4
  # descend. Provides the authorizer with both class and instance methods
7
5
  # like `updatable_by?(user)`.
@@ -20,21 +18,30 @@ module Authority
20
18
  false
21
19
  end
22
20
 
23
- # Each instance method simply calls the corresponding class method
24
- Authority.adjectives.each do |adjective|
25
- def_delegator :"self.class", :"#{adjective}_by?"
21
+ # the instance default method calls the class default method
22
+ def default(adjective, user, options = {})
23
+ user_and_maybe_options = self.class.send(:user_and_maybe_options, user, options)
24
+ self.class.send(:"#{adjective}_by?", *user_and_maybe_options)
26
25
  end
27
26
 
28
- # Each class method simply calls the `default` method
27
+ # Each method simply calls the `default` method (instance or class)
29
28
  Authority.adjectives.each do |adjective|
30
29
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
31
30
  def self.#{adjective}_by?(user, options = {})
32
- user_and_maybe_options = [user, options].tap {|args| args.pop if args.last == {}}
31
+ default(:#{adjective}, *user_and_maybe_options(user, options))
32
+ end
33
+
34
+ def #{adjective}_by?(user, options = {})
35
+ user_and_maybe_options = self.class.send(:user_and_maybe_options, user, options)
33
36
  default(:#{adjective}, *user_and_maybe_options)
34
37
  end
35
38
  RUBY
36
39
  end
37
40
 
41
+ def self.user_and_maybe_options(user, options = {})
42
+ [user, options].tap {|args| args.pop if args.last == {}}
43
+ end
44
+ private_class_method :user_and_maybe_options
38
45
  end
39
46
 
40
47
  class NoAuthorizerError < StandardError ; end
@@ -133,12 +133,21 @@ module Authority
133
133
  # The `before_filter` that will be setup to run when the class method
134
134
  # `authorize_actions_for` is called
135
135
  def run_authorization_check
136
- authorize_action_for(*instance_authority_resource)
136
+ if instance_authority_resource.is_a?(Array)
137
+ # Array includes options; pass as separate args
138
+ authorize_action_for(*instance_authority_resource)
139
+ else
140
+ # *resource would be interpreted as resource.to_a, which is wrong and
141
+ # actually triggers a query if it's a Sequel model
142
+ authorize_action_for(instance_authority_resource)
143
+ end
137
144
  end
138
145
 
139
146
  def instance_authority_resource
140
- return self.class.authority_resource if self.class.authority_resource.is_a?(Class)
141
- send(self.class.authority_resource)
147
+ case self.class.authority_resource
148
+ when Class then self.class.authority_resource
149
+ when String, Symbol then send(self.class.authority_resource)
150
+ end
142
151
  rescue NoMethodError
143
152
  raise MissingResource.new(
144
153
  "Trying to authorize actions for '#{self.class.authority_resource}', but can't. \
@@ -1,3 +1,3 @@
1
1
  module Authority
2
- VERSION = "3.0.0"
2
+ VERSION = "3.1.0"
3
3
  end
@@ -71,13 +71,13 @@ describe Authority::Abilities do
71
71
 
72
72
  it "constantizes the authorizer name as the authorizer" do
73
73
  resource_class.instance_variable_set(:@authorizer, nil)
74
- resource_class.authorizer_name.should_receive(:constantize)
74
+ expect(resource_class.authorizer_name).to receive(:constantize)
75
75
  resource_class.authorizer
76
76
  end
77
77
 
78
78
  it "memoizes the authorizer to avoid reconstantizing" do
79
79
  resource_class.authorizer
80
- resource_class.authorizer_name.should_not_receive(:constantize)
80
+ expect(resource_class.authorizer_name).not_to receive(:constantize)
81
81
  resource_class.authorizer
82
82
  end
83
83
 
@@ -106,7 +106,7 @@ describe Authority::Abilities do
106
106
  context "when given an options hash" do
107
107
 
108
108
  it "delegates `#{method_name}` to its authorizer class, passing the options" do
109
- resource_class.authorizer.should_receive(method_name).with(user, :lacking => 'nothing')
109
+ expect(resource_class.authorizer).to receive(method_name).with(user, :lacking => 'nothing')
110
110
  resource_class.send(method_name, user, :lacking => 'nothing')
111
111
  end
112
112
 
@@ -115,7 +115,7 @@ describe Authority::Abilities do
115
115
  context "when not given an options hash" do
116
116
 
117
117
  it "delegates `#{method_name}` to its authorizer class, passing no options" do
118
- resource_class.authorizer.should_receive(method_name).with(user)
118
+ expect(resource_class.authorizer).to receive(method_name).with(user)
119
119
  resource_class.send(method_name, user)
120
120
  end
121
121
 
@@ -147,8 +147,8 @@ describe Authority::Abilities do
147
147
  context "when given an options hash" do
148
148
 
149
149
  it "delegates `#{method_name}` to a new authorizer instance, passing the options" do
150
- resource_class.authorizer.stub(:new).and_return(@authorizer)
151
- @authorizer.should_receive(method_name).with(user, :with => 'mayo')
150
+ allow(resource_class.authorizer).to receive(:new).and_return(@authorizer)
151
+ expect(@authorizer).to receive(method_name).with(user, :with => 'mayo')
152
152
  resource_instance.send(method_name, user, :with => 'mayo')
153
153
  end
154
154
 
@@ -157,8 +157,8 @@ describe Authority::Abilities do
157
157
  context "when not given an options hash" do
158
158
 
159
159
  it "delegates `#{method_name}` to a new authorizer instance, passing no options" do
160
- resource_class.authorizer.stub(:new).and_return(@authorizer)
161
- @authorizer.should_receive(method_name).with(user)
160
+ allow(resource_class.authorizer).to receive(:new).and_return(@authorizer)
161
+ expect(@authorizer).to receive(method_name).with(user)
162
162
  resource_instance.send(method_name, user)
163
163
  end
164
164
 
@@ -176,7 +176,7 @@ describe Authority::Abilities do
176
176
  # instance of the authorizer. Otherwise, you might check, make a change to the
177
177
  # model instance, check again, and get an outdated answer.
178
178
  it "always creates a new authorizer instance when accessing the authorizer" do
179
- resource_instance.class.authorizer.should_receive(:new).with(resource_instance).twice
179
+ expect(resource_instance.class.authorizer).to receive(:new).with(resource_instance).twice
180
180
  2.times { resource_instance.authorizer }
181
181
  end
182
182
 
@@ -13,6 +13,20 @@ describe Authority::Authorizer do
13
13
 
14
14
  describe "instance methods" do
15
15
 
16
+ it "calls the instance default method if no instance method is defined" do
17
+ expect(authorizer).to receive(:default)
18
+ authorizer.creatable_by?(user)
19
+ end
20
+
21
+ context "the instance default method" do
22
+
23
+ it "delegates to the class default method" do
24
+ expect(authorizer.class).to receive(:default)
25
+ authorizer.default(:creatable, user)
26
+ end
27
+
28
+ end
29
+
16
30
  Authority.adjectives.each do |adjective|
17
31
  method_name = "#{adjective}_by?"
18
32
 
@@ -25,7 +39,7 @@ describe Authority::Authorizer do
25
39
  context "when given an options hash" do
26
40
 
27
41
  it "delegates `#{method_name}` to the corresponding class method, passing the options" do
28
- authorizer.class.should_receive(method_name).with(user, :under => 'God')
42
+ expect(authorizer.class).to receive(method_name).with(user, :under => 'God')
29
43
  authorizer.send(method_name, user, :under => 'God')
30
44
  end
31
45
 
@@ -34,7 +48,7 @@ describe Authority::Authorizer do
34
48
  context "when not given an options hash" do
35
49
 
36
50
  it "delegates `#{method_name}` to the corresponding class method, passing no options" do
37
- authorizer.class.should_receive(method_name).with(user)
51
+ expect(authorizer.class).to receive(method_name).with(user)
38
52
  authorizer.send(method_name, user)
39
53
  end
40
54
 
@@ -61,7 +75,7 @@ describe Authority::Authorizer do
61
75
 
62
76
  it "delegates `#{method_name}` to the authorizer's `default` method, passing the options" do
63
77
  able = method_name.sub('_by?', '').to_sym
64
- Authority::Authorizer.should_receive(:default).with(able, user, :with => 'gusto')
78
+ expect(Authority::Authorizer).to receive(:default).with(able, user, :with => 'gusto')
65
79
  Authority::Authorizer.send(method_name, user, :with => 'gusto')
66
80
  end
67
81
 
@@ -71,7 +85,7 @@ describe Authority::Authorizer do
71
85
 
72
86
  it "delegates `#{method_name}` to the authorizer's `default` method, passing no options" do
73
87
  able = method_name.sub('_by?', '').to_sym
74
- Authority::Authorizer.should_receive(:default).with(able, user)
88
+ expect(Authority::Authorizer).to receive(:default).with(able, user)
75
89
  Authority::Authorizer.send(method_name, user)
76
90
  end
77
91
 
@@ -88,14 +102,14 @@ describe Authority::Authorizer do
88
102
  context "when given an options hash" do
89
103
 
90
104
  it "returns false" do
91
- expect(Authority::Authorizer.default(:implodable, user, {:for => "my_object"})).to be_false
105
+ expect(Authority::Authorizer.default(:implodable, user, {:for => "my_object"})).to eq(false)
92
106
  end
93
107
  end
94
108
 
95
109
  context "when not given an options hash" do
96
110
 
97
111
  it "returns false" do
98
- expect(Authority::Authorizer.default(:implodable, user)).to be_false
112
+ expect(Authority::Authorizer.default(:implodable, user)).to eq(false)
99
113
  end
100
114
 
101
115
  end
@@ -17,7 +17,7 @@ describe Authority::Configuration do
17
17
  Authority.instance_variable_set :@configuration, nil
18
18
  null = File.exists?('/dev/null') ? '/dev/null' : 'NUL:' # Allow for Windows
19
19
  logger = Logger.new(null)
20
- Logger.should_receive(:new).with(STDERR).and_return(logger)
20
+ expect(Logger).to receive(:new).with(STDERR).and_return(logger)
21
21
  Authority.configure
22
22
  Authority.logger
23
23
  end
@@ -16,7 +16,7 @@ describe Authority::Controller do
16
16
  context "when including" do
17
17
 
18
18
  before :each do
19
- Authority::Controller.stub(:security_violation_callback).and_return(Proc.new {|exception| })
19
+ allow(Authority::Controller).to receive(:security_violation_callback).and_return(Proc.new {|exception| })
20
20
  end
21
21
 
22
22
  after :each do
@@ -24,7 +24,7 @@ describe Authority::Controller do
24
24
  end
25
25
 
26
26
  it "specifies rescuing security violations with a standard callback" do
27
- controller_class.should_receive(:rescue_from).with(
27
+ expect(controller_class).to receive(:rescue_from).with(
28
28
  Authority::SecurityViolation, :with => Authority::Controller.security_violation_callback
29
29
  )
30
30
  end
@@ -55,7 +55,7 @@ describe Authority::Controller do
55
55
  # this test, so I'm stealing that behavior.
56
56
 
57
57
  Authority.configuration.security_violation_handler = :fire_ze_missiles
58
- controller_instance.should_receive(:fire_ze_missiles).with(fake_exception)
58
+ expect(controller_instance).to receive(:fire_ze_missiles).with(fake_exception)
59
59
  controller_instance.instance_exec(fake_exception, &Authority::Controller.security_violation_callback)
60
60
 
61
61
  end
@@ -101,7 +101,7 @@ describe Authority::Controller do
101
101
 
102
102
  it "sets up a before_filter, passing the options it was given" do
103
103
  filter_options = {:only => [:show, :edit, :update]}
104
- controller_class.should_receive(:before_filter).with(:run_authorization_check, filter_options)
104
+ expect(controller_class).to receive(:before_filter).with(:run_authorization_check, filter_options)
105
105
  controller_class.authorize_actions_for(resource_class, filter_options)
106
106
  end
107
107
 
@@ -109,12 +109,12 @@ describe Authority::Controller do
109
109
  overridden_action_map = controller_class.authority_action_map
110
110
  overridden_action_map.update(overridden_action_map) {|k,v| v = :annihilate}
111
111
  child_controller.authorize_actions_for(resource_class, :all_actions => :annihilate)
112
- child_controller.authority_action_map.should eq(overridden_action_map)
112
+ expect(child_controller.authority_action_map).to eq(overridden_action_map)
113
113
  end
114
114
 
115
115
  it "passes the action hash to the `add_actions` method" do
116
116
  new_actions = {:synthesize => :create, :annihilate => 'delete'}
117
- child_controller.should_receive(:add_actions).with(new_actions)
117
+ expect(child_controller).to receive(:add_actions).with(new_actions)
118
118
  child_controller.authorize_actions_for(resource_class, :actions => new_actions)
119
119
  end
120
120
 
@@ -190,52 +190,52 @@ describe Authority::Controller do
190
190
  let(:controller_instance) { controller_class.new }
191
191
 
192
192
  before(:each) do
193
- controller_instance.stub(:class).and_return("FooController")
194
- controller_instance.stub(:action_name).and_return(:bar)
193
+ allow(controller_instance).to receive(:class).and_return("FooController")
194
+ allow(controller_instance).to receive(:action_name).and_return(:bar)
195
195
  end
196
196
 
197
197
  it "sets up an after_filter, passing the options it was given" do
198
198
  filter_options = {:only => [:show, :edit, :update]}
199
- controller_class.should_receive(:after_filter).with(filter_options)
199
+ expect(controller_class).to receive(:after_filter).with(filter_options)
200
200
  controller_class.ensure_authorization_performed(filter_options)
201
201
  end
202
202
 
203
203
  it "triggers AuthorizationNotPerformed in after filter" do
204
- controller_class.stub(:after_filter).and_yield(controller_instance)
205
- lambda {
204
+ allow(controller_class).to receive(:after_filter).and_yield(controller_instance)
205
+ expect {
206
206
  controller_class.ensure_authorization_performed
207
- }.should raise_error(Authority::Controller::AuthorizationNotPerformed)
207
+ }.to raise_error(Authority::Controller::AuthorizationNotPerformed)
208
208
  end
209
209
 
210
210
  it "AuthorizationNotPerformed error has meaningful message" do
211
- controller_class.stub(:after_filter).and_yield(controller_instance)
212
- lambda {
211
+ allow(controller_class).to receive(:after_filter).and_yield(controller_instance)
212
+ expect {
213
213
  controller_class.ensure_authorization_performed
214
- }.should raise_error("No authorization was performed for FooController#bar")
214
+ }.to raise_error("No authorization was performed for FooController#bar")
215
215
  end
216
216
 
217
217
  it "does not trigger AuthorizationNotPerformed when :if is false" do
218
- controller_instance.stub(:authorize?) { false }
219
- controller_class.stub(:after_filter).with({}).and_yield(controller_instance)
220
- lambda {
218
+ allow(controller_instance).to receive(:authorize?) { false }
219
+ allow(controller_class).to receive(:after_filter).with({}).and_yield(controller_instance)
220
+ expect {
221
221
  controller_class.ensure_authorization_performed(:if => :authorize?)
222
- }.should_not raise_error()
222
+ }.not_to raise_error()
223
223
  end
224
224
 
225
225
  it "does not trigger AuthorizationNotPerformed when :unless is true" do
226
- controller_instance.stub(:skip_authorization?) { true }
227
- controller_class.stub(:after_filter).with({}).and_yield(controller_instance)
228
- lambda {
226
+ allow(controller_instance).to receive(:skip_authorization?) { true }
227
+ allow(controller_class).to receive(:after_filter).with({}).and_yield(controller_instance)
228
+ expect {
229
229
  controller_class.ensure_authorization_performed(:unless => :skip_authorization?)
230
- }.should_not raise_error()
230
+ }.not_to raise_error()
231
231
  end
232
232
 
233
233
  it "does not raise error when #authorization_performed is true" do
234
234
  controller_instance.authorization_performed = true
235
- controller_class.stub(:after_filter).with({}).and_yield(controller_instance)
236
- lambda {
235
+ allow(controller_class).to receive(:after_filter).with({}).and_yield(controller_instance)
236
+ expect {
237
237
  controller_class.ensure_authorization_performed
238
- }.should_not raise_error()
238
+ }.not_to raise_error()
239
239
  end
240
240
 
241
241
  end
@@ -253,7 +253,7 @@ describe Authority::Controller do
253
253
 
254
254
  let(:controller_instance) do
255
255
  controller_class.new.tap do |cc|
256
- cc.stub(Authority.configuration.user_method).and_return(user)
256
+ allow(cc).to receive(Authority.configuration.user_method).and_return(user)
257
257
  end
258
258
  end
259
259
 
@@ -264,7 +264,7 @@ describe Authority::Controller do
264
264
  context "if a resource class was specified" do
265
265
 
266
266
  it "checks authorization on the model specified" do
267
- controller_instance.should_receive(:authorize_action_for).with(resource_class)
267
+ expect(controller_instance).to receive(:authorize_action_for).with(resource_class)
268
268
  controller_instance.send(:run_authorization_check)
269
269
  end
270
270
 
@@ -284,11 +284,18 @@ describe Authority::Controller do
284
284
 
285
285
  context "and the method returns a class" do
286
286
  before :each do
287
- controller_instance.stub(:method_to_find_class).and_return(resource_class)
287
+ allow(controller_instance).to receive(:method_to_find_class).and_return(resource_class)
288
288
  end
289
289
 
290
290
  it "checks authorization on that class" do
291
- controller_instance.should_receive(:authorize_action_for).with(resource_class)
291
+ expect(controller_instance).to receive(:authorize_action_for).with(resource_class)
292
+ controller_instance.send(:run_authorization_check)
293
+ end
294
+
295
+ it "does not call to_a on that class" do
296
+ expect(controller_instance).to receive(:authorize_action_for).with(resource_class)
297
+ # *resource is syntactic sugar for resource.to_a
298
+ expect(resource_class).not_to receive(:to_a)
292
299
  controller_instance.send(:run_authorization_check)
293
300
  end
294
301
  end
@@ -297,11 +304,11 @@ describe Authority::Controller do
297
304
  let(:some_options) { { :a => 1, :b => 2 } }
298
305
 
299
306
  before :each do
300
- controller_instance.stub(:method_to_find_class).and_return([resource_class, some_options])
307
+ allow(controller_instance).to receive(:method_to_find_class).and_return([resource_class, some_options])
301
308
  end
302
309
 
303
310
  it "checks authorization on that class and passes the options" do
304
- controller_instance.should_receive(:authorize_action_for).with(resource_class, some_options)
311
+ expect(controller_instance).to receive(:authorize_action_for).with(resource_class, some_options)
305
312
  controller_instance.send(:run_authorization_check)
306
313
  end
307
314
  end
@@ -321,7 +328,7 @@ describe Authority::Controller do
321
328
  end
322
329
 
323
330
  it "raises a MissingAction if there is no corresponding action for the controller" do
324
- controller_instance.stub(:action_name).and_return('sculpt')
331
+ allow(controller_instance).to receive(:action_name).and_return('sculpt')
325
332
  expect { controller_instance.send(:run_authorization_check) }.to raise_error(
326
333
  Authority::Controller::MissingAction
327
334
  )
@@ -331,23 +338,23 @@ describe Authority::Controller do
331
338
 
332
339
  describe "authorize_action_for" do
333
340
 
334
- before(:each) { controller_instance.stub(:action_name).and_return(:destroy) }
341
+ before(:each) { allow(controller_instance).to receive(:action_name).and_return(:destroy) }
335
342
 
336
343
  it "calls Authority.enforce to authorize the action" do
337
- Authority.should_receive(:enforce)
344
+ expect(Authority).to receive(:enforce)
338
345
  controller_instance.send(:authorize_action_for, resource_class)
339
346
  end
340
347
 
341
348
  it "passes along any options it was given" do
342
349
  options = {:for => 'insolence'}
343
- Authority.should_receive(:enforce).with('delete', resource_class, user, options)
350
+ expect(Authority).to receive(:enforce).with('delete', resource_class, user, options)
344
351
  controller_instance.send(:authorize_action_for, resource_class, options)
345
352
  end
346
353
 
347
354
  it "sets correct authorization flag" do
348
- Authority.stub(:enforce)
355
+ allow(Authority).to receive(:enforce)
349
356
  controller_instance.send(:authorize_action_for, resource_class)
350
- controller_instance.authorization_performed?.should be_true
357
+ expect(controller_instance.authorization_performed?).to eq(true)
351
358
  end
352
359
 
353
360
  end
@@ -355,7 +362,7 @@ describe Authority::Controller do
355
362
  describe "authority_user" do
356
363
 
357
364
  it "gets the user for the current request from the configured user_method" do
358
- controller_instance.should_receive(Authority.configuration.user_method)
365
+ expect(controller_instance).to receive(Authority.configuration.user_method)
359
366
  controller_instance.send(:authority_user)
360
367
  end
361
368
 
@@ -366,15 +373,15 @@ describe Authority::Controller do
366
373
  let(:mock_error) { double(:message => 'oh noes! an error!') }
367
374
 
368
375
  it "logs an error" do
369
- Authority.logger.should_receive(:warn)
370
- controller_instance.stub(:render)
376
+ expect(Authority.logger).to receive(:warn)
377
+ allow(controller_instance).to receive(:render)
371
378
  controller_instance.send(:authority_forbidden, mock_error)
372
379
  end
373
380
 
374
381
  it "renders the public/403.html file" do
375
382
  forbidden_page = Rails.root.join('public/403.html')
376
- Authority.logger.stub(:warn)
377
- controller_instance.should_receive(:render).with(:file => forbidden_page, :status => 403, :layout => false)
383
+ allow(Authority.logger).to receive(:warn)
384
+ expect(controller_instance).to receive(:render).with(:file => forbidden_page, :status => 403, :layout => false)
378
385
  controller_instance.send(:authority_forbidden, mock_error)
379
386
  end
380
387
 
@@ -19,7 +19,7 @@ describe "integration from user through model to authorizer" do
19
19
  describe "if given an options hash" do
20
20
 
21
21
  it "delegates `#{adjective_method}` to its authorizer class, passing the options" do
22
- resource_class.authorizer.should_receive(adjective_method).with(user, :lacking => 'nothing')
22
+ expect(resource_class.authorizer).to receive(adjective_method).with(user, :lacking => 'nothing')
23
23
  user.send(verb_method, resource_class, :lacking => 'nothing')
24
24
  end
25
25
 
@@ -28,7 +28,7 @@ describe "integration from user through model to authorizer" do
28
28
  describe "if not given an options hash" do
29
29
 
30
30
  it "delegates `#{adjective_method}` to its authorizer class, passing no options" do
31
- resource_class.authorizer.should_receive(adjective_method).with(user)
31
+ expect(resource_class.authorizer).to receive(adjective_method).with(user)
32
32
  user.send(verb_method, resource_instance)
33
33
  end
34
34
 
@@ -45,7 +45,7 @@ describe "integration from user through model to authorizer" do
45
45
  let!(:authorizer_instance) { resource_class.authorizer.new(resource_instance) }
46
46
 
47
47
  before :each do
48
- resource_class.authorizer.stub(:new).and_return(authorizer_instance)
48
+ allow(resource_class.authorizer).to receive(:new).and_return(authorizer_instance)
49
49
  end
50
50
 
51
51
  Authority.verbs.each do |verb|
@@ -58,7 +58,7 @@ describe "integration from user through model to authorizer" do
58
58
  describe "if given an options hash" do
59
59
 
60
60
  it "delegates `#{adjective_method}` to a new authorizer instance, passing the options" do
61
- authorizer_instance.should_receive(adjective_method).with(user, :consistency => 'mushy')
61
+ expect(authorizer_instance).to receive(adjective_method).with(user, :consistency => 'mushy')
62
62
  user.send(verb_method, resource_instance, :consistency => 'mushy')
63
63
  end
64
64
 
@@ -67,7 +67,7 @@ describe "integration from user through model to authorizer" do
67
67
  describe "if not given an options hash" do
68
68
 
69
69
  it "delegates `#{adjective_method}` to a new authorizer instance, passing no options" do
70
- authorizer_instance.should_receive(adjective_method).with(user)
70
+ expect(authorizer_instance).to receive(adjective_method).with(user)
71
71
  user.send(verb_method, resource_instance)
72
72
  end
73
73
 
@@ -18,7 +18,7 @@ describe Authority::UserAbilities do
18
18
  describe "if given options" do
19
19
 
20
20
  it "delegates the authorization check to the resource, passing the options" do
21
- resource_instance.should_receive("#{Authority.abilities[verb]}_by?").with(user, :size => 'wee')
21
+ expect(resource_instance).to receive("#{Authority.abilities[verb]}_by?").with(user, :size => 'wee')
22
22
  user.send(method_name, resource_instance, :size => 'wee')
23
23
  end
24
24
 
@@ -27,7 +27,7 @@ describe Authority::UserAbilities do
27
27
  describe "if not given options" do
28
28
 
29
29
  it "delegates the authorization check to the resource, passing no options" do
30
- resource_instance.should_receive("#{Authority.abilities[verb]}_by?").with(user)
30
+ expect(resource_instance).to receive("#{Authority.abilities[verb]}_by?").with(user)
31
31
  user.send(method_name, resource_instance)
32
32
  end
33
33
 
@@ -42,7 +42,7 @@ describe Authority::UserAbilities do
42
42
  context "when ApplicationAuthorizer responds to a matching `authorizes_to?` call" do
43
43
 
44
44
  before :each do
45
- ApplicationAuthorizer.stub(:authorizes_to_mimic_lemurs?).and_return('yessir')
45
+ allow(ApplicationAuthorizer).to receive(:authorizes_to_mimic_lemurs?).and_return('yessir')
46
46
  end
47
47
 
48
48
  it "uses the `authorizes_to` return value" do
@@ -50,12 +50,12 @@ describe Authority::UserAbilities do
50
50
  end
51
51
 
52
52
  it "passes along options if any were given" do
53
- ApplicationAuthorizer.should_receive(:authorizes_to_mimic_lemurs?).with(user, :for => :academic_credit)
53
+ expect(ApplicationAuthorizer).to receive(:authorizes_to_mimic_lemurs?).with(user, :for => :academic_credit)
54
54
  user.can?(:mimic_lemurs, :for => :academic_credit)
55
55
  end
56
56
 
57
57
  it "doesn't pass along options if none were given" do
58
- ApplicationAuthorizer.should_receive(:authorizes_to_mimic_lemurs?).with(user)
58
+ expect(ApplicationAuthorizer).to receive(:authorizes_to_mimic_lemurs?).with(user)
59
59
  user.can?(:mimic_lemurs)
60
60
  end
61
61
 
@@ -64,14 +64,14 @@ describe Authority::UserAbilities do
64
64
  context "when ApplicationAuthorizer does not respond to a matching `authorizes_to?` call" do
65
65
 
66
66
  before :each do
67
- ApplicationAuthorizer.stub(:authorizes_to_mimic_lemurs?).and_raise(NoMethodError.new('eh?'))
67
+ allow(ApplicationAuthorizer).to receive(:authorizes_to_mimic_lemurs?).and_raise(NoMethodError.new('eh?'))
68
68
  end
69
69
 
70
70
  context "when ApplicationAuthorizer responds to a matching `can` call" do
71
71
 
72
72
  before :each do
73
- ApplicationAuthorizer.stub(:can_mimic_lemurs?).and_return('thumbs up!')
74
- Authority.logger.stub(:warn)
73
+ allow(ApplicationAuthorizer).to receive(:can_mimic_lemurs?).and_return('thumbs up!')
74
+ allow(Authority.logger).to receive(:warn)
75
75
  end
76
76
 
77
77
  it "uses the `can` return value (for backwards compatibility)" do
@@ -79,7 +79,7 @@ describe Authority::UserAbilities do
79
79
  end
80
80
 
81
81
  it "sends a deprecation warning" do
82
- Authority.logger.should_receive(:warn).with(
82
+ expect(Authority.logger).to receive(:warn).with(
83
83
  "DEPRECATION WARNING: Please rename `ApplicationAuthorizer.can_mimic_lemurs?` to `authorizes_to_mimic_lemurs?`"
84
84
  )
85
85
  user.can?(:mimic_lemurs)
@@ -90,7 +90,7 @@ describe Authority::UserAbilities do
90
90
  context "when ApplicationAuthorizer does not respond to a matching `can` call" do
91
91
 
92
92
  before(:each) do
93
- ApplicationAuthorizer.stub(:can_mimic_lemurs?).and_raise(NoMethodError.new('whaaa?'))
93
+ allow(ApplicationAuthorizer).to receive(:can_mimic_lemurs?).and_raise(NoMethodError.new('whaaa?'))
94
94
  end
95
95
 
96
96
  it "re-raises the NoMethodError from the missing `authorizes_to?`" do
@@ -32,9 +32,24 @@ describe Authority do
32
32
  end
33
33
 
34
34
  it "requires the remainder of library internals after configuration" do
35
- Authority.should_receive(:require_authority_internals!)
35
+ expect(Authority).to receive(:require_authority_internals!)
36
36
  Authority.configure
37
37
  end
38
+
39
+ it "allows changing the logger" do
40
+ starting_config = Authority.configuration
41
+ logger1 = Object.new
42
+ logger2 = Object.new
43
+ config = Authority::Configuration.new
44
+ Authority.configuration = config
45
+
46
+ config.logger = logger1
47
+ expect(Authority.logger).to eq(logger1)
48
+
49
+ config.logger = logger2
50
+ expect(Authority.logger).to eq(logger2)
51
+ Authority.configuration = starting_config
52
+ end
38
53
  end
39
54
 
40
55
  describe "enforcement" do
@@ -49,7 +64,7 @@ describe Authority do
49
64
 
50
65
  it "checks the user's authorization, passing along the options" do
51
66
  options = { :for => 'context' }
52
- user.should_receive(:can_delete?).with(resource_class, options).and_return(true)
67
+ expect(user).to receive(:can_delete?).with(resource_class, options).and_return(true)
53
68
  Authority.enforce(:delete, resource_class, user, options)
54
69
  end
55
70
 
@@ -58,7 +73,7 @@ describe Authority do
58
73
  describe "when not given options" do
59
74
 
60
75
  it "checks the user's authorization, passing no options" do
61
- user.should_receive(:can_delete?).with(resource_class).and_return(true)
76
+ expect(user).to receive(:can_delete?).with(resource_class).and_return(true)
62
77
  Authority.enforce(:delete, resource_class, user)
63
78
  end
64
79
 
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: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Long
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-19 00:00:00.000000000 Z
12
+ date: 2015-07-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -39,6 +39,20 @@ dependencies:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: 0.8.7
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: 3.3.0
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: 3.3.0
42
56
  description: Authority helps you authorize actions in your Rails app. It's ORM-neutral
43
57
  and has very little fancy syntax; just group your models under one or more Authorizer
44
58
  classes and write plain Ruby methods on them.
@@ -63,6 +77,7 @@ files:
63
77
  - gemfiles/3.2.gemfile
64
78
  - gemfiles/4.0.gemfile
65
79
  - gemfiles/4.1.gemfile
80
+ - gemfiles/4.2.gemfile
66
81
  - lib/authority.rb
67
82
  - lib/authority/abilities.rb
68
83
  - lib/authority/authorizer.rb