graylog2-declarative_authorization 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/CHANGELOG +153 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +529 -0
  4. data/Rakefile +35 -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 +44 -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 +47 -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 +20 -0
  18. data/garlic_example.rb +20 -0
  19. data/init.rb +5 -0
  20. data/lib/declarative_authorization.rb +17 -0
  21. data/lib/declarative_authorization/authorization.rb +705 -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 +68 -0
  27. data/lib/declarative_authorization/in_controller.rb +645 -0
  28. data/lib/declarative_authorization/in_model.rb +162 -0
  29. data/lib/declarative_authorization/maintenance.rb +212 -0
  30. data/lib/declarative_authorization/obligation_scope.rb +354 -0
  31. data/lib/declarative_authorization/rails_legacy.rb +22 -0
  32. data/lib/declarative_authorization/railsengine.rb +6 -0
  33. data/lib/declarative_authorization/reader.rb +521 -0
  34. data/lib/tasks/authorization_tasks.rake +82 -0
  35. data/test/authorization_test.rb +1104 -0
  36. data/test/controller_filter_resource_access_test.rb +511 -0
  37. data/test/controller_test.rb +480 -0
  38. data/test/dsl_reader_test.rb +178 -0
  39. data/test/helper_test.rb +247 -0
  40. data/test/maintenance_test.rb +46 -0
  41. data/test/model_test.rb +1883 -0
  42. data/test/schema.sql +55 -0
  43. data/test/test_helper.rb +152 -0
  44. metadata +112 -0
