authorizer 0.0.1 → 0.0.2
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.
- data/History.txt +9 -1
- data/README.rdoc +19 -8
- data/lib/authorizer.rb +1 -1
- data/lib/authorizer/application_controller.rb +17 -18
- data/lib/authorizer/base.rb +74 -65
- data/lib/authorizer/exceptions.rb +5 -1
- metadata +4 -4
data/History.txt
CHANGED
@@ -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.
|
data/README.rdoc
CHANGED
@@ -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
|
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
|
|
data/lib/authorizer.rb
CHANGED
@@ -17,49 +17,48 @@ class ApplicationController < ActionController::Base
|
|
17
17
|
|
18
18
|
private
|
19
19
|
|
20
|
-
|
21
|
-
#
|
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
|
-
|
25
|
-
ret = true # always return true otherwise the filter chain would be blocked.
|
26
|
+
r = options[:object]
|
26
27
|
|
27
28
|
begin
|
28
|
-
r
|
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
|
-
|
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
|
52
|
+
r ||= resource
|
47
53
|
rescue
|
48
54
|
end
|
49
55
|
|
50
56
|
unless r.nil?
|
51
|
-
|
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
|
|
data/lib/authorizer/base.rb
CHANGED
@@ -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}
|
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.
|
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
|
-
#
|
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
|
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
|
-
#
|
228
|
-
|
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
|
-
#
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
#
|
239
|
-
#
|
240
|
-
#
|
241
|
-
#
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
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
|
-
|
314
|
-
|
315
|
-
|
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:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
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-
|
18
|
+
date: 2011-08-22 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|