lockdown_vail 1.6.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/.gitignore +6 -0
  2. data/README.txt +36 -0
  3. data/Rakefile +38 -0
  4. data/VERSION +1 -0
  5. data/lib/lockdown/context.rb +41 -0
  6. data/lib/lockdown/database.rb +41 -0
  7. data/lib/lockdown/errors.rb +11 -0
  8. data/lib/lockdown/frameworks/rails/controller.rb +187 -0
  9. data/lib/lockdown/frameworks/rails/view.rb +50 -0
  10. data/lib/lockdown/frameworks/rails.rb +114 -0
  11. data/lib/lockdown/helper.rb +111 -0
  12. data/lib/lockdown/orms/active_record.rb +68 -0
  13. data/lib/lockdown/permission.rb +222 -0
  14. data/lib/lockdown/references.rb +19 -0
  15. data/lib/lockdown/rspec_helper.rb +114 -0
  16. data/lib/lockdown/rules.rb +372 -0
  17. data/lib/lockdown/session.rb +66 -0
  18. data/lib/lockdown/system.rb +58 -0
  19. data/lib/lockdown.rb +87 -0
  20. data/lockdown.gemspec +118 -0
  21. data/lockdown_vail.gemspec +120 -0
  22. data/rails_generators/lockdown/lockdown_generator.rb +274 -0
  23. data/rails_generators/lockdown/templates/app/controllers/permissions_controller.rb +22 -0
  24. data/rails_generators/lockdown/templates/app/controllers/sessions_controller.rb +39 -0
  25. data/rails_generators/lockdown/templates/app/controllers/user_groups_controller.rb +122 -0
  26. data/rails_generators/lockdown/templates/app/controllers/users_controller.rb +117 -0
  27. data/rails_generators/lockdown/templates/app/helpers/permissions_helper.rb +2 -0
  28. data/rails_generators/lockdown/templates/app/helpers/user_groups_helper.rb +2 -0
  29. data/rails_generators/lockdown/templates/app/helpers/users_helper.rb +2 -0
  30. data/rails_generators/lockdown/templates/app/models/permission.rb +13 -0
  31. data/rails_generators/lockdown/templates/app/models/profile.rb +10 -0
  32. data/rails_generators/lockdown/templates/app/models/user.rb +95 -0
  33. data/rails_generators/lockdown/templates/app/models/user_group.rb +15 -0
  34. data/rails_generators/lockdown/templates/app/views/permissions/index.html.erb +16 -0
  35. data/rails_generators/lockdown/templates/app/views/permissions/show.html.erb +26 -0
  36. data/rails_generators/lockdown/templates/app/views/sessions/new.html.erb +12 -0
  37. data/rails_generators/lockdown/templates/app/views/user_groups/edit.html.erb +33 -0
  38. data/rails_generators/lockdown/templates/app/views/user_groups/index.html.erb +20 -0
  39. data/rails_generators/lockdown/templates/app/views/user_groups/new.html.erb +31 -0
  40. data/rails_generators/lockdown/templates/app/views/user_groups/show.html.erb +29 -0
  41. data/rails_generators/lockdown/templates/app/views/users/edit.html.erb +51 -0
  42. data/rails_generators/lockdown/templates/app/views/users/index.html.erb +22 -0
  43. data/rails_generators/lockdown/templates/app/views/users/new.html.erb +50 -0
  44. data/rails_generators/lockdown/templates/app/views/users/show.html.erb +33 -0
  45. data/rails_generators/lockdown/templates/config/initializers/lockit.rb +1 -0
  46. data/rails_generators/lockdown/templates/db/migrate/create_admin_user.rb +17 -0
  47. data/rails_generators/lockdown/templates/db/migrate/create_permissions.rb +19 -0
  48. data/rails_generators/lockdown/templates/db/migrate/create_profiles.rb +26 -0
  49. data/rails_generators/lockdown/templates/db/migrate/create_user_groups.rb +19 -0
  50. data/rails_generators/lockdown/templates/db/migrate/create_users.rb +17 -0
  51. data/rails_generators/lockdown/templates/lib/lockdown/README +42 -0
  52. data/rails_generators/lockdown/templates/lib/lockdown/init.rb +136 -0
  53. data/spec/lockdown/context_spec.rb +191 -0
  54. data/spec/lockdown/database_spec.rb +66 -0
  55. data/spec/lockdown/frameworks/rails/controller_spec.rb +240 -0
  56. data/spec/lockdown/frameworks/rails/view_spec.rb +87 -0
  57. data/spec/lockdown/frameworks/rails_spec.rb +163 -0
  58. data/spec/lockdown/permission_spec.rb +156 -0
  59. data/spec/lockdown/rspec_helper_spec.rb +41 -0
  60. data/spec/lockdown/rules_spec.rb +245 -0
  61. data/spec/lockdown/session_spec.rb +125 -0
  62. data/spec/lockdown/system_spec.rb +51 -0
  63. data/spec/lockdown_spec.rb +19 -0
  64. data/spec/rcov.opts +5 -0
  65. data/spec/spec.opts +3 -0
  66. data/spec/spec_helper.rb +8 -0
  67. metadata +140 -0
@@ -0,0 +1,372 @@
1
+ module Lockdown
2
+ module Rules
3
+ attr_accessor :options
4
+ attr_accessor :permissions
5
+ attr_accessor :user_groups
6
+
7
+ attr_reader :protected_access
8
+ attr_reader :public_access
9
+
10
+ attr_reader :permission_objects
11
+
12
+ def set_defaults
13
+ @permissions = {}
14
+ @user_groups = {}
15
+ @options = {}
16
+
17
+ @permission_objects = {}
18
+
19
+ @public_access = []
20
+ @protected_access = []
21
+
22
+ @options = {
23
+ :session_timeout => (60 * 60),
24
+ :who_did_it => :current_user_id,
25
+ :default_who_did_it => 1,
26
+ :logout_on_access_violation => false,
27
+ :access_denied_path => "/",
28
+ :successful_login_path => "/",
29
+ :subdirectory => nil,
30
+ :skip_db_sync_in => ["test"],
31
+ :link_separator => ' | ',
32
+ :user_group_model => "UserGroup",
33
+ :user_model => "User"
34
+ }
35
+ end
36
+
37
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38
+ # =Rule defining methods. e.g. Methods used in lib/lockdown/init.rb
39
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40
+
41
+ # Creates new permission object
42
+ # Refer to the Permission object for the full functionality
43
+ def set_permission(name)
44
+ @permission_objects[name] = Lockdown::Permission.new(name)
45
+ end
46
+
47
+ # Defines public access by the permission symbols
48
+ #
49
+ # ==== Example
50
+ # set_public_access(:permission_one, :permission_two)
51
+ #
52
+ def set_public_access(*perms)
53
+ perms.each do |perm_symbol|
54
+ perm = find_permission_object(perm_symbol)
55
+ if perm
56
+ perm.set_as_public_access
57
+ else
58
+ msg = "Permission not found: #{perm_symbol}"
59
+ raise Lockdown::InvalidRuleAssignment, msg
60
+ end
61
+ end
62
+ end
63
+
64
+ # Defines protected access by the permission symbols
65
+ #
66
+ # ==== Example
67
+ # set_public_access(:permission_one, :permission_two)
68
+ #
69
+ def set_protected_access(*perms)
70
+ perms.each do |perm_symbol|
71
+ perm = find_permission_object(perm_symbol)
72
+ if perm
73
+ perm.set_as_protected_access
74
+ else
75
+ msg = "Permission not found: #{perm_symbol}"
76
+ raise Lockdown::InvalidRuleAssignment, msg
77
+ end
78
+ end
79
+ end
80
+
81
+ # Define a user groups by name and permission symbol(s)
82
+ #
83
+ # ==== Example
84
+ # set_user_group(:managment_group, :permission_one, :permission_two)
85
+ #
86
+ def set_user_group(name, *perms)
87
+ user_groups[name] ||= []
88
+ perms.each do |perm|
89
+ if permission_assigned_automatically?(perm)
90
+ raise Lockdown::InvalidPermissionAssignment, "Permission is assigned automatically. Please remove it from #{name} user group"
91
+ end
92
+ user_groups[name].push(perm)
93
+ end
94
+ end
95
+
96
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
97
+ # =Convenience methods for permissions and user groups
98
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99
+
100
+ # Returns array of permission names as symbols
101
+ def get_permissions
102
+ permissions.keys
103
+ end
104
+
105
+ # Is the permission defined?
106
+ def permission_exists?(permission_symbol)
107
+ get_permissions.include?(permission_symbol)
108
+ end
109
+
110
+ alias_method :has_permission?, :permission_exists?
111
+
112
+ # returns true if the permission is public
113
+ def public_access?(perm_symbol)
114
+ obj = find_permission_object(perm_symbol)
115
+ obj.nil? ? false : obj.public_access?
116
+ end
117
+
118
+ # returns true if the permission is public
119
+ def protected_access?(perm_symbol)
120
+ obj = find_permission_object(perm_symbol)
121
+ obj.nil? ? false : obj.protected_access?
122
+ end
123
+
124
+ # These permissions are assigned by the system
125
+ def permission_assigned_automatically?(permmision_symbol)
126
+ public_access?(permmision_symbol) || protected_access?(permmision_symbol)
127
+ end
128
+
129
+ # Returns array of user group names as symbols
130
+ def get_user_groups
131
+ user_groups.keys
132
+ end
133
+
134
+ # Is the user group defined?
135
+ # The :administrators user group always exists
136
+ def user_group_exists?(user_group_symbol)
137
+ return true if user_group_symbol == Lockdown.administrator_group_symbol
138
+ get_user_groups.include?(user_group_symbol)
139
+ end
140
+
141
+ alias_method :has_user_group?, :user_group_exists?
142
+
143
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
144
+ # =Convenience methods for permissions and user groups
145
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
146
+
147
+ # Pass in a user object to be associated to the administrator user group
148
+ # The group will be created if it doesn't exist
149
+ def make_user_administrator(usr)
150
+ user_groups = usr.send(Lockdown.user_groups_hbtm_reference)
151
+ user_groups << Lockdown.user_group_class.
152
+ find_or_create_by_name(Lockdown.administrator_group_string)
153
+ end
154
+
155
+
156
+ # Returns array of controller/action values all logged in users can access.
157
+ def standard_authorized_user_rights
158
+ public_access + protected_access
159
+ end
160
+
161
+ # Return array of controller/action values user can access.
162
+ def access_rights_for_user(usr)
163
+ return unless usr
164
+ return :all if administrator?(usr)
165
+
166
+ rights = standard_authorized_user_rights
167
+
168
+ user_groups = usr.send(Lockdown.user_groups_hbtm_reference)
169
+ user_groups.each do |grp|
170
+ permissions_for_user_group(grp).each do |perm|
171
+ rights += access_rights_for_permission(perm)
172
+ end
173
+ end
174
+ rights
175
+ end
176
+
177
+ # Return array of controller/action for a user group
178
+ def access_rights_for_user_group(user_group_sym)
179
+ res = []
180
+ permissions_for_user_group(user_group_sym).each do |perm|
181
+ res << access_rights_for_permission(perm)
182
+ end
183
+ res.flatten
184
+ end
185
+
186
+ # Return array of controller/action for a permission
187
+ def access_rights_for_permission(perm)
188
+ sym = Lockdown.get_symbol(perm)
189
+
190
+ permissions[sym]
191
+ rescue
192
+ raise SecurityError, "Permission requested is not defined: #{sym}"
193
+ end
194
+
195
+
196
+ # Test user for administrator rights
197
+ def administrator?(usr)
198
+ user_has_user_group?(usr, Lockdown.administrator_group_symbol)
199
+ end
200
+
201
+ # Pass in user object and symbol for name of user group
202
+ def user_has_user_group?(usr, sym)
203
+ user_groups = usr.send(Lockdown.user_groups_hbtm_reference)
204
+ user_groups.any? do |ug|
205
+ Lockdown.convert_reference_name(ug.name) == sym
206
+ end
207
+ end
208
+
209
+ # Use this for the management screen to restrict user group list to the
210
+ # user. This will prevent a user from creating a user with more power than
211
+ # him/her self.
212
+ def user_groups_assignable_for_user(usr)
213
+ return [] if usr.nil?
214
+ ug_table = Lockdown.user_groups_hbtm_reference.to_s
215
+ if administrator?(usr)
216
+ Lockdown.user_group_class.find_by_sql <<-SQL
217
+ select #{ug_table}.* from #{ug_table} order by #{ug_table}.name
218
+ SQL
219
+ else
220
+ usr_table = Lockdown.users_hbtm_reference.to_s
221
+ if usr_table < ug_table
222
+ join_table = "#{usr_table}_#{ug_table}"
223
+ else
224
+ join_table = "#{ug_table}_#{usr_table}"
225
+ end
226
+ Lockdown.user_group_class.find_by_sql <<-SQL
227
+ select #{ug_table}.* from #{ug_table}, #{join_table}
228
+ where #{ug_table}.id = #{join_table}.#{Lockdown.user_group_id_reference}
229
+ and #{join_table}.#{Lockdown.user_id_reference} = #{usr.id}
230
+ order by #{ug_table}.name
231
+ SQL
232
+ end
233
+ end
234
+
235
+ # Similar to user_groups_assignable_for_user, this method should be
236
+ # used to restrict users from creating a user group with more power than
237
+ # they have been allowed.
238
+ def permissions_assignable_for_user(usr)
239
+ return [] if usr.nil?
240
+ if administrator?(usr)
241
+ get_permissions.collect do |k|
242
+ ::Permission.find_by_name(Lockdown.get_string(k))
243
+ end.compact
244
+ else
245
+ user_groups_assignable_for_user(usr).collect do |g|
246
+ g.permissions
247
+ end.flatten.compact
248
+ end
249
+ end
250
+
251
+ # Returns and array of permission symbols for the user group
252
+ def permissions_for_user_group(ug)
253
+ sym = Lockdown.get_symbol(ug)
254
+ perm_array = []
255
+
256
+ if has_user_group?(sym)
257
+ permissions = user_groups[sym] || []
258
+ else
259
+ if ug.respond_to?(:permissions)
260
+ permissions = ug.permissions
261
+ else
262
+ raise GroupUndefinedError, "#{ug} not found in init.rb and does not respond to #permissions"
263
+ end
264
+ end
265
+
266
+
267
+ permissions.each do |perm|
268
+ perm_sym = Lockdown.get_symbol(perm)
269
+
270
+ unless permission_exists?(perm_sym)
271
+ msg = "Permission associated to User Group is invalid: #{perm}"
272
+ raise SecurityError, msg
273
+ end
274
+
275
+ perm_array << perm_sym
276
+ end
277
+
278
+ perm_array
279
+ end
280
+
281
+ def process_rules
282
+ parse_permissions
283
+ validate_user_groups
284
+ end
285
+
286
+ private
287
+
288
+ def find_permission_object(perm_symbol)
289
+ obj = permission_objects.find{|name, pobj| pobj.name == perm_symbol}
290
+ obj[1] if obj
291
+ end
292
+
293
+ def validate_user_groups
294
+ user_groups.each do |user_group, perms|
295
+ perms.each do |perm|
296
+ unless permission_exists?(perm)
297
+ msg ="User Group: #{user_group}, permission not found: #{perm}"
298
+ raise Lockdown::InvalidRuleAssignment, msg
299
+ end
300
+ end
301
+ end
302
+ end
303
+
304
+ def parse_permissions
305
+ permission_objects.each do |name, perm|
306
+ @permissions[perm.name] ||= []
307
+ set_controller_access(perm)
308
+ end
309
+
310
+ set_model_access
311
+ end
312
+
313
+ def set_controller_access(perm)
314
+ perm.controllers.each do |name, controller|
315
+ controller.set_access_methods
316
+
317
+ @permissions[perm.name] |= controller.access_methods
318
+
319
+ if perm.public_access?
320
+ @public_access |= controller.access_methods
321
+ elsif perm.protected_access?
322
+ @protected_access |= controller.access_methods
323
+ end
324
+ end
325
+ end
326
+
327
+ def set_model_access
328
+ method_definition = "\tdef check_model_authorization\n\t#This method will check for access to model resources\n"
329
+
330
+ permission_objects.each do |name, perm|
331
+ next if perm.models.empty?
332
+
333
+ #Set filter for each controller
334
+ perm.controllers.each do |controller_name, controller|
335
+ #Set filter for each model on controller
336
+ perm.models.each do |model_name, model|
337
+ method_definition << define_restrict_model_access(controller, model)
338
+ end
339
+ end
340
+ end
341
+
342
+ method_definition << "\n\tend"
343
+
344
+ Lockdown.add_controller_method method_definition
345
+ end
346
+
347
+ def define_restrict_model_access(controller, model)
348
+ controller_class = Lockdown.fetch_controller_class(controller.name)
349
+
350
+ methods = controller.
351
+ access_methods.
352
+ collect do |am|
353
+ am[am.index('/') + 1..-1].to_sym if am.index('/')
354
+ end.compact.inspect
355
+
356
+ return <<-RUBY
357
+ if controller_name == "#{controller.name}"
358
+ if #{methods}.include?(action_name.to_sym)
359
+ unless instance_variable_defined?(:@#{model.name})
360
+ @#{model.name} = #{model.class_name}.find(params[#{model.param.inspect}])
361
+ end
362
+ # Need to make sure we find the model first before checking admin status.
363
+ return true if current_user_is_admin?
364
+ unless @#{model.name}.#{model.model_method}.#{model.association}(#{model.controller_method})
365
+ raise SecurityError, "Access to #\{action_name\} denied to #{model.name}.id #\{@#{model.name}.id\}"
366
+ end
367
+ end
368
+ end
369
+ RUBY
370
+ end
371
+ end
372
+ end
@@ -0,0 +1,66 @@
1
+ module Lockdown
2
+ module Session
3
+
4
+ protected
5
+
6
+ def access_rights_from_session
7
+ groups = session[:user_groups] || [] # => [:consumer, :collaborator]
8
+ groups.inject([]) {|ar, g| ar += Lockdown::System.access_rights_for_user_group(g) }
9
+ end
10
+
11
+ def add_lockdown_session_values(user = nil)
12
+ user ||= current_user
13
+
14
+ if user
15
+ session[:user_groups] = groups_for_user(user)
16
+ session[:current_user_id] = user.id
17
+ end
18
+ end
19
+
20
+ def groups_for_user(user)
21
+ user.send(Lockdown.user_groups_hbtm_reference).map {|ug| Lockdown.get_symbol(ug) }
22
+ end
23
+
24
+ def logged_in?
25
+ current_user_id.to_i > 0
26
+ end
27
+
28
+ def current_user_id
29
+ session[:current_user_id]
30
+ end
31
+
32
+ def current_user_is_admin?
33
+ session[:access_rights] == :all
34
+ end
35
+
36
+ def current_user_access_in_group?(grp)
37
+ return true if current_user_is_admin?
38
+ Lockdown::System.user_groups[grp].each do |perm|
39
+ return true if access_in_perm?(perm)
40
+ end
41
+ false
42
+ end
43
+
44
+ def access_in_perm?(perm)
45
+ if Lockdown::System.permissions[perm]
46
+ Lockdown::System.permissions[perm].each do |ar|
47
+ return true if session_access_rights_include?(ar)
48
+ end
49
+ end
50
+ false
51
+ end
52
+
53
+ def session_access_rights_include?(str)
54
+ return false unless session[:access_rights]
55
+ session[:access_rights].include?(str)
56
+ end
57
+
58
+ def reset_lockdown_session
59
+ [:expiry_time, :current_user_id, :access_rights, :user_groups].each do |val|
60
+ session[val] = nil if session[val]
61
+ end
62
+ end
63
+
64
+ alias_method :nil_lockdown_values, :reset_lockdown_session
65
+ end # Session
66
+ end # Lockdown
@@ -0,0 +1,58 @@
1
+ module Lockdown
2
+ class System
3
+ extend Lockdown::Rules
4
+
5
+ def self.configure(&block)
6
+ set_defaults
7
+
8
+ # Lockdown::Rules defines the methods that are used inside block
9
+ instance_eval(&block)
10
+
11
+ # Lockdown::Rules defines process_rules
12
+ process_rules
13
+
14
+ Lockdown::Database.sync_with_db unless skip_sync?
15
+
16
+ @initialized = true if Lockdown.caching?
17
+ end
18
+
19
+ def self.initialized?
20
+ @initialized
21
+ end
22
+
23
+ def self.fetch(key)
24
+ (@options||={})[key]
25
+ end
26
+
27
+ def self.call(object, system_option)
28
+ method = fetch(system_option)
29
+ if method.is_a?(Symbol) && object.respond_to?(method)
30
+ object.send(method)
31
+ end
32
+ end
33
+
34
+ protected
35
+
36
+ def self.paths_for(str_sym, *methods)
37
+ str_sym = str_sym.to_s if str_sym.is_a?(Symbol)
38
+ if methods.empty?
39
+ klass = Lockdown.fetch_controller_class(str_sym)
40
+ methods = available_actions(klass)
41
+ end
42
+ path_str = str_sym.gsub("__","\/")
43
+
44
+ subdir = Lockdown::System.fetch(:subdirectory)
45
+ path_str = "#{subdir}/#{path_str}" if subdir
46
+
47
+ controller_actions = methods.flatten.collect{|m| m.to_s}
48
+
49
+ paths = controller_actions.collect{|meth| "#{path_str}/#{meth.to_s}" }
50
+
51
+ if controller_actions.include?("index")
52
+ paths += [path_str]
53
+ end
54
+
55
+ paths
56
+ end
57
+ end # System class
58
+ end # Lockdown