public
Description: An authorization and workflow mechanism built on top of restful_authentication
Clone URL: git://github.com/jbarket/restful-authorization.git
Search Repo:
Initial version!
Jonathan Barket (author)
Thu Apr 24 16:03:45 -0700 2008
commit  078262e84d64868260b9f056d1b81c84bdf0aa6c
tree    654bf151ee6948396c7590a2fc8a848417534de8
...
 
 
 
 
 
...
1
2
3
4
5
0
@@ -0,0 +1,5 @@
0
+* 0.01 - 04/21/2008
0
+
0
+ - Initial release
0
+ - Migrated from svn to git (Google Code -> GitHub)
0
+
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
0
@@ -0,0 +1,22 @@
0
+Copyright (c) 2008 Jonathan Barket
0
+
0
+role_requirement forked code is Copyright (c) 2008 Timothy Curtis Harper
0
+
0
+Permission is hereby granted, free of charge, to any person obtaining
0
+a copy of this software and associated documentation files (the
0
+"Software"), to deal in the Software without restriction, including
0
+without limitation the rights to use, copy, modify, merge, publish,
0
+distribute, sublicense, and/or sell copies of the Software, and to
0
+permit persons to whom the Software is furnished to do so, subject to
0
+the following conditions:
0
+
0
+The above copyright notice and this permission notice shall be
0
+included in all copies or substantial portions of the Software.
0
+
0
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
0
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
0
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
0
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
0
@@ -0,0 +1,130 @@
0
+Restful Authorization Generator
0
+===============================
0
+
0
+restful-authorization is a generator designed to extend Rick Olson's
0
+restful_authentication.
0
+
0
+It provides a mechanism for custom authorization based access control,
0
+as well as a redirection system capable of allowing users to follow
0
+complex workflows that extend beyond simple authentication.
0
+
0
+Programmatically, it collects all of the authorization requirements
0
+given for a particular controller and creates a single before_filter
0
+to handle them.
0
+
0
+This plugin is a descendent of Tim C Harper's role-requirement, and
0
+none of this would be possible without his code base, or his willingness
0
+to allow me to make changes to a production ready generator.
0
+
0
+To begin using restful-authorization, run:
0
+
0
+ ./script/generate authorization role user
0
+
0
+where role is your intended Role model name and user is the name of your
0
+User model in restful_authentication.
0
+
0
+Syntax
0
+======
0
+
0
+restful-authorization is called like this:
0
+
0
+ require_foo "value", [optional keys], [redirect or render]
0
+
0
+where value is what require_foo is attempting to validate, [optional keys] are
0
+limiting methods, and [render or redirect] handle authorization failures.
0
+
0
+Basic Use
0
+=========
0
+
0
+restful-authorization uses method_missing to provide easy customization.
0
+
0
+Out of the box, it has two methods that can be called at the top of your
0
+controllers:
0
+
0
+ authorize_role "role"
0
+ authorize_state "state"
0
+
0
+restful-authorization catches any method called authorize_foo as long
0
+as it has a corresponding foo_is_authorized? method that returns true
0
+or false.
0
+
0
+An example foo_is_authorized? might look like this:
0
+
0
+ def foo_is_authorized?(user, value)
0
+ user.foo == value
0
+ end
0
+
0
+authorize_role uses the built in role system inherited from role-requirement,
0
+while authorize_state matches the state field from your user model. Out of
0
+the box, this example was designed for acts_as_state_machine.
0
+
0
+Both of these methods live in the AuthorizationSecurityClassMethods module.
0
+Once generated, authorized_system.rb can be edited directly to add new methods,
0
+or you can extend AuthorizationSecurityClassMethods elsewhere.
0
+
0
+Order of execution is directly related to placement in the controller. In
0
+the example above, the user will be checked for the role "role" and then
0
+the state "state." If the user fails to meet either condition, they will
0
+be directed as necessary with role issues handled before state issues.
0
+
0
+Limiting Methods
0
+================
0
+
0
+Individual authorization requirements can be limited via a number of keys:
0
+
0
+ * Restrict only the create and new actions
0
+ :only => [:create, :new]
0
+
0
+ * Restrict all actions except index and show
0
+ :except => [:index, :show]
0
+
0
+ * Restrict if this condition is met. The condition is a Proc or a string.
0
+ :if => Proc.new { condition == true }
0
+
0
+ * The inverse of :if
0
+ :unless => Proc.new { condition == true }
0
+
0
+
0
+Workflow Management
0
+===================
0
+
0
+Workflow can be managed in two different ways:
0
+
0
+ * URL Redirection sends the user to a new URL that can be a string, a hash
0
+ of parameters, or a named route passed as a symbol (:named_route_path)
0
+
0
+ :redirect_url => "/session/new"
0
+
0
+ * Status Control displays the contents of :render_url, which is a hash
0
+ of parameters for render, with the provided status code (404, 500).
0
+ This is useful for preventing prying eyes from seeing things that
0
+ shouldn't be available to the public.
0
+
0
+ :render_url => { :file => "#{RAILS_ROOT}/public/404.html" }, :status => "404"
0
+
0
+If :redirect_url is not specified, restful_authentication's access_denied will
0
+handle url redirections. If :render_url is not specified, but :status is, a
0
+blank page will be rendered with the given status.
0
+
0
+Forward flow is managed using restful_authentication's redirect_back_or_default
0
+method rather than redirect_to. Upon completion of a form, instead of doing a
0
+redirect_to object_path, call redirect_back_or_default(object_path).
0
+
0
+If this is unrelated to the authorization mechanism of the site, the user will
0
+be redirected to the show view. If it's part of a more complex workflow, the user
0
+will be redirected to the page that previously sent them here for failing
0
+authorization.
0
+
0
+A simple workflow for a shopping cart might go as follows:
0
+
0
+ 1. Quentin, a user without an account, locates items and adds them to his cart
0
+
0
+ 2. He attempts to checkout, which fails authorization and redirects him to
0
+ the registration page.
0
+
0
+ 3. After registering, he's redirected to the checkout page, which fails on a new
0
+ condition and redirects him to the account activation page. Quentin activates
0
+ and is now forwarded back to the checkout page.
0
+
0
+ 4. Quentin is now able to complete his transaction and purchase the items
0
+
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
0
@@ -0,0 +1,148 @@
0
+require( File.join( File.dirname(__FILE__), "../authorized_generator_helpers" ))
0
+
0
+class AuthorizedGenerator < Rails::Generator::NamedBase
0
+
0
+ include AuthorizedGeneratorHelpers
0
+
0
+ attr_accessor :roles_model_name,
0
+ :roles_table_name,
0
+ :users_table_name,
0
+ :users_model_name,
0
+ :next_user_id
0
+
0
+ def initialize(runtime_args, runtime_options = {})
0
+ super
0
+ @roles_model_name = (runtime_args[0] || "Role").classify
0
+ @users_model_name = (runtime_args[1] || "User").classify
0
+
0
+ @roles_table_name = @roles_model_name.tableize
0
+ @users_table_name = @users_model_name.tableize
0
+
0
+ puts "Generating authorization for #{@users_model_name}"
0
+ end
0
+
0
+ def manifest
0
+ record do |m|
0
+ modify_or_add_user_fixtures(m)
0
+ add_roles_and_join_table_fixtures(m)
0
+
0
+ add_method_to_user_model(m)
0
+
0
+ add_role_model(m)
0
+ add_dependencies_to_application_rb
0
+ add_authorized_system(m)
0
+ add_migration(m) unless options[:skip_migration]
0
+ end
0
+ end
0
+
0
+ def add_role_model(m)
0
+ # add the Role model
0
+ m.template 'role_model.rb.erb', roles_model_filename
0
+ end
0
+
0
+ def add_method_to_user_model(m)
0
+ content_for_insertion = render_template("_has_role.erb")
0
+ # modify the User model unless it's already got AuthorizedSystem code in there
0
+ if insert_content_after(users_model_filename,
0
+ Regexp.new("class +#{users_model_name}"),
0
+ content_for_insertion,
0
+ :unless => lambda { |content| content.include? "def has_role?"; }
0
+ )
0
+ puts "Added the following to the top of #{users_model_filename}:\n#{content_for_insertion}\n\n"
0
+ else
0
+ puts "Not modifying #{users_model_filename} because it appears that the funtion has_role? already exists.\n\n"
0
+ end
0
+ end
0
+
0
+ def modify_or_add_user_fixtures(m)
0
+ if (File.exists?(users_fixture_filename))
0
+ users_fixtures_content = File.read users_fixture_filename
0
+ users_fixtures = YAML.load(users_fixtures_content)
0
+
0
+ begin
0
+ throw "Can't understand whatever is in #{users_fixture_filename}" unless Hash===users_fixtures
0
+
0
+ unless users_fixtures.has_key?("admin")
0
+ @next_user_id = (users_fixtures.collect{ |k, params| params["id"].to_i}.max||0) + 1
0
+ output = users_fixtures_content + "\n" + render_template("users_admin_fixture_with_roles.yml")
0
+
0
+ # prevent generator from truncating the whole file if something goes wrong.
0
+ if output.length > users_fixtures_content.length
0
+ File.open(users_fixture_filename, "w") {|f| f.write(output) }
0
+ end
0
+ else
0
+ @next_user_id = users_fixtures["admin"]["id"].to_i
0
+ end
0
+ rescue
0
+ skip_fixtures = true
0
+ end
0
+ else
0
+ # users.yml doesn't exist. Generate it from scratch
0
+ @next_user_id = 1
0
+
0
+ m.template 'users_admin_fixture_with_roles.yml',
0
+ File.join('test/fixtures', "#{users_table_name}.yml")
0
+ end
0
+
0
+ end
0
+
0
+ def add_migration(m)
0
+ m.migration_template 'migration.rb.erb', 'db/migrate', :assigns => {
0
+ :migration_name => "Create#{roles_model_name.pluralize.gsub(/::/, '')}"
0
+ }, :migration_file_name => "create_#{roles_table_name}"
0
+ end
0
+
0
+ def add_roles_and_join_table_fixtures(m)
0
+ m.template 'roles_users.yml',
0
+ File.join('test/fixtures', "#{habtm_name}.yml")
0
+ m.template 'roles.yml',
0
+ File.join('test/fixtures', "#{roles_table_name}.yml")
0
+ end
0
+
0
+ def add_authorized_system(m)
0
+ m.template 'authorized_system.rb.erb',
0
+ File.join('lib', "authorized_system.rb")
0
+ end
0
+
0
+ def add_dependencies_to_application_rb
0
+ app_filename = "#{RAILS_ROOT}/app/controllers/application.rb"
0
+
0
+ restful_authentication_content = <<EOF
0
+ # AuthenticatedSystem must be included for AuthorizedSystem and is provided by restful_authentication
0
+ include AuthenticatedSystem
0
+EOF
0
+
0
+ restful_authorization_content = <<EOF
0
+ include AuthorizedSystem
0
+EOF
0
+
0
+ insert_content_after(
0
+ app_filename,
0
+ /class +ApplicationController/,
0
+ restful_authentication_content,
0
+ :unless => lambda {|content| /include +AuthenticatedSystem/.match(content) }
0
+ ) && puts("Added ApplicationController include to #{app_filename}")
0
+
0
+ insert_content_after(
0
+ app_filename,
0
+ /include +AuthenticatedSystem/,
0
+ restful_authorization_content,
0
+ :unless => lambda {|content| /include +AuthorizedSystem/.match(content) }
0
+ ) && puts("Addded AuthorizedSystem include to #{app_filename}")
0
+
0
+ end
0
+
0
+ def users_model_filename; "app/models/#{users_model_name.underscore}.rb"; end;
0
+ def users_name; "#{users_model_name.downcase}"; end;
0
+ def habtm_name; [roles_table_name, users_table_name].sort * "_"; end
0
+ def roles_foreign_key; roles_table_name.singularize.foreign_key; end
0
+ def roles_model_filename; "app/models/#{roles_model_name.underscore}.rb"; end;
0
+ def users_foreign_key; users_table_name.singularize.foreign_key; end
0
+ def users_fixture_filename; "test/fixtures/#{users_table_name}.yml"; end;
0
+
0
+ protected
0
+ def banner
0
+ "Usage: #{$0} authorized RoleModelName [TargetUserModelName]"
0
+ end
0
+
0
+end
0
\ No newline at end of file
...
 
 
 
 
 
 
 
 
 
 
 
