lockdown 0.9.8 → 1.0.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.
@@ -4,11 +4,7 @@ module Lockdown
4
4
  module Controller
5
5
 
6
6
  def available_actions(klass)
7
- if klass.respond_to?(:action_methods)
8
- klass.action_methods
9
- else
10
- klass.public_instance_methods - klass.hidden_actions
11
- end
7
+ klass.action_methods
12
8
  end
13
9
 
14
10
  def controller_name(klass)
@@ -17,6 +13,7 @@ module Lockdown
17
13
 
18
14
  # Locking methods
19
15
  module Lock
16
+
20
17
  def configure_lockdown
21
18
  check_session_expiry
22
19
  store_location
@@ -32,9 +29,11 @@ module Lockdown
32
29
 
33
30
  def check_request_authorization
34
31
  unless authorized?(path_from_hash(params))
35
- raise SecurityError, "Authorization failed for params #{params.inspect}"
32
+ raise SecurityError, "Authorization failed! \nparams: #{params.inspect}\nsession: #{session.inspect}"
36
33
  end
37
34
  end
35
+
36
+ protected
38
37
 
39
38
  def path_allowed?(url)
40
39
  session[:access_rights] ||= Lockdown::System.public_access
@@ -76,7 +75,7 @@ module Lockdown
76
75
  begin
77
76
  hash = ActionController::Routing::Routes.recognize_path(path, :method => method)
78
77
  return path_allowed?(path_from_hash(hash)) if hash
79
- rescue Exception
78
+ rescue Exception => e
80
79
  # continue on
81
80
  end
82
81
 
@@ -13,34 +13,39 @@ module Lockdown
13
13
  mod.extend Lockdown::Frameworks::Rails::Environment
14
14
  mixin
15
15
  end
16
-
16
+
17
17
  def mixin
18
- Lockdown.controller_parent.class_eval do
18
+ mixin_controller
19
+
20
+ Lockdown.view_helper.class_eval do
21
+ include Lockdown::Frameworks::Rails::View
22
+ end
23
+
24
+ Lockdown::System.class_eval do
25
+ extend Lockdown::Frameworks::Rails::System
26
+ end
27
+ end
28
+
29
+ def mixin_controller(klass = Lockdown.controller_parent)
30
+ klass.class_eval do
19
31
  include Lockdown::Session
20
32
  include Lockdown::Frameworks::Rails::Controller::Lock
21
33
  end
22
34
 
23
- Lockdown.controller_parent.helper_method :authorized?
35
+ klass.helper_method :authorized?
36
+
37
+ klass.hide_action(:set_current_user, :configure_lockdown, :check_request_authorization)
24
38
 
25
- Lockdown.controller_parent.before_filter do |c|
39
+ klass.before_filter do |c|
26
40
  c.set_current_user
27
41
  c.configure_lockdown
28
42
  c.check_request_authorization
43
+ c.check_model_authorization
29
44
  end
30
45
 
31
- Lockdown.controller_parent.filter_parameter_logging :password,
32
- :password_confirmation
46
+ klass.filter_parameter_logging :password, :password_confirmation
33
47
 
34
- Lockdown.controller_parent.rescue_from SecurityError,
35
- :with => proc{|e| access_denied(e)}
36
-
37
- Lockdown.view_helper.class_eval do
38
- include Lockdown::Frameworks::Rails::View
39
- end
40
-
41
- Lockdown::System.class_eval do
42
- extend Lockdown::Frameworks::Rails::System
43
- end
48
+ klass.rescue_from SecurityError, :with => proc{|e| access_denied(e)}
44
49
  end
45
50
  end # class block
46
51
 
@@ -54,12 +59,24 @@ module Lockdown
54
59
  "#{project_root}/lib/lockdown/init.rb"
55
60
  end
56
61
 
62
+ def view_helper
63
+ ::ActionView::Base
64
+ end
65
+
66
+ # cache_classes is true in production and testing, need to
67
+ # modify the ApplicationController
57
68
  def controller_parent
