authorizer 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,12 @@
1
+ === 0.0.2 2011-08-22
2
+
3
+ * Major enhancements:
4
+ * Find function wasn't working properly, a user would get a list of objects from another user. Also reworked its internals so all arguments are passed on to the ActiveRecord::Base find function.
5
+ * Minor enhancements:
6
+ * Improved error messages.
7
+ * Fixed some other bugs and quirks.
8
+
1
9
  === 0.0.1 2011-07-01
2
10
 
3
11
  * 1 major enhancement:
4
- * Initial release
12
+ * Initial release.
@@ -45,13 +45,15 @@ Handles authorization for you.
45
45
  Authorize a user on an object
46
46
 
47
47
  Authorizer::Base.authorize_user( :object => object )
48
-
49
48
  => true/false
50
49
 
51
50
  If you want to know if the current user is authorized on an object, use:
52
51
 
53
- Authorizer::Base.user_is_authorized?( :object => object)
52
+ Authorizer::Base.user_is_authorized?( :object => object )
54
53
  => true/false
54
+
55
+ Authorizer::Base.authorize!( :object => object, :message => "You are not authorized to access this resource." ) # message is optional
56
+ => returns true or raises Authorizer::UserNotAuthorized
55
57
 
56
58
  Remove authorization from an object
57
59
 
@@ -91,16 +93,13 @@ Authorizer uses ActiveRecord observers to make sure it doesn't make any mess, fo
91
93
 
92
94
  - Ruby (this gem was tested with 1.8.7)
93
95
  - Rails 2.3 (tested with 2.3.11 and 2.3.12)
94
- - Authlogic (for authentication)
96
+ - An authentication mechanism such as Authlogic for authentication (tested with authlogic 2.1.6)
95
97
 
96
98
  Optional:
97
99
  - inherited_resources if you want to use the controller filters supplied with this gem. Otherwise, you'll have to check for authorization yourself.
98
100
 
99
101
  == INSTALL:
100
102
 
101
- Installation
102
- ===
103
-
104
103
  1. sudo gem install authorizer
