authorizer 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +9 -6
- data/lib/authorizer.rb +1 -1
- data/lib/authorizer/base.rb +95 -64
- data/lib/authorizer/object_observer.rb +24 -0
- metadata +10 -13
data/README.rdoc
CHANGED
@@ -100,9 +100,11 @@ Optional:
|
|
100
100
|
|
101
101
|
== INSTALL:
|
102
102
|
|
103
|
-
1. sudo gem install authorizer
|
104
|
-
|
105
|
-
|
103
|
+
Step 1. sudo gem install authorizer
|
104
|
+
|
105
|
+
Step 2. add "authorizer" to your Gemfile (I hope you've stopped using config.gem already even if you are on Rails 2.3?)
|
106
|
+
|
107
|
+
Step 3. generate a migration for authorization objects:
|
106
108
|
|
107
109
|
script/generate migration CreateObjectRoles
|
108
110
|
|
@@ -123,8 +125,9 @@ Paste this code into the newly generated file:
|
|
123
125
|
drop_table :object_roles
|
124
126
|
end
|
125
127
|
|
126
|
-
4. run "rake db:migrate" to migrate your database
|
127
|
-
|
128
|
+
Step 4. run "rake db:migrate" to migrate your database
|
129
|
+
|
130
|
+
Step 5. Add these lines to your app/controllers/application_controller.rb:
|
128
131
|
|
129
132
|
require 'authorizer/exceptions'
|
130
133
|
|
@@ -133,7 +136,7 @@ Paste this code into the newly generated file:
|
|
133
136
|
render :file => "#{Rails.root}/public/403.html", :status => 403
|
134
137
|
end
|
135
138
|
|
136
|
-
6. Download the file public/403.html from {authorizer_project}[https://github.com/cmdjohnson/authorizer_project] and copy it to your own app.
|
139
|
+
Step 6. Download the file public/403.html from {authorizer_project}[https://github.com/cmdjohnson/authorizer_project] and copy it to your own app.
|
137
140
|
|
138
141
|
That's it!
|
139
142
|
|
data/lib/authorizer.rb
CHANGED
data/lib/authorizer/base.rb
CHANGED
@@ -11,28 +11,36 @@ require 'authorizer/application_controller'
|
|
11
11
|
|
12
12
|
module Authorizer
|
13
13
|
class Base < ApplicationController
|
14
|
-
|
15
|
-
#
|
14
|
+
# Authorize the current user (retrieved by calling current_user on the object passed using the :object parameter.
|
15
|
+
# The user can also be explicly spcified using :user.
|
16
|
+
# If no :role is specified, "owner" is used.
|
17
|
+
#
|
18
|
+
# Params:
|
19
|
+
# - :user (default: current_user)
|
20
|
+
# - :object
|
21
|
+
# - :role
|
16
22
|
#
|
17
|
-
#
|
18
|
-
|
19
|
-
############################################################################
|
20
|
-
|
21
|
-
def self.authorize_user(options)
|
22
|
-
OptionsChecker.check(options, [ :object ])
|
23
|
-
|
23
|
+
# Example: Authorizer::Base.authorize_user :object => object
|
24
|
+
def self.authorize_user(options = {})
|
24
25
|
ret = false
|
25
26
|
|
26
27
|
object = options[:object]
|
27
28
|
role = options[:role] || "owner"
|
28
29
|
user = options[:user] || get_current_user
|
30
|
+
|
31
|
+
# User can specify the object using a block, too.
|
32
|
+
if block_given?
|
33
|
+
object = yield
|
34
|
+
end
|
29
35
|
|
30
36
|
return false if basic_check_fails?(options)
|
31
37
|
|
32
38
|
check_user(user)
|
33
39
|
# Checks done. Let's go.
|
34
40
|
|
35
|
-
|
41
|
+
if !object.nil? && !user.nil?
|
42
|
+
or_ = find_object_role(object, user)
|
43
|
+
end
|
36
44
|
|
37
45
|
# This time, we want it to be nil.
|
38
46
|
if or_.nil? && !user.nil?
|
@@ -47,12 +55,10 @@ module Authorizer
|
|
47
55
|
ret
|
48
56
|
end
|
49
57
|
|
50
|
-
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
############################################################################
|
55
|
-
|
58
|
+
# Return true if a user is authorized to act upon this object. Raises Authorizer::UserNotAuthorized upon failure.
|
59
|
+
# Params:
|
60
|
+
# - :user (default: current_user)
|
61
|
+
# - :object
|
56
62
|
def self.authorize! options = {}
|
57
63
|
auth_ok = user_is_authorized?(options)
|
58
64
|
|
@@ -71,12 +77,10 @@ module Authorizer
|
|
71
77
|
auth_ok
|
72
78
|
end
|
73
79
|
|
74
|
-
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
############################################################################
|
79
|
-
|
80
|
+
# Return true if a user is authorized to act upon this object. Return false if this is not the case.
|
81
|
+
# Params:
|
82
|
+
# - :user (default: current_user)
|
83
|
+
# - :object
|
80
84
|
def self.user_is_authorized? options = {}
|
81
85
|
OptionsChecker.check(options, [ :object ])
|
82
86
|
|
@@ -108,17 +112,19 @@ module Authorizer
|
|
108
112
|
ret
|
109
113
|
end
|
110
114
|
|
111
|
-
#
|
115
|
+
# Return true if a user is authorized to act upon this object. Return false if this is not the case.
|
116
|
+
# Synonym for user_is_authorized?
|
117
|
+
# Params:
|
118
|
+
# - :user (default: current_user)
|
119
|
+
# - :object
|
112
120
|
def self.authorize(options = {})
|
113
|
-
user_is_authorized?(options)
|
121
|
+
user_is_authorized?(options) # Could't get alias_method to work. Don't ask me why.
|
114
122
|
end
|
115
123
|
|
116
|
-
|
117
|
-
#
|
118
|
-
|
119
|
-
#
|
120
|
-
############################################################################
|
121
|
-
|
124
|
+
# Remove authorization from a certain object. Returns true upon success and false upon failure.
|
125
|
+
# Params:
|
126
|
+
# - :user (default: current_user)
|
127
|
+
# - :object
|
122
128
|
def self.remove_authorization options = {}
|
123
129
|
OptionsChecker.check(options, [ :object ])
|
124
130
|
|
@@ -133,7 +139,9 @@ module Authorizer
|
|
133
139
|
check_user(user)
|
134
140
|
# Checks done. Let's go.
|
135
141
|
|
136
|
-
|
142
|
+
unless user.nil?
|
143
|
+
or_ = find_object_role(object, user)
|
144
|
+
end
|
137
145
|
|
138
146
|
unless or_.nil?
|
139
147
|
Rails.logger.debug("Authorizer: removed authorization for user ID #{user.id} on #{or_.description}")
|
@@ -145,10 +153,26 @@ module Authorizer
|
|
145
153
|
|
146
154
|
ret
|
147
155
|
end
|
156
|
+
|
157
|
+
# From the entire collection of Posts in the database, return the number of Posts that belong to the current user.
|
158
|
+
# Returns nil upon failure, returns a positive integer or 0 on success.
|
159
|
+
def self.count(class_name, options = {})
|
160
|
+
ret = nil
|
161
|
+
|
162
|
+
user = options[:user] || get_current_user
|
163
|
+
find_options = options[:find_options] || {}
|
164
|
+
|
165
|
+
if !class_name.blank? && !user.blank?
|
166
|
+
begin
|
167
|
+
ret = Authorizer::Base.find(class_name, :all, find_options, { :user => user }).count
|
168
|
+
rescue => e
|
169
|
+
Rails.logger.warn("#{__FILE__}: #{__LINE__}: Failed to count objects for class_name '#{class_name}' for user #{user.inspect}. Error was: #{e}")
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
ret
|
174
|
+
end
|
148
175
|
|
149
|
-
############################################################################
|
150
|
-
# find
|
151
|
-
############################################################################
|
152
176
|
# From the entire collection of Posts, return the subset that belongs to the current user.
|
153
177
|
#
|
154
178
|
# Arguments:
|
@@ -156,8 +180,6 @@ module Authorizer
|
|
156
180
|
# - what: will be passed on to the ActiveRecord find function (e.g. Post.find(what))
|
157
181
|
# - find_options: will also be passed on (e.g. Post.find(what, find_options))
|
158
182
|
# - authorizer_options: options for authorizer, e.g. { :user => @user }
|
159
|
-
############################################################################
|
160
|
-
|
161
183
|
def self.find(class_name, what, find_options = {}, authorizer_options = {})
|
162
184
|
options = { :class_name => class_name, :what => what, :find_options => find_options }
|
163
185
|
my_options = authorizer_options.merge(options) # options overrides user-specified options.
|
@@ -165,20 +187,15 @@ module Authorizer
|
|
165
187
|
internal_find(my_options)
|
166
188
|
end
|
167
189
|
|
168
|
-
|
169
|
-
#
|
170
|
-
|
171
|
-
|
190
|
+
# Return true if a user is authorized to act upon this object. Return false if this is not the case.
|
191
|
+
# Synonym for user_is_authorized
|
192
|
+
#
|
193
|
+
# This method's only parameter is the object to be checked for authorization so you don't have to type :object => object.
|
172
194
|
def self.is_authorized? object
|
173
195
|
user_is_authorized? :object => object
|
174
196
|
end
|
175
197
|
|
176
|
-
|
177
|
-
# create_ownership
|
178
|
-
#
|
179
|
-
# ObjectRole.create!( :klazz_name => object.class.to_s, :object_reference => object.id, :user => current_user, :role => "owner" )
|
180
|
-
############################################################################
|
181
|
-
|
198
|
+
# Shortcut for user_is_authorized. Takes the actual object as a parameter instead of a Hash.
|
182
199
|
def self.create_ownership object
|
183
200
|
ret = false
|
184
201
|
|
@@ -233,11 +250,19 @@ module Authorizer
|
|
233
250
|
# Get the real klazz
|
234
251
|
klazz = nil
|
235
252
|
# Check it
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
253
|
+
# Ok, Check it ... but ...
|
254
|
+
# If no user is found, let's leave it up to the auth solution to redirect the user to a login page.
|
255
|
+
unless user.nil?
|
256
|
+
begin
|
257
|
+
klazz = eval(class_name)
|
258
|
+
rescue => e
|
259
|
+
# No need to throw this exception here. Just log the error.
|
260
|
+
# It would appear whenever Authorizer was used when a user isn't logged in.
|
261
|
+
# That just is too much ...
|
262
|
+
s = "Could not eval class '#{class_name}'. It presumably does not exist. Maybe you mistyped its name? Error was: #{e.inspect}"
|
263
|
+
#raise ArgumentError.new(s) if klazz.nil?
|
264
|
+
Rails.logger.warn("#{__FILE__}: #{__LINE__}: " + s)
|
265
|
+
end
|
241
266
|
end
|
242
267
|
# oooo ooo ooo ___ --- === __- --_- ++_+_ =--- +- =+=-=- =-= <--- ice beam!
|
243
268
|
unless klazz.nil?
|
@@ -278,6 +303,7 @@ module Authorizer
|
|
278
303
|
ret
|
279
304
|
end
|
280
305
|
|
306
|
+
# Find the ObjectRole record that matches object (first argument) and user (second argument).
|
281
307
|
def self.find_object_role(object, user)
|
282
308
|
return nil if object.nil? || user.nil?
|
283
309
|
|
@@ -309,19 +335,24 @@ module Authorizer
|
|
309
335
|
|
310
336
|
def self.check_user(user)
|
311
337
|
ret = true
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
338
|
+
|
339
|
+
# YES YES I know it's a good habit to check for current_user, but I've decided not to raise anything
|
340
|
+
# and make this method basically void.
|
341
|
+
# Why?
|
342
|
+
# Let the auth mechanism redirect the user if no user is present.
|
343
|
+
# I think that's the proper way to do things.
|
344
|
+
|
345
|
+
# if user.nil?
|
346
|
+
# raise Authorizer::RuntimeException.new "User cannot be nil. Maybe you should specify authorizer_options = { :user => user } if you are not calling from a controller?"
|
347
|
+
# end
|
348
|
+
#
|
349
|
+
# unless user.is_a?(ActiveRecord::Base)
|
350
|
+
# raise Authorizer::RuntimeException.new "User must inherit from ActiveRecord::Base"
|
351
|
+
# end
|
352
|
+
#
|
353
|
+
# if user.new_record?
|
354
|
+
# raise Authorizer::RuntimeException.new "User must be saved"
|
355
|
+
# end
|
325
356
|
|
326
357
|
ret
|
327
358
|
end
|
@@ -17,5 +17,29 @@ module Authorizer
|
|
17
17
|
object_role.destroy
|
18
18
|
end
|
19
19
|
end
|
20
|
+
|
21
|
+
# This is a Rails only feature:
|
22
|
+
# Single Table Inheritance (STI) is implemented using the Type column.
|
23
|
+
# The 'type' column contains the name of the subclass of the table the record is in.
|
24
|
+
# For example, Dog is a subclass of Animal.
|
25
|
+
# If we have a Dog object here that changes its 'type' to Animal, the ObjectRole must be updated to reflect the new class name.
|
26
|
+
def after_update(object)
|
27
|
+
type = object.try(:read_attribute, :type)
|
28
|
+
# Big chance the object doesn't even have the 'type' attribute. In that case, do nothing.
|
29
|
+
unless type.blank?
|
30
|
+
object_class_name = object.class.to_s
|
31
|
+
# This is how we gonna detect that the type has changed:
|
32
|
+
# object_class_name should be different than type.
|
33
|
+
unless type.eql?(object_class_name)
|
34
|
+
object_roles = ObjectRole.find_all_by_object(object)
|
35
|
+
# Walk through the object roles associated with this object
|
36
|
+
for object_role in object_roles
|
37
|
+
# update it!
|
38
|
+
# it should reflect the new type.
|
39
|
+
object_role.update_attributes!( :klazz_name => type )
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
20
44
|
end
|
21
45
|
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:
|
5
|
-
prerelease:
|
4
|
+
hash: 25
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- CmdJohnson
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
19
|
-
default_executable:
|
18
|
+
date: 2011-09-27 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: options_checker
|
@@ -40,14 +39,13 @@ dependencies:
|
|
40
39
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
40
|
none: false
|
42
41
|
requirements:
|
43
|
-
- -
|
42
|
+
- - ~>
|
44
43
|
- !ruby/object:Gem::Version
|
45
|
-
hash:
|
44
|
+
hash: 27
|
46
45
|
segments:
|
47
46
|
- 2
|
48
|
-
-
|
49
|
-
|
50
|
-
version: 2.8.0
|
47
|
+
- 12
|
48
|
+
version: "2.12"
|
51
49
|
type: :development
|
52
50
|
version_requirements: *id002
|
53
51
|
description: |-
|
@@ -110,7 +108,6 @@ files:
|
|
110
108
|
- lib/authorizer/user_observer.rb
|
111
109
|
- app/models/object_role.rb
|
112
110
|
- rails/init.rb
|
113
|
-
has_rdoc: true
|
114
111
|
homepage: https://github.com/cmdjohnson/authorizer
|
115
112
|
licenses: []
|
116
113
|
|
@@ -141,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
138
|
requirements: []
|
142
139
|
|
143
140
|
rubyforge_project: authorizer
|
144
|
-
rubygems_version: 1.
|
141
|
+
rubygems_version: 1.8.10
|
145
142
|
signing_key:
|
146
143
|
specification_version: 3
|
147
144
|
summary: Authorizer is a gem for Ruby (in conjunction with Rails 2.3) that does authorization for you on a per-object basis
|