authority 3.0.0 → 3.1.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: 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