58
- ::ActionController::Base
69
+ if ::Rails.env == 'development'
70
+ ActionController::Base
71
+ else
72
+ ApplicationController
73
+ end
59
74
  end
60
75
 
61
- def view_helper
62
- ::ActionView::Base
76
+ # cache_classes is true in production and testing, need to
77
+ # do an instance eval instead
78
+ def add_controller_method(code)
79
+ Lockdown.controller_parent.class_eval code, __FILE__,__LINE__ +1
63
80
  end
64
81
 
65
82
  def controller_class_name(str)
@@ -70,6 +87,10 @@ module Lockdown
70
87
  Lockdown.camelize(str)
71
88
  end
72
89
  end
90
+
91
+ def fetch_controller_class(str)
92
+ eval("::#{controller_class_name(str)}")
93
+ end
73
94
  end
74
95
 
75
96
  module System
@@ -78,68 +99,6 @@ module Lockdown
78
99
  def skip_sync?
79
100
  Lockdown::System.fetch(:skip_db_sync_in).include?(ENV['RAILS_ENV'])
80
101
  end
81
-
82
- def load_controller_classes
83
- @controller_classes = {}
84
-
85
- maybe_load_framework_controller_parent
86
-
87
- ApplicationController.helper_method :authorized?
88
-
89
- ApplicationController.before_filter do |c|
90
- c.set_current_user
91
- c.configure_lockdown
92
- c.check_request_authorization
93
- end
94
-
95
- ApplicationController.filter_parameter_logging :password,
96
- :password_confirmation
97
-
98
- ApplicationController.rescue_from SecurityError,
99
- :with => proc{|e| access_denied(e)}
100
-
101
-
102
- Dir.chdir("#{Lockdown.project_root}/app/controllers") do
103
- Dir["**/*.rb"].sort.each do |c|
104
- next if c == "application.rb"
105
- lockdown_load(c)
106
- end
107
- end
108
-
109
- if ENV['RAILS_ENV'] != 'production'
110
- if ActiveSupport.const_defined?("Dependencies")
111
- ActiveSupport::Dependencies.clear
112
- else
113
- Dependencies.clear
114
- end
115
- end
116
- end
117
-
118
- def maybe_load_framework_controller_parent
119
- if ::Rails::VERSION::MAJOR >= 2 && ::Rails::VERSION::MINOR >= 3
120
- filename = "application_controller.rb"
121
- else
122
- filename = "application.rb"
123
- end
124
-
125
- require_or_load(filename)
126
- end
127
-
128
- def lockdown_load(filename)
129
- klass = Lockdown.class_name_from_file(filename)
130
-
131
- require_or_load(filename)
132
-
133
- @controller_classes[klass] = Lockdown.qualified_const_get(klass)
134
- end
135
-
136
- def require_or_load(filename)
137
- if ActiveSupport.const_defined?("Dependencies")
138
- ActiveSupport::Dependencies.require_or_load(filename)
139
- else
140
- Dependencies.require_or_load(filename)
141
- end
142
- end
143
102
  end # System
144
103
  end # Rails
145
104
  end # Frameworks
@@ -49,24 +49,6 @@ module Lockdown
49
49
  :administrators
50
50
  end
51
51
 
52
- def qualified_const_defined?(klass)
53
- if klass =~ /::/
54
- namespace, klass = klass.split("::")
55
- eval("#{namespace}.const_defined?(#{klass})") if const_defined?(namespace)
56
- else
57
- const_defined?(klass)
58
- end
59
- end
60
-
61
- def qualified_const_get(klass)
62
- if klass =~ /::/
63
- namespace, klass = klass.split("::")
64
- eval(namespace).const_get(klass)
65
- else
66
- const_get(klass)
67
- end
68
- end
69
-
70
52
  private
71
53
 
72
54
  def string_name(str_sym)
@@ -3,23 +3,46 @@ module Lockdown
3
3
  class PermissionScopeCollision < StandardError; end
4
4
 
