tarsolya-declarative_authorization 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/CHANGELOG +139 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +503 -0
  4. data/Rakefile +43 -0
  5. data/app/controllers/authorization_rules_controller.rb +259 -0
  6. data/app/controllers/authorization_usages_controller.rb +23 -0
  7. data/app/helpers/authorization_rules_helper.rb +218 -0
  8. data/app/views/authorization_rules/_change.erb +58 -0
  9. data/app/views/authorization_rules/_show_graph.erb +37 -0
  10. data/app/views/authorization_rules/_suggestions.erb +48 -0
  11. data/app/views/authorization_rules/change.html.erb +169 -0
  12. data/app/views/authorization_rules/graph.dot.erb +68 -0
  13. data/app/views/authorization_rules/graph.html.erb +40 -0
  14. data/app/views/authorization_rules/index.html.erb +17 -0
  15. data/app/views/authorization_usages/index.html.erb +36 -0
  16. data/authorization_rules.dist.rb +20 -0
  17. data/config/routes.rb +7 -0
  18. data/garlic_example.rb +20 -0
  19. data/init.rb +5 -0
  20. data/lib/declarative_authorization.rb +15 -0
  21. data/lib/declarative_authorization/authorization.rb +681 -0
  22. data/lib/declarative_authorization/development_support/analyzer.rb +252 -0
  23. data/lib/declarative_authorization/development_support/change_analyzer.rb +253 -0
  24. data/lib/declarative_authorization/development_support/change_supporter.rb +620 -0
  25. data/lib/declarative_authorization/development_support/development_support.rb +243 -0
  26. data/lib/declarative_authorization/helper.rb +60 -0
  27. data/lib/declarative_authorization/in_controller.rb +623 -0
  28. data/lib/declarative_authorization/in_model.rb +162 -0
  29. data/lib/declarative_authorization/maintenance.rb +198 -0
  30. data/lib/declarative_authorization/obligation_scope.rb +345 -0
  31. data/lib/declarative_authorization/rails_legacy.rb +14 -0
  32. data/lib/declarative_authorization/reader.rb +496 -0
  33. data/test/authorization_test.rb +971 -0
  34. data/test/controller_filter_resource_access_test.rb +511 -0
  35. data/test/controller_test.rb +465 -0
  36. data/test/dsl_reader_test.rb +173 -0
  37. data/test/helper_test.rb +171 -0
  38. data/test/maintenance_test.rb +46 -0
  39. data/test/model_test.rb +1694 -0
  40. data/test/schema.sql +54 -0
  41. data/test/test_helper.rb +137 -0
  42. metadata +118 -0
data/CHANGELOG ADDED
@@ -0,0 +1,139 @@
1
+ * Omnipotent roles [timcharper]
2
+
3
+ * Meaningful error in case of missing authorization rules file [timcharper]
4
+
5
+ * Rails 3 support [sb]
6
+
7
+ * Support shallow nested resources [jjb]
8
+
9
+ * Allow multiple authorization rules files [kaichen]
10
+
11
+ ** RELEASE 0.4 (November 15, 2009) **
12
+
13
+ * Implemented controller namespace handling [sb]
14
+
15
+ * Improved if_attribute to allow nesting of has_many associations [sb]
16
+
17
+ * Improved if_permitted_to: allow has_many associations and improved context inference [sb]
18
+
19
+ * Added option on handling non-existant auto-loaded object [sb]
20
+
21
+ * Added with_user as module method [sb]
22
+
23
+ * Change support i18n [sb]
24
+
25
+ ** RELEASE 0.3.2.3 (October 12, 2009) **
26
+
27
+ * Switched to gemcutter [sb]
28
+
29
+ * Fixed has_role? for guest user. Closes #8 [sb]
30
+
31
+ * Fixed unnecessary DB query with named scopes [sb, ledermann]
32
+
33
+ * Change support: suggestions: grouping, sorting by affected users [sb]
34
+
35
+ * Fixed context inference from AR objects for STI by switching to #class.name.tableize [sb]
36
+
37
+ * Allow multiple contexts as arguments to has_permission_on [Jeroen van Dijk]
38
+
39
+ ** RELEASE 0.3.2.2 (August 27, 2009) **
40
+
41
+ * Fix without_access_control test cases [sb]
42
+
43
+ * Fixed error on debug logging (Closes #6) [sb]
44
+
45
+ * Fixed without_access_control instance method in TestHelper [sb]
46
+
47
+ ** RELEASE 0.3.2.1 (August 14, 2009) **
48
+
49
+ * Fix gemspec for Rdoc generation [sb]
50
+
51
+ ** RELEASE 0.3.2 (August 13, 2009) **
52
+
53
+ * Fix for model-level permitted_to?/! [sb]
54
+
55
+ ** RELEASE 0.3.1 (August 12, 2009) **
56
+
57
+ * Change Support: Suggestion grouping, sort by affected users [sb]
58
+
59
+ * Changed context derived from objects to #class.name.tableize to fix STI [sb]
60
+
61
+ * Simplified controller authorization with filter_resource_access [sb]
62
+
63
+ * Allow passing explicit context in addition to object in permitted_to? [Olly Lylo, sb]
64
+
65
+ * Change Supporter: suggest changes to authorization rules [sb]
66
+
67
+ * Added permitted_to!/? in model [Eike Carls]
68
+
69
+ * New test helper: should_(not_)_be_allowed_to(privilege, object_or_context) [sb]
70
+
71
+ ** RELEASE 0.3 (April 20, 2009) **
72
+
73
+ * New option :join_by for has_permission_on to allow AND'ing of statements in one has_permission_on block [sb]
74
+
75
+ * Allow using_access_control to be called directly on ActiveRecord::Base, globally enabling model security [sb]
76
+
77
+ * New operator: intersects_with, comparing two Enumerables in if_attribute [sb]
78
+
79
+ * Improved if_permitted_to syntax: if the attribute is left out, permissions are checked on for the current object [sb]
80
+
81
+ * Added #has_role_with_hierarchy? method to retrieve explicit and calculated roles [jeremyf]
82
+
83
+ * Added a simple rules analyzer to help improve authorization rules [sb]
84
+
85
+ * Gemified plugin. Needed to restructure the lib path contents [sb]
86
+
87
+ * Added handling of Authorization::AuthorizationInController::ClassMethods.filter_access_to parameters that are of the form [:show, :update] instead of just :show, :update. [jeremyf]
88
+
89
+ * Added authorization usage helper for checking filter_access_to usage in controllers [sb]
90
+
91
+ * Added a authorization rules browser. See README for more information [sb]
92
+
93
+ * Added Model.using_access_control? to check if a model has model security activated [sb]
94
+
95
+ * Changed Authorization::ObligationScope#map_table_alias_for [Brian Langenfeld]
96
+ * Fixed to prevent bad aliases from being produced.
97
+
98
+ * Changed Authorization::Attribute#validate? [Brian Langenfeld]
99
+ * Encountering a nil value when evaluating an attribute now raises a NilAttributeValueError, instead of an AuthorizationError. We leave it to the caller to decide what to do about it.
100
+
101
+ * Changed Authorization::Engine#permit! [Brian Langenfeld]
102
+ * We now convert incoming privileges to symbols (e.g. 'read' is made equivalent to :read). This ensures the privileges will match those defined in the authorization rules file.
103
+ * The method now properly infers context when checking against an association (e.g. user.posts). We do this by leveraging ActiveRecord builder method 'new' to instantiate a proper object we can work with.
104
+ * When testing rules for positive results (via Authorization::Attribute#validate?), we now rescue NilAttributeValueError exceptions, simply causing the rule to return a negative result (instead of barfing).
105
+
106
+ * Changed Authorization::ObligationScope#rebuild_join_options! [Brian Langenfeld]
107
+ * If we're dealing with multiple obligations we have to check (i.e. ones that result in OR'd conditions), we now use :include instead of :joins for our generated scope. This does seem like a kludge, but until ActiveRecord scopes support unions (for checking obligations individually and consolidating the results), we don't have much choice. Something to revisit later, for sure.
108
+
109
+ ** RELEASE 0.2 (February 2, 2009) **
110
+
111
+ * added negative operators: is_not, not_in, does_not_contain [sb]
112
+
113
+ * changed user.roles to user.role_symbols to reduce interferance with associations [sb]
114
+
115
+ * Ruby 1.9 and Rails 2.3 compatibility [sb]
116
+
117
+ * if_permitted_to for has_permission_on blocks for DRYer auth rules [sb]
118
+
119
+ * ObligationScope rewrite of query rewriting [Brian Langenfeld]
120
+
121
+ * changed exception hierarchy to begin at StandardError [sb]
122
+
123
+ * :is_in operator [sb]
124
+
125
+ * added has_role? helper [sb]
126
+
127
+ * made plugin thread-safe [sb]
128
+
129
+ * added maintenance and test helpers [sb]
130
+
131
+ * changed default permission denied response to 403 Forbidden [sb]
132
+
133
+ * descriptions for titles and roles [sb]
134
+
135
+ * fixed for PostgreSQL [Mark Mansour]
136
+
137
+ * improved DSL syntax: allow for array of contexts in has_permission_on [sb]
138
+
139
+ ** RELEASE 0.1 (August 22, 2008) **
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,503 @@
1
+ = Declarative Authorization
2
+
3
+ The declarative authorization plugin offers an authorization mechanism inspired
4
+ by _RBAC_. The most notable distinction to other authorization plugins is the
5
+ declarative approach. That is, authorization rules are not defined
6
+ programmatically in between business logic but in an authorization configuration.
7
+
8
+ With programmatic authorization rules, the developer needs to specify which roles are
9
+ allowed to access a specific controller action or a part of a view, which is
10
+ not DRY. With a growing application code base roles' permissions often
11
+ change and new roles are introduced. Then, at several places of the source code
12
+ the changes have to be implemented, possibly leading to omissions and thus hard
13
+ to find errors. In these cases, a declarative approach as offered by decl_auth
14
+ increases the development and maintenance efficiency.
15
+
16
+
17
+ Plugin features
18
+ * Authorization at controller action level
19
+ * Authorization helpers for Views
20
+ * Authorization at model level
21
+ * Authorize CRUD (Create, Read, Update, Delete) activities
22
+ * Query rewriting to automatically only fetch authorized records
23
+ * DSL for specifying Authorization rules in an authorization configuration
24
+
25
+
26
+ Requirements
27
+ * An authentication mechanism
28
+ * User object in Controller#current_user
29
+ * (For model security) Setting Authorization.current_user
30
+ * User objects need to respond to a method :role_symbols that returns an
31
+ array of role symbols
32
+ See below for installation instructions.
33
+
34
+
35
+ There is a decl_auth screencast by Ryan Bates, nicely introducing the main concepts:
36
+ http://railscasts.com/episodes/188-declarative-authorization
37
+
38
+
39
+ = Authorization Data Model
40
+
41
+ ----- App domain ----|-------- Authorization conf ---------|------- App domain ------
42
+
43
+ includes includes
44
+ .--. .---.
45
+ | v | v
46
+ .------. can_play .------. has_permission .------------. requires .----------.
47
+ | User |----------->| Role |----------------->| Permission |<-----------| Activity |
48
+ '------' * * '------' * * '------------' 1 * '----------'
49
+ |
50
+ .-------+------.
51
+ 1 / | 1 \ *
52
+ .-----------. .---------. .-----------.
53
+ | Privilege | | Context | | Attribute |
54
+ '-----------' '---------' '-----------'
55
+
56
+ In the application domain, each *User* may be assigned to *Roles* that should
57
+ define the users' job in the application, such as _Administrator_. On the
58
+ right-hand side of this diagram, application developers specify which *Permissions*
59
+ are necessary for users to perform activities, such as calling a controller action,
60
+ viewing parts of a View or acting on records in the database. Note that
61
+ Permissions consist of an *Privilege* that is to be performed, such as _read_,
62
+ and a *Context* in that the Operation takes place, such as _companies_.
63
+
64
+ In the authorization configuration, Permissions are assigned to Roles and Role
65
+ and Permission hierarchies are defined. *Attributes* may be employed to allow
66
+ authorization according to dynamic information about the context and the
67
+ current user, e.g. "only allow access on employees that belong to the
68
+ current user's branch."
69
+
70
+
71
+ = Examples
72
+
73
+ A fully functional example application can be found at
74
+ http://github.com/stffn/decl_auth_demo_app
75
+
76
+ Details on the demonstrated methods can be found in the API docs, either
77
+ generated by yourself or at http://www.tzi.org/~sbartsch/declarative_authorization
78
+
79
+ == Controller
80
+
81
+ If authentication is in place, there are two ways to enable user-specific
82
+ access control on controller actions. For resource controllers, which more
83
+ or less follow the CRUD pattern, +filter_resource_access+ is the simplest
84
+ approach. It sets up instance variables in before filters and calls
85
+ filter_access_to with the appropriate parameters to protect the CRUD methods.
86
+
87
+ class EmployeesController < ApplicationController
88
+ filter_resource_access
89
+ ...
90
+ end
91
+
92
+ See Authorization::AuthorizationInController::ClassMethods for options on
93
+ nested resources and custom member and collection actions.
94
+
95
+ If you prefer less magic or your controller has no resemblance with the resource
96
+ controllers, directly calling filter_access_to may be the better option. Examples
97
+ are given in the following. E.g. the privilege index users is required for
98
+ action index. This works as a first default configuration for RESTful
99
+ controllers, with these privileges easily handled in the authorization
100
+ configuration, which will be described below.
101
+
102
+ class EmployeesController < ApplicationController
103
+ filter_access_to :all
104
+ def index
105
+ ...
106
+ end
107
+ ...
108
+ end
109
+
110
+ When custom actions are added to such a controller, it helps to define more
111
+ clearly which privileges are the respective requirements. That is when the
112
+ filter_access_to call may become more verbose:
113
+
114
+ class EmployeesController < ApplicationController
115
+ filter_access_to :all
116
+ # this one would be included in :all, but :read seems to be
117
+ # a more suitable privilege than :auto_complete_for_user_name
118
+ filter_access_to :auto_complete_for_employee_name, :require => :read
119
+ def auto_complete_for_employee_name
120
+ ...
121
+ end
122
+ ...
123
+ end
124
+
125
+ For some actions it might be necessary to check certain attributes of the
126
+ object the action is to be acting on. Then, the object needs to be loaded
127
+ before the action's access control is evaluated. On the other hand, some actions
128
+ might prefer the authorization to ignore specific attribute checks as the object is
129
+ unknown at checking time, so attribute checks and thus automatic loading of
130
+ objects needs to be enabled explicitly.
131
+
132
+ class EmployeesController < ApplicationController
133
+ filter_access_to :update, :attribute_check => true
134
+ def update
135
+ # @employee is already loaded from param[:id] because of :attribute_check
136
+ end
137
+ end
138
+
139
+ You can provide the needed object through before_filters. This way, you have
140
+ full control over the object that the conditions are checked against. Just make
141
+ sure, your before_filters occur before any of the filter_access_to calls.
142
+
143
+ class EmployeesController < ApplicationController
144
+ before_filter :new_employee_from_params, :only => :create
145
+ before_filter :new_employee, :only => [:index, :new]
146
+ filter_access_to :all, :attribute_check => true
147
+
148
+ def create
149
+ @employee.save!
150
+ end
151
+
152
+ protected
153
+ def new_employee_from_params
154
+ @employee = Employee.new(params[:employee])
155
+ end
156
+ end
157
+
158
+ If the access is denied, a +permission_denied+ method is called on the
159
+ current_controller, if defined, and the issue is logged.
160
+ For further customization of the filters and object loading, have a look at
161
+ the complete API documentation of filter_access_to in
162
+ Authorization::AuthorizationInController::ClassMethods.
163
+
164
+
165
+ == Views
166
+
167
+ In views, a simple permitted_to? helper makes showing blocks according to the
168
+ current user's privileges easy:
169
+
170
+ <% permitted_to? :create, :employees do %>
171
+ <%= link_to 'New', new_employee_path %>
172
+ <% end %>
173
+
174
+ Only giving a symbol :employees as context prevents any checks of attributes
175
+ as there is no object to check against. For example, in case of nested resources
176
+ a new object may come in handy:
177
+
178
+ <% permitted_to? :create, Branch.new(:company => @company) do
179
+ # or @company.branches.new
180
+ # or even @company.branches %>
181
+ <%= link_to 'New', new_company_branch_path(@company) %>
182
+ <% end %>
183
+
184
+ Lists are straight-forward:
185
+
186
+ <% for employee in @employees %>
187
+ <%= link_to 'Edit', edit_employee_path(employee) if permitted_to? :update, employee %>
188
+ <% end %>
189
+
190
+ See also Authorization::AuthorizationHelper.
191
+
192
+
193
+ == Models
194
+
195
+ There are two destinct features for model security built into this plugin:
196
+ authorizing CRUD operations on objects as well as query rewriting to limit
197
+ results according to certain privileges.
198
+
199
+ See also Authorization::AuthorizationInModel.
200
+
201
+ === Model security for CRUD opterations
202
+ To activate model security, all it takes is an explicit enabling for each
203
+ model that model security should be enforced on, i.e.
204
+
205
+ class Employee < ActiveRecord::Base
206
+ using_access_control
207
+ ...
208
+ end
209
+
210
+ Thus,
211
+ Employee.create(...)
212
+ fails, if the current user is not allowed to :create :employees according
213
+ to the authorization rules. For the application to find out about what
214
+ happened if an operation is denied, the filters throw
215
+ Authorization::NotAuthorized exceptions.
216
+
217
+ As access control on read are costly, with possibly lots of objects being
218
+ loaded at a time in one query, checks on read need to be actived explicitly by
219
+ adding the :include_read option.
220
+
221
+ === Query rewriting through named scopes
222
+ When retrieving large sets of records from databases, any authorization needs
223
+ to be integrated into the query in order to prevent inefficient filtering
224
+ afterwards and to use LIMIT and OFFSET in SQL statements. To keep authorization
225
+ rules out of the source code, this plugin offers query rewriting mechanisms
226
+ through named scopes. Thus,
227
+
228
+ Employee.with_permissions_to(:read)
229
+
230
+ returns all employee records that the current user is authorized to read. In
231
+ addition, just like normal named scopes, query rewriting may be chained with
232
+ the usual find method:
233
+
234
+ Employee.with_permissions_to(:read).find(:all, :conditions => ...)
235
+
236
+ If the current user is completely missing the permissions, an
237
+ Authorization::NotAuthorized exception is raised. Through
238
+ Model.obligation_conditions, application developers may retrieve
239
+ the conditions for manual rewrites.
240
+
241
+
242
+ == Authorization Rules
243
+
244
+ Authorization rules are defined in config/authorization_rules.rb
245
+ (Or redefine rules files path via +Authorization::AUTH_RULE_FILES+). E.g.
246
+
247
+ authorization do
248
+ role :admin do
249
+ has_permission_on :employees, :to => [:create, :read, :update, :delete]
250
+ end
251
+ end
252
+
253
+ There is a default role :+guest+ that is used if a request is not associated
254
+ with any user or with a user without any roles. So, if your application has
255
+ public pages, :+guest+ can be used to allow access for users that are not
256
+ logged in. All other roles are application defined and need to be associated
257
+ with users by the application.
258
+
259
+ Privileges, such as :create, may be put into hierarchies to simplify
260
+ maintenance. So the example above has the same meaning as
261
+
262
+ authorization do
263
+ role :admin do
264
+ has_permission_on :employees, :to => :manage
265
+ end
266
+ end
267
+
268
+ privileges do
269
+ privilege :manage do
270
+ includes :create, :read, :update, :delete
271
+ end
272
+ end
273
+
274
+ Privilege hierarchies may be context-specific, e.g. applicable to :employees.
275
+
276
+ privileges do
277
+ privilege :manage, :employees, :includes => :increase_salary
278
+ end
279
+
280
+ For more complex use cases, authorizations need to be based on attributes. E.g.
281
+ if a branch admin should manage only employees of his branch (see
282
+ Authorization::Reader in the API docs for a full list of available operators):
283
+
284
+ authorization do
285
+ role :branch_admin do
286
+ has_permission_on :employees do
287
+ to :manage
288
+ # user refers to the current_user when evaluating
289
+ if_attribute :branch => is {user.branch}
290
+ end
291
+ end
292
+ end
293
+
294
+ To reduce redundancy in has_permission_on blocks, a rule may depend on
295
+ permissions on associated objects:
296
+
297
+ authorization do
298
+ role :branch_admin do
299
+ has_permission_on :branches, :to => :manage do
300
+ if_attribute :managers => contains {user}
301
+ end
302
+
303
+ has_permission_on :employees, :to => :manage do
304
+ if_permitted_to :manage, :branch
305
+ # instead of
306
+ #if_attribute :branch => {:managers => contains {user}}
307
+ end
308
+ end
309
+ end
310
+
311
+ Lastly, not only privileges may be organized in a hierarchy but roles as well.
312
+ Here, project manager inherit the permissions of employees.
313
+
314
+ role :project_manager do
315
+ includes :employee
316
+ end
317
+
318
+ See also Authorization::Reader.
319
+
320
+ == Testing
321
+
322
+ declarative_authorization provides a few helpers to ease the testing with
323
+ authorization in mind.
324
+
325
+ In your test_helper.rb, to enable the helpers add
326
+
327
+ require 'declarative_authorization/maintenance'
328
+
329
+ class Test::Unit::TestCase
330
+ include Authorization::TestHelper
331
+ ...
332
+ end
333
+
334
+ Now, in unit tests, you may deactivate authorization if needed e.g. for test
335
+ setup and assume certain identities for tests:
336
+
337
+ class EmployeeTest < ActiveSupport::TestCase
338
+ def test_should_read
339
+ without_access_control do
340
+ Employee.create(...)
341
+ end
342
+ assert_nothing_raised do
343
+ with_user(admin) do
344
+ Employee.find(:first)
345
+ end
346
+ end
347
+ end
348
+ end
349
+
350
+ In functional tests, get, posts, etc. may be tested in the name of certain users:
351
+
352
+ get_with admin, :index
353
+ post_with admin, :update, :employee => {...}
354
+
355
+ See Authorization::TestHelper for more information.
356
+
357
+
358
+ = Installation of declarative_authorization
359
+
360
+ One of three options to install the plugin:
361
+ * Install by Gem: Add to your environment.rb in the initializer block:
362
+ config.gem "declarative_authorization"
363
+ Note: you need gemcutter support in place, i.e. call
364
+ gem install gemcutter
365
+ gem tumble
366
+ And call from your application's root directory
367
+ rake gems:install
368
+ * Alternatively, to install from github, execute in your application's root directory
369
+ cd vendor/plugins && git clone git://github.com/stffn/declarative_authorization.git
370
+ * Or, download one of the released versions from Github at
371
+ http://github.com/stffn/declarative_authorization/downloads
372
+
373
+ Then,
374
+ * provide the requirements as noted below,
375
+ * create a basic config/authorization_rules.rb--you might want to take the
376
+ provided example authorization_rules.dist.rb in the plugin root as a starting
377
+ point,
378
+ * add +filter_access_to+, +permitted_to+? and model security as needed.
379
+
380
+ == Providing the Plugin's Requirements
381
+ The requirements are
382
+ * Rails >= 2.2, including 3 and Ruby >= 1.8.6, including 1.9
383
+ * An authentication mechanism
384
+ * A user object returned by Controller#current_user
385
+ * An array of role symbols returned by User#role_symbols
386
+ * (For model security) Setting Authorization.current_user to the request's user
387
+
388
+ Of the various ways to provide these requirements, here is one way employing
389
+ restful_authentication.
390
+
391
+ * Install restful_authentication
392
+ cd vendor/plugins && git clone git://github.com/technoweenie/restful-authentication.git restful_authentication
393
+ cd ../.. && ruby script/generate authenticated user sessions
394
+ * Move "include AuthenticatedSystem" to ApplicationController
395
+ * Add +filter_access_to+ calls as described above.
396
+ * If you'd like to use model security, add a before_filter that sets the user
397
+ globally to your ApplicationController. This is thread-safe.
398
+ before_filter :set_current_user
399
+ protected
400
+ def set_current_user
401
+ Authorization.current_user = current_user
402
+ end
403
+
404
+ * Add roles field to the User model through a :+has_many+ association
405
+ (this is just one possible approach; you could just as easily use
406
+ :+has_many+ :+through+ or a serialized roles array):
407
+ * create a migration for table roles
408
+ class CreateRoles < ActiveRecord::Migration
409
+ def self.up
410
+ create_table "roles" do |t|
411
+ t.column :title, :string
412
+ t.references :user
413
+ end
414
+ end
415
+
416
+ def self.down
417
+ drop_table "roles"
418
+ end
419
+ end
420
+
421
+ * create a model Role,
422
+ class Role < ActiveRecord::Base
423
+ belongs_to :user
424
+ end
425
+
426
+ * add +has_many+ :+roles+ to the User model and a roles method that returns the roles
427
+ as an Array of Symbols, e.g.
428
+ class User < ActiveRecord::Base
429
+ has_many :roles
430
+ def role_symbols
431
+ (roles || []).map {|r| r.title.to_sym}
432
+ end
433
+ end
434
+
435
+ * add roles to your User objects using e.g.
436
+ user.roles.create(:title => "admin")
437
+
438
+ Note: If you choose to generate an Account model for restful_authentication
439
+ instead of a User model as described above, you have to customize the
440
+ examples and create a ApplicationController#current_user method.
441
+
442
+
443
+ == Debugging Authorization
444
+
445
+ Currently, the main means of debugging authorization decisions is logging and
446
+ exceptions. Denied access to actions is logged to +warn+ or +info+, including
447
+ some hints about what went wrong.
448
+
449
+ All bang methods throw exceptions which may be used to retrieve more
450
+ information about a denied access than a Boolean value.
451
+
452
+
453
+ == Authorization Development Support
454
+
455
+ If your authorization rules become more complex, you might be glad to use
456
+ the authorization rules browser that comes with declarative_authorization.
457
+ It has a syntax-highlighted and a graphical view with filtering of the current
458
+ authorization rules.
459
+
460
+ By default, it will only be available in development mode. To use it, add
461
+ the following lines to your authorization_rules.rb for the appropriate role:
462
+
463
+ has_permission_on :authorization_rules, :to => :read
464
+
465
+ Then, point your browser to
466
+ http://localhost/authorization_rules
467
+
468
+ The browser needs Rails 2.3 (for Engine support). The graphical view requires
469
+ Graphviz (which e.g. can be installed through the graphviz package under Debian
470
+ and Ubuntu) and has only been tested under Linux. Note: for Change Support
471
+ you'll need to have a User#login method that returns a non-ambiguous user
472
+ name for identification.
473
+
474
+
475
+ = Help and Contact
476
+
477
+ We have an issue tracker[http://github.com/stffn/declarative_authorization/issues]
478
+ for bugs and feature requests as well as a
479
+ Google Group[http://groups.google.com/group/declarative_authorization] for
480
+ discussions on the usage of the plugin. You are very welcome to contribute.
481
+ Just fork the git repository and create a new issue, send a pull request or
482
+ contact me personally.
483
+
484
+ Maintained by
485
+
486
+ Steffen Bartsch
487
+ TZI, Universität Bremen, Germany
488
+ sbartsch at tzi.org
489
+
490
+
491
+ = Contributors
492
+
493
+ Thanks to John Joseph Bachir, Eike Carls, Kai Chen, Erik Dahlstrand,
494
+ Jeroen van Dijk, Sebastian Dyck, Jeremy Friesen, Tim Harper, Daniel Kristensen,
495
+ Brian Langenfeld, Georg Ledermann, Geoff Longman, Olly Lylo, Mark Mansour,
496
+ Thomas Maurer, Mike Vincent
497
+
498
+
499
+ = Licence
500
+
501
+ Copyright (c) 2008 Steffen Bartsch, TZI, Universität Bremen, Germany
502
+ released under the MIT license
503
+