...
1
2
3
4
5
6
7
8
9
10
11
0
@@ -0,0 +1,11 @@
0
+
0
+ has_and_belongs_to_many :<%=roles_table_name%>
0
+
0
+ # has_role? simply needs to return true or false whether a user has a role or not.
0
+ # It may be a good idea to have "admin" roles return true always
0
+ def has_role?(role_in_question)
0
+ @<%roles_table_name%>_list ||= self.<%=roles_table_name%>.collect(&:name).collect(&:downcase)
0
+ return true if @<%roles_table_name%>_list.include?("admin")
0
+ (@<%roles_table_name%>_list.include?(role_in_question.downcase.to_s))
0
+ end
0
+
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
0
@@ -0,0 +1,243 @@
0
+module AuthorizedSystem
0
+ def self.included(base)
0
+ base.send :class_inheritable_array, :auth_requirements
0
+ base.send :include, AuthorizationSecurityInstanceMethods
0
+ base.send :extend, AuthorizationSecurityClassMethods
0
+ base.send :helper_method, :url_options_authenticate?
0
+ base.send :helper_method, :next_authorized_url?
0
+
0
+ base.send :auth_requirements=, []
0
+
0
+ end
0
+
0
+ module AuthorizationSecurityClassMethods
0
+
0
+ # This is the core of AuthorizedSystem.
0
+ #
0
+ # By calling require_authorization at the top of your
0
+ # controller via dynamically create methods, you can
0
+ # test for a variety of conditions.
0
+ #
0
+ # Example Usage:
0
+ #
0
+ # require_role "contractor"
0
+ # require_role "admin", :only => :destroy # don't allow contractors to destroy
0
+ #
0
+ # require_state "active", :only => [:new, :create] # only allow active <%= users_name %>s to create new items
0
+ #
0
+ #
0
+ # Valid options
0
+ #
0
+ # * :only - authorization is only required for these actions
0
+ # * :except - authorization is required for all other actions
0
+ # * :if - a Proc or a string to evaluate; the authorization is required if it returns true
0
+ # * :unless - the inverse of :if
0
+ #
0
+ # * :redirect_url - takes a named route as a symbol (:new_example_path), string "/example/new",
0
+ # or hash { :controller => "example", :action => "new" }
0
+ #
0
+ # The <%= users_name %> is redirected to :redirect_url if authorization fails. If nothing is specified, it defaults
0
+ # to restful_authentication's access_denied
0
+ #
0
+ # * :render_url - takes a hash of parameters to pass to render such as
0
+ # { :file => "#{RAILS_ROOT}/public/404.html" }
0
+ #
0
+ # * :status - takes a status code ("304", "404", "500") as a string
0
+ #
0
+ # Rather than redirecting the <%= users_name %>, the action specified in :render_url is rendered with the
0
+ # given status. If no :render_url is specified, it renders a blank page with the status code given.
0
+ #
0
+ def require_authorization(type, values, options = {})
0
+ options.assert_valid_keys(:if, :unless, :only, :except, :redirect_url, :render_url, :status)
0
+
0
+ # only declare the before filter once
0
+ unless @before_filter_declared ||= false
0
+ @before_filter_declared = true
0
+ before_filter :check_authorization
0
+ end
0
+
0
+ # convert values to an array if it isn't already one
0
+ values = [values] unless Array === values
0
+
0
+ # convert any keys into symbols
0
+ for key in [:only, :except]
0
+ if options.has_key?(key)
0
+ options[key] = [options[key]] unless Array === options[key]
0
+ options[key] = options[key].compact.collect{|v| v.to_sym}
0
+ end
0
+ end
0
+
0
+ self.auth_requirements||=[]
0
+ self.auth_requirements << {:type => type, :values => values, :options => options }
0
+ end
0
+
0
+ # The method_missing helper for AuthorizedSystem catches
0
+ # all class level methods beginning with authorize_foo
0
+ # that have a matching foo_is_authorized? method.
0
+ #
0
+ # It then executes request_authorization and passes
0
+ # foo as the authorization type.
0
+ def method_missing(method_id, *arguments)
0
+ super unless method_id.to_s.match(/^authorize_([_a-zA-Z]\w*)$/) and respond_to?("#{method_id.to_s.gsub(/^authorize_/,'')}_is_authorized?")
0
+ require_authorization(method_id.to_s.gsub(/^authorize_/,''), *arguments )
0
+ end
0
+
0
+ # This method takes a <%= users_name %>, params (which includes a :controller
0
+ # and :action) and a binding. It evalutes all authorization
0
+ # requirements for this particular route and returns the
0
+ # :redirect_url and :status for the first requirement it fails
0
+ # to meet.
0
+ def next_authorized_url_for?(<%= users_name %>, params = {}, binding = self.binding)
0
+ return nil unless Array===self.auth_requirements
0
+ self.auth_requirements.each do |requirement|
0
+ type = requirement[:type]
0
+ values = requirement[:values]
0
+ options = requirement[:options]
0
+
0
+ # handle the restriction keys associated with this requirement
0
+ if options.has_key?(:only)
0
+ next unless options[:only].include?( (params[:action]||"index").to_sym)
0
+ end
0
+
0
+ if options.has_key?(:except)
0
+ next if options[:except].include?( (params[:action]||"index").to_sym)
0
+ end
0
+
0
+ if options.has_key?(:if)
0
+ next unless ( String===options[:if] ? eval(options[:if], binding) : options[:if].call(params) )
0
+ end
0
+
0
+ if options.has_key?(:unless)
0
+ next if ( String===options[:unless] ? eval(options[:unless], binding) : options[:unless].call(params) )
0
+ end
0
+
0
+ if options.has_key?(:render_url) && options.has_key?(:status)
0
+ options[:redirect_url] = options[:render_url]
0
+ end
0
+
0
+ # run the authorization test method associated with the current requirement
0
+ values.each { |value|
0
+ return { :url => options[:redirect_url], :status => options[:status] } unless send("#{type}_is_authorized?", <%= users_name %>, value)
0
+ } unless (<%= users_name %>==:false || <%= users_name %>==false)
0
+ end
0
+
0
+ return nil
0
+ end
0
+
0
+
0
+ # This is a wrapper method for next_authorized_url_for? that makes
0
+ # up the core of AuthorizedSystem. If next_authorized_url_for?
0
+ # returns nil, the <%= users_name %> is authorized to view the current page.
0
+ def <%= users_name %>_authorized_for?(<%= users_name %>, params = {}, binding = self.binding)
0
+ unless next_authorized_url_for?(<%= users_name %>, params, binding)
0
+ return true
0
+ end
0
+
0
+ return false
0
+ end
0
+
0
+ def reset_auth_requirements!
0
+ self.auth_requirements.clear
0
+ end
0
+
0
+
0
+ # == Authorization Test Methods
0
+ #
0
+ # These methods correspond to types stored in auth_requirement.
0
+ #
0
+ # For a particular form of authorization to exist, it must have
0
+ # a method here in the format #{type}_is_authorized?(<%= users_name %>, value)
0
+ # that returns a boolean value
0
+ #
0
+ # next_authorized_url_for? will dynamically allow for new
0
+ # authorization requirements based on these methods. In other words,
0
+ # if the following method existed:
0
+ #
0
+ # def foo_is_authorized?(<%= users_name %>, value)
0
+ # true
0
+ # end
0
+ #
0
+ # the dynamic method authorize_foo would be available in your
0
+ # controllers.
0
+
0
+ # This method invokes the generated has_role? method to
0
+ # determine if a <%= users_name %> has a given role. By default,
0
+ # has_role? downcases both the stored roles and the
0
+ # requested match, so Admin == admin == ADMIN and so on.
0
+ def role_is_authorized?(<%= users_name %>, value)
0
+ <%= users_name %>.has_role?(value)
0
+ end
0
+
0
+ # This method is provided as an example of authorization beyond
0
+ # the internal role system. It verifies that the <%= users_name %> has
0
+ # a field "state" that matches the required value. This works
0
+ # out of the box with Scott Barron's acts_as_state_machine.
0
+ def state_is_authorized?(<%= users_name %>, value)
0
+ <%= users_name %>.state.downcase == value.downcase
0
+ end
0
+
0
+ end
0
+
0
+ module AuthorizationSecurityInstanceMethods
0
+ # Verifies that restful_authentication is properly required before restful-authorization gets going
0
+ def self.included(base)
0
+ raise "Because restful-authorization extends restful_authentication, AuthenticatedSystem must be included before first before AuthorizedSystem!" unless base.included_modules.include?(AuthenticatedSystem)
0
+ end
0
+
0
+ # When <%= users_name %>_authorized_for fails, access_denied stores the current location
0
+ # in the session and then handles :redirect_to and :status as described in
0
+ # the require_authorization documentation.
0
+ #
0
+ # It's important to use restful_authentication's redirect_back_or_default
0
+ # instead of redirect_to to make sure that the workflow can move forward
0
+ # as well as backward.
0
+ def access_denied
0
+ store_location
0
+ if status = self.next_authorized_url?(params)[:status]
0
+ if self.next_authorized_url?(params)[:url]
0
+ render self.next_authorized_url?(params)[:url], :status => status
0
+ else
0
+ render :nothing => true, :status => status
0
+ end
0
+ else
0
+ if self.next_authorized_url?(params)[:url]
0
+ redirect_to(Symbol===self.next_authorized_url?(params)[:url] ? eval(self.next_authorized_url?(params)[:url].to_s) : self.next_authorized_url?(params)[:url])
0
+ else
0
+ super
0
+ end
0
+ end
0
+ end
0
+
0
+ # This is the before filter called by require_authorization
0
+ def check_authorization
0
+ return access_denied unless self.url_options_authenticate?(params)
0
+ true
0
+ end
0
+
0
+ protected
0
+ # This calls <%= users_name %>_authorized_for? on the given parameters. If no controller
0
+ # is specified, it defaults to the current one.
0
+ def url_options_authenticate?(params = {})
0
+ params = params.symbolize_keys
0
+ if params[:controller]
0
+ base = eval("#{params[:controller]}_controller".classify)
0
+ else
0
+ base = self.class
0
+ end
0
+ base.<%= users_name %>_authorized_for?(current_<%= users_name %>, params, binding)
0
+ end
0
+
0
+ # This calls next_authorized_url_for? on the given parameters. If no controller
0
+ # is specified, it defaults to the current one.
0
+ def next_authorized_url?(params = {})
0
+ params = params.symbolize_keys
0
+ if params[:controller]
0
+ base = eval("#{params[:controller]}_controller".classify)
0
+ else
0
+ base = self.class
0
+ end
0
+ base.next_authorized_url_for?(current_<%= users_name %>, params, binding)
0
+ end
0
+
0
+ end
0
+ end
0
\ No newline at end of file
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
0
@@ -0,0 +1,19 @@
0
+class <%= migration_name %> < ActiveRecord::Migration
0
+ def self.up
0
+ create_table "<%= roles_table_name %>" do |t|
0
+ t.string :name
0
+ end
0
+
0
+ # generate the join table
0
+ create_table "<%= habtm_name %>", :id => false do |t|
0
+ t.integer "<%= roles_foreign_key %>", "<%= users_foreign_key %>"
0
+ end
0
+ add_index "<%= habtm_name %>", "<%= roles_foreign_key %>"
0
+ add_index "<%= habtm_name %>", "<%= users_foreign_key %>"
0
+ end
0
+
0
+ def self.down
0
+ drop_table "<%= roles_table_name %>"
0
+ drop_table "<%= habtm_name %>"
0
+ end
0
+end
0
\ No newline at end of file
...
 
 
 
