authority 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.markdown CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  This is mainly to document major new features and backwards-incompatible changes.
4
4
 
5
+ ## v2.0.1
6
+
7
+ Documentation and test cleanup.
8
+
5
9
  ## v2.0.0
6
10
 
7
11
  - **Breaking change**: models now assume their authorizer is `ApplicationAuthorizer` unless told otherwise. Generator creates a blank `ApplicationAuthorizer`. This, combined with the change in v1.1.0, makes the `default_strategy` proc obsolete in favor of straightforward inheritance of a `default` method, so support for `config.default_strategy` is removed.
data/README.markdown CHANGED
@@ -87,9 +87,10 @@ The authorization process generally flows like this:
87
87
  | # calls `default`...
88
88
  v
89
89
  AdminAuthorizer.default(:creatable, current_user) # *You define this method.*
90
- # If you don't, the one inherited
91
- # from Authority::Authorizer just
92
- # returns false.
90
+ # If you don't, it will use the one
91
+ # inherited from ApplicationAuthorizer.
92
+ # (Its parent, Authority::Authorizer,
93
+ # defines the method as `return false`.)
93
94
 
94
95
  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.
95
96
 
@@ -260,27 +261,47 @@ end
260
261
 
261
262
  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:
262
263
 
263
- - `authorize_actions_for Transaction` protects multiple controller actions with a `before_filter`, which performs a **class-level** check. If the current user is never allowed to delete a `Transaction`, they'll never even get to the controller's `destroy` method.
264
- - `authorize_action_for @transaction` 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 `@transaction` instance.
264
+ - `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.
265
+ - `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.
265
266
 
266
- The relationship between controller actions and abilities - like checking `readable_by?` on the `index` action - is configurable both globally, using `config.controller_action_map`, and per controller, as below.
267
+ 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:
267
268
 
268
269
  ```ruby
269
- class LlamaController < ApplicationController
270
+ config.controller_action_map = {
271
+ :index => 'read', # `index` controller action will check `readable_by?`
272
+ :show => 'read',
273
+ :new => 'create', # `new` controller action will check `creatable_by?`
274
+ :create => 'create', # ...etc
275
+ :edit => 'update',
276
+ :update => 'update',
277
+ :destroy => 'delete'
278
+ }
279
+ ```
280
+
281
+ They are also configurable per controller, as follows:
282
+
283
+ ```ruby
284
+ class LlamasController < ApplicationController
270
285
 
271
286
  # Check class-level authorizations before all actions except :create
272
287
  # Also, to authorize this controller's 'neuter' action, ask whether `current_user.can_update?(Llama)`
273
288
  authorize_actions_for Llama, :except => :create, :actions => {:neuter => :update},
274
289
 
275
290
  # To authorize this controller's 'breed' action, ask whether `current_user.can_create?(Llama)`
276
- authority_action :breed => 'new'
291
+ authority_action :breed => 'create'
277
292
 
278
293
  ...
279
294
 
280
295
  def edit
281
296
  @llama = Llama.find(params[:id])
297
+ authorize_action_for(@llama) # Check to see if you're allowed to edit this llama. failure == SecurityViolation
298
+ end
299
+
300
+ def update
301
+ @llama = Llama.find(params[:id])
302
+ authorize_action_for(@llama) # Check to see if you're allowed to edit this llama.
282
303
  @llama.attributes = params[:llama] # Don't save the attributes before authorizing
283
- authorize_action_for(@llama) # failure == SecurityViolation
304
+ authorize_action_for(@llama) # Check again, to see if the changes are allowed.
284
305
  if @llama.save?
285
306
  # etc
286
307
  end
@@ -329,6 +350,8 @@ end
329
350
 
330
351
  If you want different error handling per controller, define `fire_ze_missiles` on each of them.
331
352
 
353
+ Your method will be handed the `SecurityViolation`, which has a `message` method. In case you want to build your own message, it also exposes `user`, `action` and `resource`.
354
+
332
355
  <a name="credits">
333
356
  ## Credits, AKA 'Shout-Outs'
334
357
 
data/TODO.markdown CHANGED
@@ -7,8 +7,5 @@
7
7
 
8
8
  ## Documentation
9
9
 
10
- - Example of checking clean/dirty attributes in instance-level checks. For example, if I'm only allowed to update blue laser cannons, can I make them red? Maybe I need to check whether the old value was blue?
11
-
12
10
  ## Features
13
11
 
14
- - It would be nice to have an `authorized_link_to` method, which determines from the given path and the user's permissions whether to show the link. Not sure yet how hard this would be.
@@ -27,6 +27,7 @@ module Authority
27
27
  RUBY
28
28
  end
29
29
 
30
+ # @return [Class] of the designated authorizer
30
31
  def authorizer
31
32
  @authorizer ||= authorizer_name.constantize # Get an actual reference to the authorizer class
32
33
  rescue NameError
@@ -1,7 +1,7 @@
1
1
  module Authority
2
2
  class Configuration
3
3
 
4
- # Has default settings, overrideable in the initializer.
4
+ # Has default settings, which can be overridden in the initializer.
5
5
 
6
6
  attr_accessor :abilities, :controller_action_map, :user_method, :security_violation_handler, :logger
7
7
 
@@ -11,7 +11,7 @@ module Authority
11
11
 
12
12
  def self.security_violation_callback
13
13
  Proc.new do |exception|
14
- # Through the magic of ActiveSupport's Proc#bind, `ActionController::Base#rescue_from`
14
+ # Through the magic of ActiveSupport's `Proc#bind`, `ActionController::Base#rescue_from`
15
15
  # can call this proc and make `self` the actual controller instance
16
16
  self.send(Authority.configuration.security_violation_handler, exception)
17
17
  end
@@ -59,13 +59,13 @@ module Authority
59
59
 
60
60
  private
61
61
 
62
- # The before filter that will be setup to run when the class method
62
+ # The `before_filter` that will be setup to run when the class method
63
63
  # `authorize_actions_for` is called
64
64
  def run_authorization_check
65
65
  authorize_action_for self.class.authority_resource
66
66
  end
67
67
 
68
- # Convenience wrapper for sending configured user_method to extract the
68
+ # Convenience wrapper for sending configured `user_method` to extract the
69
69
  # request's current user
70
70
  #
71
71
  # @return [Object] the user object returned from sending the user_method
@@ -73,7 +73,7 @@ module Authority
73
73
  send(Authority.configuration.user_method)
74
74
  end
75
75
 
76
- # To be run in a before_filter; ensure this controller action is allowed for the user
76
+ # To be run in a `before_filter`; ensure this controller action is allowed for the user
77
77
  #
78
78
  # @param authority_resource [Class], the model class associated with this controller
79
79
  # @raise [MissingAction] if controller action isn't a key in `config.controller_action_map`
@@ -1,3 +1,3 @@
1
1
  module Authority
2
- VERSION = "2.0.0"
2
+ VERSION = "2.0.1"
3
3
  end
@@ -25,7 +25,7 @@ module Authority
25
25
  private
26
26
 
27
27
  def create_authorizers_directory
28
- # creates empty directory if none; doesn't empty the directory
28
+ # Creates empty directory if none; doesn't empty the directory
29
29
  empty_directory "app/authorizers"
30
30
  end
31
31
 
@@ -10,6 +10,7 @@ Authority.configure do |config|
10
10
  # config.user_method = :current_user
11
11
 
12
12
  # CONTROLLER_ACTION_MAP
13
+ # =====================
13
14
  # For a given controller method, what verb must a user be able to do?
14
15
  # For example, a user can access 'show' if they 'can_read' the resource.
15
16
  #
@@ -29,6 +30,7 @@ Authority.configure do |config|
29
30
  # }
30
31
 
31
32
  # ABILITIES
33
+ # =========
32
34
  # Teach Authority how to understand the verbs and adjectives in your system. Perhaps you
33
35
  # need {:microwave => 'microwavable'}. I'm not saying you do, of course. Stop looking at
34
36
  # me like that.
@@ -43,6 +45,7 @@ Authority.configure do |config|
43
45
  # }
44
46
 
45
47
  # SECURITY_VIOLATION_HANDLER
48
+ # ==========================
46
49
  # If a SecurityViolation is raised, what controller method should be used to rescue it?
47
50
  #
48
51
  # Default is:
@@ -50,6 +53,7 @@ Authority.configure do |config|
50
53
  # config.security_violation_handler = :authority_forbidden # Defined in controller.rb
51
54
 
52
55
  # LOGGER
56
+ # ======
53
57
  # If a user tries to perform an unauthorized action, where should we log that fact?
54
58
  # Provide a logger object which responds to `.warn(message)`, unless your
55
59
  # security_violation_handler calls a different method.
@@ -35,14 +35,10 @@ describe Authority::Abilities do
35
35
  end
36
36
 
37
37
  it "should raise a friendly error if the authorizer doesn't exist" do
38
- AbilityModel.instance_variable_set(:@authorizer, nil)
39
- AbilityModel.authorizer_name = 'NonExistentAuthorizer'
40
- expect { AbilityModel.authorizer }.to raise_error(Authority::NoAuthorizerError)
41
-
42
- # Cleanup to prevent affecting other tests
43
- # TODO: Clean up this cleanup code. :)
44
- AbilityModel.instance_variable_set(:@authorizer, nil)
45
- AbilityModel.authorizer_name = 'ApplicationAuthorizer'
38
+ class NoAuthorizerModel < AbilityModel; end ;
39
+ NoAuthorizerModel.instance_variable_set(:@authorizer, nil)
40
+ NoAuthorizerModel.authorizer_name = 'NonExistentAuthorizer'
41
+ expect { NoAuthorizerModel.authorizer }.to raise_error(Authority::NoAuthorizerError)
46
42
  end
47
43
 
48
44
  end
@@ -91,8 +87,9 @@ describe Authority::Abilities do
91
87
  @ability_model.should respond_to(:authorizer)
92
88
  end
93
89
 
94
- # TODO: Nathan will comment more clearly in the future
95
- # aka "don't memoize" (to prevent dirty models from contaminating authorization)
90
+ # When checking instance methods, we want to ensure that every check uses a new
91
+ # instance of the authorizer. Otherwise, you might check, make a change to the
92
+ # model instance, check again, and get an outdated answer.
96
93
  it "should always create a new authorizer instance when accessing the authorizer" do
97
94
  @ability_model.class.authorizer.should_receive(:new).with(@ability_model).twice
98
95
  2.times { @ability_model.authorizer }
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.0.0
4
+ version: 2.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-04-30 00:00:00.000000000 Z
13
+ date: 2012-06-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
17
- requirement: &2152144680 !ruby/object:Gem::Requirement
17
+ requirement: &75848730 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,7 +22,7 @@ dependencies:
22
22
  version: 3.0.0
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *2152144680
25
+ version_requirements: *75848730
26
26
  description: Authority helps you authorize actions in your Rails app. It's ORM-neutral
27
27
  and has very little fancy syntax; just group your models under one or more Authorizer
28
28
  classes and write plain Ruby methods on them.
@@ -90,20 +90,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
90
  version: '0'
91
91
  requirements: []
92
92
  rubyforge_project:
93
- rubygems_version: 1.8.16
93
+ rubygems_version: 1.8.10
94
94
  signing_key:
95
95
  specification_version: 3
96
96
  summary: Authority helps you authorize actions in your Rails app using plain Ruby
97
97
  methods on Authorizer classes.
98
- test_files:
99
- - spec/authority/abilities_spec.rb
100
- - spec/authority/authorizer_spec.rb
101
- - spec/authority/configuration_spec.rb
102
- - spec/authority/controller_spec.rb
103
- - spec/authority/user_abilities_spec.rb
104
- - spec/authority_spec.rb
105
- - spec/spec_helper.rb
106
- - spec/support/ability_model.rb
107
- - spec/support/example_controllers.rb
108
- - spec/support/mock_rails.rb
109
- - spec/support/user.rb
98
+ test_files: []