5
5
  class Controller
6
- attr_accessor :name, :access_methods
6
+ attr_accessor :name, :access_methods, :only_methods, :except_methods
7
7
 
8
8
  def initialize(name)
9
9
  @name = name
10
+ @except_methods = []
11
+ end
12
+
13
+ def set_access_methods
14
+ if @only_methods
15
+ @access_methods = paths_for(@name, *@only_methods)
16
+ else
17
+ @access_methods = paths_for(@name)
18
+ end
19
+
20
+ apply_exceptions
21
+ end
22
+
23
+ private
24
+
25
+ def apply_exceptions
26
+ @access_methods = @access_methods - @except_methods
27
+ end
28
+
29
+ def paths_for(str_sym, *methods)
30
+ Lockdown::System.paths_for(str_sym, *methods)
10
31
  end
11
32
  end
12
33
 
13
34
  class Model
14
- attr_accessor :name, :controller_method, :model_method, :association
35
+ attr_accessor :name, :controller_method, :model_method, :association, :param
15
36
 
16
- def initialize(name)
37
+ def initialize(name, param = :id)
17
38
  @name = name
39
+ @param = :id
18
40
  end
19
41
 
20
- def association=(type)
21
- @assocation = type
42
+ def class_name
43
+ self.name.to_s.camelize
22
44
  end
45
+
23
46
  end
24
47
 
25
48
  class Permission
@@ -42,16 +65,16 @@ module Lockdown
42
65
  # ==== Summary of model oriented methods:
43
66
  #
44
67
  # # defines which model we're talking about
45
- # .to_model(:model_name)
68
+ # .to_model(:model)
46
69
  #
47
- # # data_method must be available to the controller
48
- # .where(:data_method)
70
+ # # model_method is simply a public method on :model
71
+ # .where(:model_method)
49
72
  #
50
- # # model_name.value_method must equal data_method
51
- # .equals(:value_method)
73
+ # # controller_method must equal model_method
74
+ # .equals(:controller_method)
52
75
  #
53
- # # model_name.values_method.include?(data_method)
54
- # .is_in(:values_method)
76
+ # # controller_method.include?(model_method)
77
+ # .is_in(:controller_method)
55
78
  #
56
79
  #
57
80
  # ==== Example:
@@ -84,7 +107,6 @@ module Lockdown
84
107
  validate_context
85
108
 
86
109
  controller = Controller.new(name_symbol)
87
- controller.access_methods = paths_for(name_symbol)
88
110
  @controllers[name_symbol] = controller
89
111
  @current_context = Lockdown::ControllerContext.new(name_symbol)
90
112
  self
@@ -95,8 +117,7 @@ module Lockdown
95
117
  def only_methods(*methods)
96
118
  validate_context
97
119
 
98
- current_controller.access_methods = paths_for(current_controller.name,
99
- *methods)
120
+ current_controller.only_methods = methods
100
121
  @current_context = Lockdown::RootContext.new(@name)
101
122
  self
102
123
  end
@@ -104,39 +125,40 @@ module Lockdown
104
125
  def except_methods(*methods)
105
126
  validate_context
106
127
 
107
- current_controller.access_methods = current_controller.access_methods - paths_for(current_controller.name, *methods)
128
+ current_controller.except_methods = methods
108
129
 
109
130
  @current_context = Lockdown::RootContext.new(@name)
110
131
  self
111
132
  end
112
133
 
113
- def to_model(name_symbol)
134
+ def to_model(name_symbol, param = :id)
114
135
  validate_context
115
136
 
116
- @models[name_symbol] = Model.new(name_symbol)
137
+ @models[name_symbol] = Model.new(name_symbol, param)
117
138
  @current_context = Lockdown::ModelContext.new(name_symbol)
118
139
  self
119
140
  end
120
141
 
121
- def where(controller_method)
142
+ def where(model_method)
122
143
  validate_context
123
144
 
145
+ current_model.model_method = model_method
124
146
  @current_context = Lockdown::ModelWhereContext.new(current_context.name)
125
147
  self
126
148
  end
127
149
 
128
- def equals(model_method)
150
+ def equals(controller_method)
129
151
  validate_context
130
152
 
131
- associate_model_method(model_method, :equals)
153
+ associate_controller_method(controller_method, :==)
132
154
  @current_context = Lockdown::RootContext.new(@name)
133
155
  self
134
156
  end
135
157
 
136
- def is_in(model_method)
158
+ def is_in(controller_method)
137
159
  validate_context
138
160
 
139
- associate_model_method(model_method, :includes)
161
+ associate_controller_method(controller_method, :include?)
140
162
  @current_context = Lockdown::RootContext.new(@name)
141
163
  self
142
164
  end
@@ -183,8 +205,8 @@ module Lockdown
183
205
 
184
206
  private
185
207
 
186
- def associate_model_method(model_method, association)
187
- current_model.model_method = model_method
208
+ def associate_controller_method(controller_method, association)
209
+ current_model.controller_method = controller_method
188
210
  current_model.association = association
189
211
  @current_context = Lockdown::RootContext.new(@name)
190
212
  end
@@ -196,9 +218,5 @@ module Lockdown
196
218
  raise InvalidRuleContext, "Method: #{calling_method} was called on wrong context #{current_context}. Allowed methods are: #{current_context.allowed_methods.join(',')}."
197
219
  end
198
220
  end
199
-
200
- def paths_for(controller, *methods)
201
- Lockdown::System.paths_for(controller, *methods)
202
- end
203
221
  end
204
222
  end
@@ -5,7 +5,6 @@ module Lockdown
5
5
  attr_accessor :options
6
6
  attr_accessor :permissions
7
7
  attr_accessor :user_groups
8
- attr_accessor :controller_classes
9
8
 
10
9
  attr_reader :protected_access
11
10
  attr_reader :public_access
@@ -254,24 +253,36 @@ module Lockdown
254
253
  end
255
254
 
256
255
  def process_rules
257
- parse_permissions
258
256
  validate_user_groups
257
+ parse_permissions
259
258
  end
260
259
 
261
260
  private
262
261
 
262
+ def validate_user_groups
263
+ user_groups.each do |user_group, perms|
264
+ perms.each do |perm|
265
+ unless permission_exists?(perm)
266
+ msg ="User Group: #{user_group}, permission not found: #{perm}"
267
+ raise InvalidRuleAssignment, msg
268
+ end
269
+ end
270
+ end
271
+ end
272
+
263
273
  def parse_permissions
264
274
  permission_objects.each do |name, perm|
265
275
  @permissions[perm.name] ||= []
266
-
267
276
  set_controller_access(perm)
268
-
269
- set_model_access(perm)
270
277
  end
278
+
279
+ set_model_access
271
280
  end
272
281
 
273
282
  def set_controller_access(perm)
274
283
  perm.controllers.each do |name, controller|
284
+ controller.set_access_methods
285
+
275
286
  @permissions[perm.name] |= controller.access_methods
276
287
 
277
288
  if perm.public_access?
@@ -282,40 +293,49 @@ module Lockdown
282
293
  end
283
294
  end
284
295
 
285
- def set_model_access(perm)
286
- perm.models.each do |model|
287
- # Create inherited method on Lockdown.orm_parent that
288
- # will create a list of controller/actions the model
296
+ def set_model_access
297
+ method_definition = "\tdef check_model_authorization\n\t#This method will check for access to model resources\n"
298
+
299
+ permission_objects.each do |name, perm|
300
+ next if perm.models.empty?
301
+
302
+ #Set filter for each controller
303
+ perm.controllers.each do |controller_name, controller|
304
+ #Set filter for each model on controller
305
+ perm.models.each do |model_name, model|
306
+ method_definition << define_restrict_model_access(controller, model)
307
+ end
308
+ end
289
309
  end
290
310
 
291
- # Create method to access that list for link_to call validation
292
- #Lockdown.orm_parent.instance_eval <<-RUBY, __FILE__,__LINE__ + 1
293
- # def self.inherited(klass)
294
- # super
295
- #
296
- # end
297
- #RUBY
298
-
299
- # Create inherited method on Lockdown.controller_parent that
300
- # will setup before_filter
301
- #Lockdown.controller_parent.instance_eval <<-RUBY, __FILE__,__LINE__ + 1
302
- # def self.inherited(klass)
303
- # super
304
- #
305
- # end
306
- #RUBY
307
- end
311
+ method_definition << "\n\tend"
308
312
 
313
+ #puts "method_definition:\n #{method_definition}"
309
314
 
310
- def validate_user_groups
311
- user_groups.each do |user_group, perms|
312
- perms.each do |perm|
313
- unless permission_exists?(perm)
314
- msg ="User Group: #{user_group}, permission not found: #{perm}"
315
- raise InvalidRuleAssignment, msg
315
+ Lockdown.add_controller_method method_definition
316
+ end
317
+
318
+ def define_restrict_model_access(controller, model)
319
+ controller_class = Lockdown.fetch_controller_class(controller.name)
320
+
321
+ methods = controller.
322
+ access_methods.
323
+ collect{|am| am[am.index('/') + 1..-1].to_sym}.inspect
324
+
325
+ return <<-RUBY
326
+ if controller_name == "#{controller.name}"
327
+ if #{methods}.include?(action_name.to_sym)
328
+ unless instance_variable_defined?(:@#{model.name})
329
+ @#{model.name} = #{model.class_name}.find(params[#{model.param.inspect}])
330
+ end
331
+ # Need to make sure we find the model first before checking admin status.
332
+ return true if current_user_is_admin?
333
+ unless #{model.controller_method}.#{model.association}(@#{model.name}.#{model.model_method})
334
+ raise SecurityError, "Access to #\{action_name\} denied to #{model.name}.id #\{@#{model.name}.id\}"
335
+ end
316
336
  end
317
337
  end
318
- end
338
+ RUBY
319
339
  end
320
340
  end
321
341
  end
@@ -5,9 +5,6 @@ module Lockdown
5
5
  def self.configure(&block)
6
6
  set_defaults
7
7
 
8
- # Defined by the framework
9
- load_controller_classes
10
-
11
8
  # Lockdown::Rules defines the methods that are used inside block
12
9
  instance_eval(&block)
13
10
 
@@ -33,7 +30,7 @@ module Lockdown
33
30
  def self.paths_for(str_sym, *methods)
34
31
  str_sym = str_sym.to_s if str_sym.is_a?(Symbol)
35
32
  if methods.empty?
36
- klass = fetch_controller_class(str_sym)
33
+ klass = Lockdown.fetch_controller_class(str_sym)
37
34
  methods = available_actions(klass)
38
35
  end
39
36
  path_str = str_sym.gsub("__","\/")
@@ -51,10 +48,5 @@ module Lockdown
51
48
 
52
49
  paths
53
50
  end
54
-
55
- def self.fetch_controller_class(str)
56
- controller_classes[Lockdown.controller_class_name(str)]
57
- end
58
-
59
51
  end # System class
60
52
  end # Lockdown
data/lib/lockdown.rb CHANGED
@@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), "lockdown", "helper")
3
3
  module Lockdown
4
4
  extend Lockdown::Helper
5
5
 
6
- VERSION = '0.9.8'
6
+ VERSION = '1.0.0'
7
7
 
8
8
  # Returns the version string for the library.
9
9
  def self.version
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.9.8
4
+ version: 1.0.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: 2009-06-07 00:00:00 -04:00
12
+ date: 2009-07-08 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -128,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
128
  requirements: []
129
129
 
130
130
  rubyforge_project: lockdown
131
- rubygems_version: 1.3.3
131
+ rubygems_version: 1.3.4
132
132
  signing_key:
133
133
  specification_version: 3
134
134
  summary: Lockdown is an authorization system for RubyOnRails (ver >= 2