0
...
1
2
3
4
0
@@ -0,0 +1,3 @@
0
+class <%= class_name %> < ActiveRecord::Base
0
+
0
+end
0
\ No newline at end of file
...
 
 
 
 
 
 
0
...
1
2
3
4
5
6
7
0
@@ -0,0 +1,6 @@
0
+admin_role:
0
+ id: 1
0
+ name: admin
0
+user_role:
0
+ id: 2
0
+ name: user
0
\ No newline at end of file
...
 
 
 
0
...
1
2
3
4
0
@@ -0,0 +1,3 @@
0
+admin_is_admin:
0
+ <%=users_foreign_key%>: <%= next_user_id %> # admin
0
+ <%=roles_foreign_key%>: 1 # admin role
0
\ No newline at end of file
...
 
 
 
 
 
 
 
 
0
...
1
2
3
4
5
6
7
8
9
0
@@ -0,0 +1,8 @@
0
+admin:
0
+ id: <%= next_user_id %>
0
+ login: admin
0
+ email: admin@example.com
0
+ salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
0
+ crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test
0
+ # activation_code: adminscode # only if you're activating new signups
0
+ created_at: <%%= 1.days.ago.to_s :db %>
0
\ No newline at end of file
...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
0
@@ -0,0 +1,33 @@
0
+module AuthorizedGeneratorHelpers
0
+
0
+ def insert_content_after(filename, regexp, content_for_insertion, options = {})
0
+ content = File.read(filename)
0
+ options[:unless] ||= lambda {false }
0
+ # already have the function? Don't generate it twice
0
+ unless options[:unless].call(content)
0
+ # find the line that has the model declaration
0
+ lines = content.split("\n")
0
+ found_line = nil
0
+
0
+ 0.upto(lines.length-1) {|line_number|
0
+ found_line = line_number if regexp.match(lines[line_number])
0
+ }
0
+ if found_line
0
+ # insert the rest of these lines after the found line
0
+ lines.insert(found_line+1, content_for_insertion)
0
+ content = lines * "\n"
0
+
0
+ File.open(filename, "w") {|f| f.puts content }
0
+ return true
0
+ end
0
+ else
0
+ return false
0
+ end
0
+ end
0
+
0
+ def render_template(name)
0
+ template = File.read( File.join( File.dirname(__FILE__), "authorized/templates", name))
0
+ ERB.new(template, nil, "-").result(binding)
0
+ end
0
+
0
+end
0
\ No newline at end of file
...
 
0
...
1
2
0
@@ -0,0 +1 @@
0
+puts IO.read(File.join(File.dirname(__FILE__), 'README'))
0
\ No newline at end of file

Comments

    No one has commented yet.