@@ -0,0 +1,153 @@
1
+ ** RELEASE 0.5.2 (Dec 31, 2010) **
2
+
3
+ * Bugfixes and documentation updates
4
+
5
+ ** RELEASE 0.5.1 (Sep 12, 2010) **
6
+
7
+ ** RELEASE 0.5 (July 21, 2010) **
8
+
9
+ * Ruby 1.9.2 compatibility [sb]
10
+
11
+ * Comparisons in authorization roles: lt, lte, gt, gte [aepstein,hollownest]
12
+
13
+ * DSL optimization: allow array being passed to to
14
+
15
+ * Omnipotent roles [timcharper]
16
+
17
+ * Meaningful error in case of missing authorization rules file [timcharper]
18
+
19
+ * Rails 3 support [sb]
20
+
21
+ * Support shallow nested resources [jjb]
22
+
23
+ * Allow multiple authorization rules files [kaichen]
24
+
25
+ ** RELEASE 0.4 (November 15, 2009) **
26
+
27
+ * Implemented controller namespace handling [sb]
28
+
29
+ * Improved if_attribute to allow nesting of has_many associations [sb]
30
+
31
+ * Improved if_permitted_to: allow has_many associations and improved context inference [sb]
32
+
33
+ * Added option on handling non-existant auto-loaded object [sb]
34
+
35
+ * Added with_user as module method [sb]
36
+
37
+ * Change support i18n [sb]
38
+
39
+ ** RELEASE 0.3.2.3 (October 12, 2009) **
40
+
41
+ * Switched to gemcutter [sb]
42
+
43
+ * Fixed has_role? for guest user. Closes #8 [sb]
44
+
45
+ * Fixed unnecessary DB query with named scopes [sb, ledermann]
46
+
47
+ * Change support: suggestions: grouping, sorting by affected users [sb]
48
+
49
+ * Fixed context inference from AR objects for STI by switching to #class.name.tableize [sb]
50
+
51
+ * Allow multiple contexts as arguments to has_permission_on [Jeroen van Dijk]
52
+
53
+ ** RELEASE 0.3.2.2 (August 27, 2009) **
54
+
55
+ * Fix without_access_control test cases [sb]
56
+
57
+ * Fixed error on debug logging (Closes #6) [sb]
58
+
59
+ * Fixed without_access_control instance method in TestHelper [sb]
60
+
61
+ ** RELEASE 0.3.2.1 (August 14, 2009) **
62
+
63
+ * Fix gemspec for Rdoc generation [sb]
64
+
65
+ ** RELEASE 0.3.2 (August 13, 2009) **
66
+
67
+ * Fix for model-level permitted_to?/! [sb]
68
+
69
+ ** RELEASE 0.3.1 (August 12, 2009) **
70
+
71
+ * Change Support: Suggestion grouping, sort by affected users [sb]
72
+
73
+ * Changed context derived from objects to #class.name.tableize to fix STI [sb]
74
+
75
+ * Simplified controller authorization with filter_resource_access [sb]
76
+
77
+ * Allow passing explicit context in addition to object in permitted_to? [Olly Lylo, sb]
78
+
79
+ * Change Supporter: suggest changes to authorization rules [sb]
80
+
81
+ * Added permitted_to!/? in model [Eike Carls]
82
+
83
+ * New test helper: should_(not_)_be_allowed_to(privilege, object_or_context) [sb]
84
+
85
+ ** RELEASE 0.3 (April 20, 2009) **
86
+
87
+ * New option :join_by for has_permission_on to allow AND'ing of statements in one has_permission_on block [sb]
88
+
89
+ * Allow using_access_control to be called directly on ActiveRecord::Base, globally enabling model security [sb]
90
+
91
+ * New operator: intersects_with, comparing two Enumerables in if_attribute [sb]
92
+
93
+ * Improved if_permitted_to syntax: if the attribute is left out, permissions are checked on for the current object [sb]
94
+
95
+ * Added #has_role_with_hierarchy? method to retrieve explicit and calculated roles [jeremyf]
96
+
97
+ * Added a simple rules analyzer to help improve authorization rules [sb]
98
+
99
+ * Gemified plugin. Needed to restructure the lib path contents [sb]
100
+
101
+ * Added handling of Authorization::AuthorizationInController::ClassMethods.filter_access_to parameters that are of the form [:show, :update] instead of just :show, :update. [jeremyf]
102
+
103
+ * Added authorization usage helper for checking filter_access_to usage in controllers [sb]
104
+
105
+ * Added a authorization rules browser. See README for more information [sb]
106
+
107
+ * Added Model.using_access_control? to check if a model has model security activated [sb]
108
+
109
+ * Changed Authorization::ObligationScope#map_table_alias_for [Brian Langenfeld]
110
+ * Fixed to prevent bad aliases from being produced.
111
+
112
+ * Changed Authorization::Attribute#validate? [Brian Langenfeld]
113
+ * 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.
114
+
115
+ * Changed Authorization::Engine#permit! [Brian Langenfeld]
116
+ * 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.
117
+ * 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.
118
+ * 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).
119
+
120
+ * Changed Authorization::ObligationScope#rebuild_join_options! [Brian Langenfeld]
121
+ * 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.
122
+
123
+ ** RELEASE 0.2 (February 2, 2009) **
124
+
125
+ * added negative operators: is_not, not_in, does_not_contain [sb]
126
+
127
+ * changed user.roles to user.role_symbols to reduce interferance with associations [sb]
128
+
129
+ * Ruby 1.9 and Rails 2.3 compatibility [sb]
130
+
131
+ * if_permitted_to for has_permission_on blocks for DRYer auth rules [sb]
132
+
133
+ * ObligationScope rewrite of query rewriting [Brian Langenfeld]
134
+
135
+ * changed exception hierarchy to begin at StandardError [sb]
136
+
137
+ * :is_in operator [sb]
138
+
139
+ * added has_role? helper [sb]
140
+
141
+ * made plugin thread-safe [sb]
142
+
143
+ * added maintenance and test helpers [sb]
144
+
145
+ * changed default permission denied response to 403 Forbidden [sb]
146
+
147
+ * descriptions for titles and roles [sb]
148
+
149
+ * fixed for PostgreSQL [Mark Mansour]
150
+
151
+ * improved DSL syntax: allow for array of contexts in has_permission_on [sb]
152
+
153
+ ** RELEASE 0.1 (August 22, 2008) **
@@ -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.
@@ -0,0 +1,529 @@
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
+ If you need to change the default role, you can do so by adding an initializer
260
+ that contains the following statement:
261
+
262
+ Authorization.default_role = :anonymous
263
+
264
+ Privileges, such as :create, may be put into hierarchies to simplify
265
+ maintenance. So the example above has the same meaning as
266
+
267
+ authorization do
268
+ role :admin do
269
+ has_permission_on :employees, :to => :manage
270
+ end
271
+ end
272
+
273
+ privileges do
274
+ privilege :manage do
275
+ includes :create, :read, :update, :delete
276
+ end
277
+ end
278
+
279
+ Privilege hierarchies may be context-specific, e.g. applicable to :employees.
280
+
281
+ privileges do
282
+ privilege :manage, :employees, :includes => :increase_salary
283
+ end
284
+
285
+ For more complex use cases, authorizations need to be based on attributes. Note
286
+ that you then also need to set :attribute_check => true in controllers for filter_access_to.
287
+ E.g. if a branch admin should manage only employees of his branch (see
288
+ Authorization::Reader in the API docs for a full list of available operators):
289
+
290
+ authorization do
291
+ role :branch_admin do
292
+ has_permission_on :employees do
293
+ to :manage
294
+ # user refers to the current_user when evaluating
295
+ if_attribute :branch => is {user.branch}
296
+ end
297
+ end
298
+ end
299
+
300
+ To reduce redundancy in has_permission_on blocks, a rule may depend on
301
+ permissions on associated objects:
302
+
303
+ authorization do
304
+ role :branch_admin do
305
+ has_permission_on :branches, :to => :manage do
306
+ if_attribute :managers => contains {user}
307
+ end
308
+
309
+ has_permission_on :employees, :to => :manage do
310
+ if_permitted_to :manage, :branch
311
+ # instead of
312
+ #if_attribute :branch => {:managers => contains {user}}
313
+ end
314
+ end
315
+ end
316
+
317
+ Lastly, not only privileges may be organized in a hierarchy but roles as well.
318
+ Here, project manager inherit the permissions of employees.
319
+
320
+ role :project_manager do
321
+ includes :employee
322
+ end
323
+
324
+ See also Authorization::Reader.
325
+
326
+ == Testing
327
+
328
+ declarative_authorization provides a few helpers to ease the testing with
329
+ authorization in mind.
330
+
331
+ In your test_helper.rb, to enable the helpers add
332
+
333
+ require 'declarative_authorization/maintenance'
334
+
335
+ class Test::Unit::TestCase
336
+ include Authorization::TestHelper
337
+ ...
338
+ end
339
+
340
+ For using the test helpers with RSpec, just add the following lines to your
341
+ spec_helper.rb (somewhere after require 'spec/rails'):
342
+
343
+ require 'declarative_authorization/maintenance'
344
+ include Authorization::TestHelper
345
+
346
+ Now, in unit tests, you may deactivate authorization if needed e.g. for test
347
+ setup and assume certain identities for tests:
348
+
349
+ class EmployeeTest < ActiveSupport::TestCase
350
+ def test_should_read
351
+ without_access_control do
352
+ Employee.create(...)
353
+ end
354
+ assert_nothing_raised do
355
+ with_user(admin) do
356
+ Employee.find(:first)
357
+ end
358
+ end
359
+ end
360
+ end
361
+
362
+ Or, with RSpec, it would work like this:
363
+
364
+ describe Employee do
365
+ it "should read" do
366
+ without_access_control do
367
+ Employee.create(...)
368
+ end
369
+ with_user(admin) do
370
+ Employee.find(:first)
371
+ end
372
+ end
373
+ end
374
+
375
+ In functional tests, get, posts, etc. may be tested in the name of certain users:
376
+
377
+ get_with admin, :index
378
+ post_with admin, :update, :employee => {...}
379
+
380
+ See Authorization::TestHelper for more information.
381
+
382
+
383
+ = Installation of declarative_authorization
384
+
385
+ One of three options to install the plugin:
386
+ * Install by Gem: Add to your environment.rb in the initializer block:
387
+ config.gem "declarative_authorization"
388
+ Note: you need gemcutter support in place, i.e. call
389
+ gem install gemcutter
390
+ gem tumble
391
+ And call from your application's root directory
392
+ rake gems:install
393
+ * Alternatively, to install from github, execute in your application's root directory
394
+ cd vendor/plugins && git clone git://github.com/stffn/declarative_authorization.git
395
+ * Or, download one of the released versions from Github at
396
+ http://github.com/stffn/declarative_authorization/downloads
397
+
398
+ Then,
399
+ * provide the requirements as noted below,
400
+ * create a basic config/authorization_rules.rb--you might want to take the
401
+ provided example authorization_rules.dist.rb in the plugin root as a starting
402
+ point,
403
+ * add +filter_access_to+, +permitted_to+? and model security as needed.
404
+
405
+ == Providing the Plugin's Requirements
406
+ The requirements are
407
+ * Rails >= 2.2, including 3 and Ruby >= 1.8.6, including 1.9
408
+ * An authentication mechanism
409
+ * A user object returned by Controller#current_user
410
+ * An array of role symbols returned by User#role_symbols
411
+ * (For model security) Setting Authorization.current_user to the request's user
412
+
413
+ Of the various ways to provide these requirements, here is one way employing
414
+ restful_authentication.
415
+
416
+ * Install restful_authentication
417
+ cd vendor/plugins && git clone git://github.com/technoweenie/restful-authentication.git restful_authentication
418
+ cd ../.. && ruby script/generate authenticated user sessions
419
+ * Move "include AuthenticatedSystem" to ApplicationController
420
+ * Add +filter_access_to+ calls as described above.
421
+ * If you'd like to use model security, add a before_filter that sets the user
422
+ globally to your ApplicationController. This is thread-safe.
423
+ before_filter :set_current_user
424
+ protected
425
+ def set_current_user
426
+ Authorization.current_user = current_user
427
+ end
428
+
429
+ * Add roles field to the User model through a :+has_many+ association
430
+ (this is just one possible approach; you could just as easily use
431
+ :+has_many+ :+through+ or a serialized roles array):
432
+ * create a migration for table roles
433
+ class CreateRoles < ActiveRecord::Migration
434
+ def self.up
435
+ create_table "roles" do |t|
436
+ t.column :title, :string
437
+ t.references :user
438
+ end
439
+ end
440
+
441
+ def self.down
442
+ drop_table "roles"
443
+ end
444
+ end
445
+
446
+ * create a model Role,
447
+ class Role < ActiveRecord::Base
448
+ belongs_to :user
449
+ end
450
+
451
+ * add +has_many+ :+roles+ to the User model and a roles method that returns the roles
452
+ as an Array of Symbols, e.g.
453
+ class User < ActiveRecord::Base
454
+ has_many :roles
455
+ def role_symbols
456
+ (roles || []).map {|r| r.title.to_sym}
457
+ end
458
+ end
459
+
460
+ * add roles to your User objects using e.g.
461
+ user.roles.create(:title => "admin")
462
+
463
+ Note: If you choose to generate an Account model for restful_authentication
464
+ instead of a User model as described above, you have to customize the
465
+ examples and create a ApplicationController#current_user method.
466
+
467
+
468
+ == Debugging Authorization
469
+
470
+ Currently, the main means of debugging authorization decisions is logging and
471
+ exceptions. Denied access to actions is logged to +warn+ or +info+, including
472
+ some hints about what went wrong.
473
+
474
+ All bang methods throw exceptions which may be used to retrieve more
475
+ information about a denied access than a Boolean value.
476
+
477
+
478
+ == Authorization Development Support
479
+
480
+ If your authorization rules become more complex, you might be glad to use
481
+ the authorization rules browser that comes with declarative_authorization.
482
+ It has a syntax-highlighted and a graphical view with filtering of the current
483
+ authorization rules.
484
+
485
+ By default, it will only be available in development mode. To use it, add
486
+ the following lines to your authorization_rules.rb for the appropriate role:
487
+
488
+ has_permission_on :authorization_rules, :to => :read
489
+
490
+ Then, point your browser to
491
+ http://localhost/authorization_rules
492
+
493
+ The browser needs Rails 2.3 (for Engine support). The graphical view requires
494
+ Graphviz (which e.g. can be installed through the graphviz package under Debian
495
+ and Ubuntu) and has only been tested under Linux. Note: for Change Support
496
+ you'll need to have a User#login method that returns a non-ambiguous user
497
+ name for identification.
498
+
499
+
500
+ = Help and Contact
501
+
502
+ We have an issue tracker[http://github.com/stffn/declarative_authorization/issues]
503
+ for bugs and feature requests as well as a
504
+ Google Group[http://groups.google.com/group/declarative_authorization] for
505
+ discussions on the usage of the plugin. You are very welcome to contribute.
506
+ Just fork the git repository and create a new issue, send a pull request or
507
+ contact me personally.
508
+
509
+ Maintained by
510
+
511
+ Steffen Bartsch
512
+ TZI, Universität Bremen, Germany
513
+ sbartsch at tzi.org
514
+
515
+
516
+ = Contributors
517
+
518
+ Thanks to John Joseph Bachir, Eike Carls, Dennis Blöte, Kai Chen, Erik Dahlstrand,
519
+ Jeroen van Dijk, Alexander Dobriakov, Sebastian Dyck, Ari Epstein, Jeremy Friesen,
520
+ Tim Harper, hollownest, Daniel Kristensen, Brad Langhorst, Brian Langenfeld,
521
+ Georg Ledermann, Geoff Longman, Olly Lylo, Mark Mansour, Thomas Maurer, Sharagoz,
522
+ TJ Singleton, Mike Vincent
523
+
524
+
525
+ = Licence
526
+
527
+ Copyright (c) 2008 Steffen Bartsch, TZI, Universität Bremen, Germany
528
+ released under the MIT license
529
+