105
104
  2. add "authorizer" to your Gemfile (I hope you've stopped using config.gem already even if you are on Rails 2.3?)
106
105
  3. generate a migration for authorization objects:
@@ -125,14 +124,26 @@ Paste this code into the newly generated file:
125
124
  end
126
125
 
127
126
  4. run "rake db:migrate" to migrate your database
127
+ 5. Add these lines to your app/controllers/application_controller.rb:
128
+
129
+ require 'authorizer/exceptions'
130
+
131
+ rescue_from Authorizer::UserNotAuthorized do |exception|
132
+ # Show a static 403 page upon authorization failure
133
+ render :file => "#{Rails.root}/public/403.html", :status => 403
134
+ end
135
+
136
+ 6. Download the file public/403.html from {authorizer_project}[https://github.com/cmdjohnson/authorizer_project] and copy it to your own app.
128
137
 
129
138
  That's it!
130
139
 
131
140
  == DEVELOPERS:
132
141
 
133
- Reviews, patches and bug tickets are welcome!
142
+ Reviews, patches and bug tickets are welcome! There's still some features that need to be implemented:
143
+ - (Multiple) roles for users on an object
144
+ - Rails 3 support!
134
145
 
135
- {authorizer_project}[https://github.com/cmdjohnson/authorizer_project] is a sample project that shows the usage of the Authorizer gem. It also contains all tests for your testing pleasure.
146
+ {authorizer_project}[https://github.com/cmdjohnson/authorizer_project] is a sample project that shows the usage of the Authorizer gem. It also contains all unit and functional tests for your testing pleasure.
136
147
 
137
148
  == LICENSE:
138
149
 
@@ -3,5 +3,5 @@ $:.unshift(File.dirname(__FILE__)) unless
3
3
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
4
4
 
5
5
  module Authorizer
6
- VERSION = '0.0.1'
6
+ VERSION = '0.0.2'
7
7
  end
@@ -17,49 +17,48 @@ class ApplicationController < ActionController::Base
17
17
 
18
18
  private
19
19
 
20
- ##############################################################################
21
- # authorizer
22
- ##############################################################################
20
+ # Own an object (you've just created)
21
+ # With no arguments given, this method will try to use inherited_resources to determine the object you've just created.
22
+ # The object can be overridden with :object => object
23
+ def own_created_object(options = {})
24
+ ret = false # default answer: don't allow
23
25
 
24
- def own_created_object
25
- ret = true # always return true otherwise the filter chain would be blocked.
26
+ r = options[:object]
26
27
 
27
28
  begin
28
- r = resource
29
+ r ||= resource
29
30
  rescue
30
31
  end
31
32
 
32
33
  unless r.nil?
33
34
  # only if this objet was successfully created will we do this.
34
35
  unless r.new_record?
35
- Authorizer::Base.authorize_user( :object => r )
36
+ ret = Authorizer::Base.authorize_user( :object => r )
36
37
  end
37
38
  end
38
39
 
39
40
  ret
40
41
  end
41
42
 
42
- def authorize
43
+ # Authorize on the current object.
44
+ # With no arguments given, this method will try to use inherited_resources to determine the object you're supposed to authorize on.
45
+ # The object can be overridden with :object => object
46
+ def authorize(options = {})
43
47
  ret = false # return false by default, effectively using a whitelist method.
44
48
 
49
+ r = options[:object]
50
+
45
51
  begin
46
- r = resource
52
+ r ||= resource
47
53
  rescue
48
54
  end
49
55
 
50
56
  unless r.nil?
51
- auth = Authorizer::Base.user_is_authorized?( :object => r )
52
-
53
- if auth.eql?(false)
54
- raise Authorizer::UserNotAuthorized.new("You are not authorized to access this resource.")
55
- end
57
+ # Use the bang method, it will raise an Exception if needed
58
+ ret = Authorizer::Base.authorize!( :object => r )
56
59
  end
57
60
 
58
61
  ret
59
62
  end
60
-
61
- ##############################################################################
62
- # end authorizer
63
- ##############################################################################
64
63
  end
65
64
 
@@ -40,20 +40,44 @@ module Authorizer
40
40
  object_reference = object.id
41
41
 
42
42
  ObjectRole.create!( :klazz_name => klazz_name, :object_reference => object_reference, :user => user, :role => role )
43
- Rails.logger.debug("Authorizer: created authorization on #{object} for current_user with ID #{user.id} witih role #{role}")
43
+ Rails.logger.debug("Authorizer: created authorization on #{object} for current_user with ID #{user.id} with role #{role}")
44
44
  ret = true
45
45
  end
46
46
 
47
47
  ret
48
48
  end
49
49
 
50
+ ############################################################################
51
+ # authorize!
52
+ #
53
+ # Bang version of authorize
54
+ ############################################################################
55
+
56
+ def self.authorize! options = {}
57
+ auth_ok = user_is_authorized?(options)
58
+
59
+ # User can override error message
60
+ message = options[:message]
61
+ # Attempt to fetch from I18n
62
+ begin
63
+ message ||= I18n.translate!("authorizer.access_denied")
64
+ rescue
65
+ end
66
+ # Default error message
67
+ message ||= "You are not authorized to access this resource."
68
+
69
+ raise Authorizer::UserNotAuthorized.new(message) unless auth_ok
70
+
71
+ auth_ok
72
+ end
73
+
50
74
  ############################################################################
51
75
  # user_is_authorized?
52
76
  #
53
77
  # If no user is specified, current_user is used.
54
78
  ############################################################################
55
79
 
56
- def self.user_is_authorized? options
80
+ def self.user_is_authorized? options = {}
57
81
  OptionsChecker.check(options, [ :object ])
58
82
 
59
83
  ret = false
@@ -78,12 +102,17 @@ module Authorizer
78
102
  if ret
79
103
  Rails.logger.debug("Authorizer: authorized current_user with ID #{user.id} to access #{or_.description} because of role #{or_.role}") unless user.nil? || or_.nil?
80
104
  else
81
- Rails.logger.debug("Authorizer: authorization failed for current_user with ID #{user.id} to access #{object.to_s}") unless user.nil? || object.nil?
105
+ Rails.logger.debug("Authorizer: authorization failed for current_user with ID #{user.id} to access #{object.inspect}") unless user.nil? || object.nil?
82
106
  end
83
107
 
84
108
  ret
85
109
  end
86
110
 
111
+ # Could't get alias_method to work. Don't ask me why.
112
+ def self.authorize(options = {})
113
+ user_is_authorized?(options)
114
+ end
115
+
87
116
  ############################################################################
88
117
  # remove_authorization
89
118
  ############################################################################
@@ -120,8 +149,7 @@ module Authorizer
120
149
  ############################################################################
121
150
  # find
122
151
  ############################################################################
123
- # Out of the collection of all Posts, return the subset that belongs to the current user.
124
- # External method that maps to the internal_find which is the generic find method.
152
+ # From the entire collection of Posts, return the subset that belongs to the current user.
125
153
  #
126
154
  # Arguments:
127
155
  # - class_name: which class to use, e.g. "Post"
@@ -139,8 +167,6 @@ module Authorizer
139
167
 
140
168
  ############################################################################
141
169
  # is_authorized?
142
- #
143
- # Checks if the corresponding role.eql?("owner")
144
170
  ############################################################################
145
171
 
146
172
  def self.is_authorized? object
@@ -198,80 +224,54 @@ module Authorizer
198
224
  class_name = options[:class_name]
199
225
  what = options[:what]
200
226
  find_options = options[:find_options] || {}
201
- user = options[:user] || get_current_user
202
-
203
- # We don't do the what checks anymore, ActiveRecord::Base.find does that for us now.
204
- #what_checks = [ :all, :first, :last, :id ]
205
- #raise "What must be one of #{what_checks.inspect}" unless what_checks.include?(what)
227
+ user = options[:user] || get_current_user # Default is current user, but the specified user will override.
206
228
 
207
229
  # Check userrrrrrrrrrrr --- =====================- ---= ===-=- *&((28 @((8
208
230
  check_user(user)
209
- # rrrr
210
231
  ret = nil
211
- # Checks
212
232
  # Checks done. Let's go.
213
233
  # Get the real klazz
214
234
  klazz = nil
215
235
  # Check it
216
236
  begin
217
237
  klazz = eval(class_name)
218
- rescue
238
+ rescue => e
239
+ # Throw an exception if klazz is nil
240
+ raise ArgumentError.new("Could not eval class '#{klazz}'. It presumably does not exist. Maybe you mistyped its name? Error was: #{e.inspect}") if klazz.nil?
219
241
  end
220
242
  # oooo ooo ooo ___ --- === __- --_- ++_+_ =--- +- =+=-=- =-= <--- ice beam!
221
243
  unless klazz.nil?
222
244
  # now we know klazz really exists.
223
- # let's find the object_role objects that match the user and klaz.
245
+ # let's find the object_role objects that match the user and klazz.
224
246
  # Get the object_role objects
225
247
  object_roles_conditions = { :klazz_name => class_name, :user_id => user.id }
226
248
  object_roles = ObjectRole.find(:all, :conditions => object_roles_conditions )
227
- # Get a list of IDs. These are objects that are owned by the current_user
228
- object_role_ids = object_roles.collect { |or_| or_.object_reference } # [ 1, 1, 1, 1 ]
229
- # Make it at least an array if object_role_ids returns nil
230
- object_role_ids ||= []
231
- # Try to emulate find as good as we can
232
- # so don't skip this, try to always pass it on.
249
+ # OK.
250
+ # We already have the comprehensive list of object roles we are authorized on.
233
251
  unless object_roles.nil?
234
- # Prepare find_options
235
- leading_find_options = {} # insert conventions here if needed
236
- my_find_options = find_options.merge(leading_find_options)
237
- # If the user passed an Array we should filter it with the list of available (authorized) objects.
238
- #
239
- # http://www.ruby-doc.org/core/classes/Array.html
240
- # &
241
- # Set Intersection—Returns a new array containing elements common to the two arrays, with no duplicates.
242
- safe_what = what
243
- if what.is_a?(Array)
244
- safe_what = what & object_role_ids
245
- end
246
- # The big show. Let's call out F I N D !!!!!!
247
- # INF FINFD FIWI FFIND IF FIND FIND FIND FIND FIND FIND FIND FIND
248
- # FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND
249
- # FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND
250
- # FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND
251
- # FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND
252
- # FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND
253
- # FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND
254
- # FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND
255
- # FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND
256
- # FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND
257
- # FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND FIND
258
- if safe_what.eql?(:all)
259
- ret = klazz.find(:all, my_find_options)
260
- elsif safe_what.eql?(:first)
261
- ret = klazz.find(object_role_ids.first, my_find_options)
262
- elsif safe_what.eql?(:last)
263
- ret = klazz.find(object_role_ids.last, my_find_options)
264
- else
265
- ret = klazz.find(safe_what, my_find_options)
252
+ # Get a list of IDs. These are objects that are owned by the current_user
253
+ object_role_ids = object_roles.collect { |or_| or_.object_reference } # [ 1, 1, 1, 1 ]
254
+ # Make it at least an array if collect returns nil
255
+ object_role_ids ||= []
256
+ # DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT
257
+ # DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT
258
+ # DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT
259
+ # DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT
260
+ # DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT
261
+ # DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT DO IT
262
+ unless object_role_ids.nil?
263
+ # Prepare find_options
264
+ leading_find_options = {} # insert conventions here if needed, maybe for security or other purposes
265
+ my_find_options = find_options.merge(leading_find_options)
266
+ # Big chance object_role_ids equals an Empty Array (TM) or []
267
+ # That's good, it means this line will be
268
+ #
269
+ # Post.scoped_by_id([]).find(:all)
270
+ #
271
+ # Which will never ever return anything.
272
+ # This is also good because it means we can just proxy whatever we get from the user into Find and it will take care of it for us.
273
+ ret = klazz.scoped_by_id(object_role_ids).find(what, my_find_options) # scoped_by is new in 2.3. sweeeeeeeeeeeet
266
274
  end
267
- # SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT????
268
- # SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT????
269
- # SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT????
270
- # SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT????
271
- # SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT????
272
- # SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT????
273
- # SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT????
274
- # SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT???? SAFE WHAT????
275
275
  end
276
276
  end
277
277
 
@@ -310,9 +310,18 @@ module Authorizer
310
310
  def self.check_user(user)
311
311
  ret = true
312
312
 
313
- raise "User cannot be nil" if user.nil?
314
- raise "User must inherit from ActiveRecord::Base" unless user.is_a?(ActiveRecord::Base)
315
- raise "User must be saved" if user.new_record?
313
+ if user.nil?
314
+ raise Authorizer::RuntimeException.new "User cannot be nil. Maybe you should specify authorizer_options = { :user => user } if you are not calling from a controller?"
315
+ end
316
+
317
+ unless user.is_a?(ActiveRecord::Base)
318
+ raise Authorizer::RuntimeException.new "User must inherit from ActiveRecord::Base"
319
+
320
+ end
321
+
322
+ if user.new_record?
323
+ raise Authorizer::RuntimeException.new "User must be saved"
324
+ end
316
325
 
317
326
  ret
318
327
  end
@@ -1,6 +1,10 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module Authorizer
3
+ # Thrown when the user is not authorized.
3
4
  class UserNotAuthorized < Exception
4
-
5
+ end
6
+
7
+ # Thrown when an internal error occurs, such as when an ObjectRole record doesn't exist.
8
+ class RuntimeException < Exception
5
9
  end
6
10
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authorizer
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - CmdJohnson
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-07-26 00:00:00 +02:00
18
+ date: 2011-08-22 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency