lockdown 0.3.15 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt CHANGED
@@ -1,3 +1,9 @@
1
+ == 0.4.0 2008-05-04
2
+ * Added: Automatically sync definitions in init.rb with database to remove migrations requirement
3
+ * Added: Improved notification if invalid user group or permission is referenced in init.rb
4
+ * Added: Check in user_groups controller to prevent url hack and modify/destroy user group defined in init.rb
5
+ * Modified: Renamed access_rights_for_perm to access_rights_for_permission for consistency sake. Change then method call in permissions_helper if you have this installed
6
+
1
7
  == 0.3.15 2008-05-03
2
8
  * Fixed: The controller inspection code was short-circuiting the Dependencies reload mechanism while in development mode.
3
9
 
@@ -20,6 +20,10 @@ Lockdown::System.configure do
20
20
  # Set redirect to path on successful login:
21
21
  # options[:successful_login_path] = "/"
22
22
  #
23
+ # Set the system to sync the Permissions and UserGroups defined here
24
+ # with the database.
25
+ # options[:sync_init_rb_with_db] = true
26
+ #
23
27
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24
28
  # Define permissions
25
29
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -22,6 +22,16 @@ module Lockdown
22
22
  str_sym.is_a?(String) ? convert_reference_name(str_sym) : str_sym
23
23
  end
24
24
 
25
+ def lockdown_symbol(value)
26
+ if value.respond_to?(:name)
27
+ symbol_name(value.name)
28
+ elsif value.is_a?(String)
29
+ symbol_name(value)
30
+ else
31
+ value
32
+ end
33
+ end
34
+
25
35
  def camelize(str)
26
36
  str.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
27
37
  end
@@ -20,8 +20,11 @@ module Lockdown
20
20
  attr_accessor :controller_classes #:nodoc:
21
21
 
22
22
  def configure(&block)
23
- self.set_defaults
24
- self.instance_eval(&block)
23
+ set_defaults
24
+ instance_eval(&block)
25
+ if options[:use_db_models] && options[:sync_init_rb_with_db]
26
+ sync_with_db
27
+ end
25
28
  end
26
29
 
27
30
  def [](key)
@@ -41,67 +44,99 @@ module Lockdown
41
44
  @permissions.keys
42
45
  end
43
46
 
47
+ def permission_exists?(perm)
48
+ get_permissions.include?(perm)
49
+ end
50
+
44
51
  def set_user_group(name, *perms)
45
52
  @user_groups[name] ||= []
46
- perms.each{|perm| @user_groups[name].push(perm)}
53
+ perms.each do |perm|
54
+ unless permission_exists?(perm)
55
+ raise SecurityError, "For UserGroup (#{name}), permission is invalid: #{perm}"
56
+ end
57
+ @user_groups[name].push(perm)
58
+ end
47
59
  end
48
60
 
49
61
  def get_user_groups
50
62
  @user_groups.keys
51
63
  end
52
64
 
65
+ def permissions_for_user_group(ug)
66
+ sym = lockdown_symbol(ug)
67
+
68
+ if has_user_group?(sym)
69
+ @user_groups[sym].each do |perm|
70
+ unless permission_exists?(perm)
71
+ raise SecurityError, "Permission associated to User Group is invalid: #{perm}"
72
+ end
73
+ yield perm
74
+ end
75
+ elsif ug.responds_to?(:name)
76
+ # This user group was defined in the database
77
+ ug.permissions.each do |perm|
78
+ perm_sym = symbol_name(perm.name)
79
+ unless permission_exists?(perm_sym)
80
+ raise SecurityError, "Permission associated to User Group is invalid: #{perm_sym}"
81
+ end
82
+ yield perm_sym
83
+ end
84
+ else
85
+ raise SecurityError, "UserGroup is not known: #{ug.inspect}"
86
+ end
87
+ end
88
+
89
+ def access_rights_for_permission(perm)
90
+ sym = lockdown_symbol(perm)
91
+
92
+ unless permission_exists?(sym)
93
+ raise SecurityError, "Permission requested is not defined: #{sym}"
94
+ end
95
+ @permissions[sym]
96
+ end
97
+
98
+ def public_access?(perm)
99
+ @public_access.include?(perm)
100
+ end
101
+
53
102
  def set_public_access(*perms)
54
103
  perms.each{|perm| @public_access += @permissions[perm]}
55
104
  end
56
105
 
106
+ def protected_access?(perm)
107
+ @protected_access.include?(perm)
108
+ end
109
+
57
110
  def set_protected_access(*perms)
58
111
  perms.each{|perm| @protected_access += @permissions[perm]}
59
112
  end
60
113
 
114
+ def permission_assigned_automatically?(perm)
115
+ public_access?(perm) || protected_access?(perm)
116
+ end
117
+
61
118
  def standard_authorized_user_rights
62
119
  Lockdown::System.public_access + Lockdown::System.protected_access
63
120
  end
64
121
 
65
- #
66
- # Create a user group record in the database
67
- #
68
- def create_user_group(str_sym)
69
- return unless @options[:use_db_models]
70
- ug = UserGroup.create(:name => string_name(str_sym))
71
- #
72
- # No need to create permissions records for administrators
73
- #
74
- ug_sym = symbol_name(ug.name)
75
- return if ug_sym == administrator_group_symbol
76
-
77
- if self.has_user_group?(ug)
78
- @user_groups[ug_sym].collect do |perm|
79
- Permission.create(:name => string_name(perm))
80
- end
81
- end
82
- end
83
-
84
- def create_administrator_user_group
85
- return unless @options[:use_db_models]
86
- Lockdown::System.create_user_group administrator_group_symbol
87
- end
88
-
89
122
  #
90
123
  # Determine if the user group is defined in init.rb
91
124
  #
92
125
  def has_user_group?(ug)
93
- return true if symbol_name(ug.name) == administrator_group_symbol
94
- @user_groups.each do |key,value|
95
- return true if key == symbol_name(ug.name)
126
+ sym = lockdown_symbol(ug)
127
+
128
+ return true if sym == administrator_group_symbol
129
+ get_user_groups.each do |key|
130
+ return true if key == sym
96
131
  end
97
- return false
132
+ false
98
133
  end
99
134
 
100
135
  #
101
136
  # Delete a user group record from the database
102
137
  #
103
138
  def delete_user_group(str_sym)
104
- ug = UserGroup.find_by_name(string_name(str_sym))
139
+ ug = UserGroup.find(:first, :conditions => ["name = ?",string_name(str_sym)])
105
140
  ug.destroy unless ug.nil?
106
141
  end
107
142
 
@@ -113,24 +148,14 @@ module Lockdown
113
148
 
114
149
  if @options[:use_db_models]
115
150
  usr.user_groups.each do |grp|
116
- if @user_groups.has_key? symbol_name(grp.name)
117
- @user_groups[symbol_name(grp.name)].each do |perm|
118
- rights += @permissions[perm]
119
- end
120
- else
121
- grp.permissions.each do |perm|
122
- rights += @permissions[symbol_name(perm.name)]
123
- end
124
- end
151
+ permissions_for_user_group(grp) do |perm|
152
+ rights += access_rights_for_permission(perm)
153
+ end
125
154
  end
126
155
  end
127
156
  rights
128
157
  end
129
158
 
130
- def access_rights_for_perm(perm)
131
- (perms = @permissions[symbol_name(perm.name)]) == nil ? [] : perms
132
- end
133
-
134
159
  #
135
160
  # Use this for the management screen to restrict user group list to the
136
161
  # user. This will prevent a user from creating a user with more power than
@@ -168,9 +193,13 @@ module Lockdown
168
193
  end
169
194
 
170
195
  def make_user_administrator(usr)
196
+ unless Lockdown.database_table_exists?(UserGroup)
197
+ create_administrator_user_group
198
+ end
199
+
171
200
  usr.user_groups << UserGroup.find_or_create_by_name(administrator_group_string)
172
201
  end
173
-
202
+
174
203
  def administrator?(usr)
175
204
  user_has_user_group?(usr, administrator_group_symbol)
176
205
  end
@@ -196,16 +225,22 @@ module Lockdown
196
225
  @private_access = []
197
226
 
198
227
  @options = {
199
- :use_db_models => true,
200
- :session_timeout => (60 * 60),
201
- :logout_on_access_violation => false,
202
- :access_denied_path => "/",
203
- :successful_login_path => "/"
204
- }
228
+ :use_db_models => true,
229
+ :sync_init_rb_with_db => true,
230
+ :session_timeout => (60 * 60),
231
+ :logout_on_access_violation => false,
232
+ :access_denied_path => "/",
233
+ :successful_login_path => "/"
234
+ }
205
235
  end
206
236
 
207
237
  private
208
238
 
239
+ def create_administrator_user_group
240
+ return unless @options[:use_db_models]
241
+ UserGroup.create :name => administrator_group_name
242
+ end
243
+
209
244
  def user_has_user_group?(usr, sym)
210
245
  usr.user_groups.each do |ug|
211
246
  return true if convert_reference_name(ug.name) == sym
@@ -227,7 +262,7 @@ module Lockdown
227
262
  end
228
263
 
229
264
  def controller_class_name_from_file(str)
230
- str.split(".")[0].split("/").collect{|str| camelize(str) }.join("::")
265
+ str.split(".")[0].split("/").collect{|s| camelize(s) }.join("::")
231
266
  end
232
267
 
233
268
  def controller_class_name(str)
@@ -274,6 +309,64 @@ module Lockdown
274
309
  const_get(klass)
275
310
  end
276
311
  end
277
- end # class block
312
+
313
+ #
314
+ # This is very basic and could be handled better using orm specific
315
+ # functionality, but I wanted to keep it generic to avoid creating
316
+ # an interface for each the different orm implementations.
317
+ # We'll see how it works...
318
+ #
319
+ def sync_with_db
320
+ return unless database_configured?
321
+ # Create permissions not found in the database
322
+ get_permissions.each do |key|
323
+ next if permission_assigned_automatically?(key)
324
+ str = string_name(key)
325
+ p = Permission.find(:first, :conditions => ["name = ?", str])
326
+ unless p
327
+ puts ">> Lockdown: Permission not found in db: #{str}, creating."
328
+ Permission.create(:name => str)
329
+ end
330
+ end
331
+
332
+ #
333
+ # Delete the permissions not found in init.rb
334
+ #
335
+ db_perms = Permission.find(:all).dup
336
+ perm_keys = get_permissions
337
+ db_perms.each do |dbp|
338
+ unless perm_keys.include?(symbol_name(dbp.name))
339
+ puts ">> Lockdown: Permission no longer in init.rb: #{dbp.name}, deleting."
340
+ Lockdown.database_execute("delete from permissions_user_groups where permission_id = #{dbp.id}")
341
+ dbp.destroy
342
+ end
343
+ end
344
+
345
+ # Create user groups not found in the database
346
+ get_user_groups.each do |key|
347
+ str = string_name(key)
348
+ ug = UserGroup.find(:first, :conditions => ["name = ?", str])
349
+ unless ug
350
+ puts ">> Lockdown: UserGroup not in the db: #{str}, creating."
351
+ ug = UserGroup.create(:name => str)
352
+ #Inefficient, definitely, but shouldn't have any issues across orms.
353
+ permissions_for_user_group(key) do |perm|
354
+ p = Permission.find(:first, :conditions => ["name = ?", string_name(perm)])
355
+ Lockdown.database_execute <<-SQL
356
+ insert into permissions_user_groups(permission_id, user_group_id)
357
+ values(#{p.id}, #{ug.id})
358
+ SQL
359
+ end
360
+ end
361
+ end
362
+ end
363
+
364
+ def database_configured?
365
+ return unless const_defined?("Permission") && const_defined?("UserGroup")
366
+
367
+ Lockdown.database_table_exists?(Permission) &&
368
+ Lockdown.database_table_exists?(UserGroup)
369
+ end
370
+ end # class block
278
371
  end # System class
279
372
  end # Lockdown
@@ -1,8 +1,8 @@
1
1
  module Lockdown #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 3
5
- TINY = 15
4
+ MINOR = 4
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/lib/lockdown.rb CHANGED
@@ -47,6 +47,35 @@ module Lockdown
47
47
  end
48
48
  end
49
49
 
50
+ def database_execute(query)
51
+ if active_record_orm?
52
+ ActiveRecord::Base.connection.execute(query)
53
+ elsif datamapper_orm?
54
+ DataMapper.database.execute(query)
55
+ else
56
+ raise NotImplementedError, "ORM unknown to Lockdown! Lockdown recognizes DataMapper and ActiveRecord"
57
+ end
58
+ end
59
+
60
+ def database_query(query)
61
+ if active_record_orm?
62
+ ActiveRecord::Base.connection.execute(query)
63
+ elsif datamapper_orm?
64
+ DataMapper.database.query(query)
65
+ else
66
+ raise NotImplementedError, "ORM unknown to Lockdown! Lockdown recognizes DataMapper and ActiveRecord"
67
+ end
68
+ end
69
+
70
+ def database_table_exists?(klass)
71
+ if active_record_orm?
72
+ klass.table_exists?
73
+ elsif datamapper_orm?
74
+ DataMapper.database.table_exists?(klass)
75
+ else
76
+ raise NotImplementedError, "ORM unknown to Lockdown! Lockdown recognizes DataMapper and ActiveRecord"
77
+ end
78
+ end
50
79
  private
51
80
 
52
81
  def project_related_value(merb_val, rails_val)
@@ -88,6 +88,9 @@ class UserGroupsController < ApplicationController
88
88
 
89
89
  def find_user_group
90
90
  @user_group = UserGroup.find(params[:id])
91
+ if @action_name != "show" && Lockdown::System.has_user_group?(@user_group)
92
+ raise SecurityError,"Invalid attempt to modify user group."
93
+ end
91
94
  end
92
95
 
93
96
  def update_permissions
@@ -4,7 +4,7 @@ module PermissionsHelper
4
4
  end
5
5
 
6
6
  def permission_access_rights_value
7
- Lockdown::System.access_rights_for_perm(@permission).collect{|r| r}.join("<br/>")
7
+ Lockdown::System.access_rights_for_permission(@permission).collect{|r| r}.join("<br/>")
8
8
  end
9
9
 
10
10
  def permission_users_value
@@ -1,11 +1,5 @@
1
1
  class CreateAdminUserAndUserGroup < ActiveRecord::Migration
2
2
  def self.up
3
- #
4
- # Creating an administrators user group database record
5
- # to allow for the creation of other administrators
6
- #
7
- Lockdown::System.create_administrator_user_group
8
-
9
3
  # TODO: Change the password
10
4
  u = User.new( :password => "password",
11
5
  :password_confirmation => "password",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lockdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.15
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Stone
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-05-03 00:00:00 -04:00
12
+ date: 2008-05-05 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency