tuersteher 0.3.0 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.3.3
data/lib/tuersteher.rb CHANGED
@@ -37,30 +37,35 @@ module Tuersteher
37
37
 
38
38
  DEFAULT_RULES_CONFIG_FILE = 'access_rules.rb' # in config-dir
39
39
 
40
+ # private initializer why this class is a singleton
40
41
  def initialize
41
42
  @path_rules = []
42
43
  @model_rules = []
43
44
  end
44
45
 
46
+ # get all path_rules as array of PathAccessRule-Instances
45
47
  def path_rules
46
48
  read_rules unless @was_read
47
49
  @path_rules
48
50
  end
49
51
 
52
+ # get all model_rules as array of ModelAccessRule-Instances
50
53
  def model_rules
51
54
  read_rules unless @was_read
52
55
  @model_rules
53
56
  end
54
57
 
55
58
 
59
+ # evaluated rules_definitions and create path-/model-rules
56
60
  def eval_rules rules_definitions
57
61
  @path_rules = []
58
62
  @model_rules = []
59
63
  eval rules_definitions
64
+ @was_read = true
60
65
  Tuersteher::TLogger.logger.info "Tuersteher::AccessRulesStorage: #{@path_rules.size} path-rules and #{@model_rules.size} model-rules"
61
66
  end
62
67
 
63
- # Laden der AccesRules aus den Dateien
68
+ # Load AccesRules from file
64
69
  # config/access_rules.rb
65
70
  def read_rules
66
71
  @rules_config_file ||= File.join(Rails.root, 'config', DEFAULT_RULES_CONFIG_FILE)
@@ -74,7 +79,6 @@ module Tuersteher
74
79
  rules_file.close
75
80
  if content
76
81
  eval_rules content
77
- @was_read = true
78
82
  end
79
83
  rescue => ex
80
84
  Tuersteher::TLogger.logger.error "Tuersteher::AccessRulesStorage - Error in rules: #{ex.message}\n\t"+ex.backtrace.join("\n\t")
@@ -106,12 +110,16 @@ module Tuersteher
106
110
  end
107
111
  end
108
112
 
113
+ # create new rule as grant-rule
114
+ # and add this to the model_rules array
109
115
  def grant
110
116
  rule = ModelAccessRule.new(@current_model_class)
111
117
  @model_rules << rule
112
118
  rule.grant
113
119
  end
114
120
 
121
+ # create new rule as deny-rule
122
+ # and add this to the model_rules array
115
123
  def deny
116
124
  rule = ModelAccessRule.new(@current_model_class)
117
125
  @model_rules << rule
@@ -122,62 +130,67 @@ module Tuersteher
122
130
 
123
131
 
124
132
  class AccessRules
125
-
126
- # Pruefen Zugriff fuer eine Web-action
127
- # user User, für den der Zugriff geprüft werden soll (muss Methode has_role? haben)
128
- # path Pfad der Webresource (String)
129
- # method http-Methode (:get, :put, :delete, :post), default ist :get
130
- #
131
- def self.path_access?(user, path, method = :get)
132
- rule = AccessRulesStorage.instance.path_rules.detect do |r|
133
- r.fired?(path, method, user)
134
- end
135
- if Tuersteher::TLogger.logger.debug?
136
- if rule.nil?
137
- s = 'denied'
138
- elsif rule.deny?
139
- s = "denied with #{rule}"
140
- else
141
- s = "granted with #{rule}"
133
+ class << self
134
+ # Pruefen Zugriff fuer eine Web-action
135
+ # user User, für den der Zugriff geprüft werden soll (muss Methode has_role? haben)
136
+ # path Pfad der Webresource (String)
137
+ # method http-Methode (:get, :put, :delete, :post), default ist :get
138
+ #
139
+ def path_access?(user, path, method = :get)
140
+ rule = AccessRulesStorage.instance.path_rules.detect do |r|
141
+ r.fired?(path, method, user)
142
142
  end
143
- Tuersteher::TLogger.logger.debug("Tuersteher: path_access?(#{path}, #{method}) => #{s}")
143
+ if Tuersteher::TLogger.logger.debug?
144
+ if rule.nil?
145
+ s = 'denied'
146
+ elsif rule.deny?
147
+ s = "denied with #{rule}"
148
+ else
149
+ s = "granted with #{rule}"
150
+ end
151
+ usr_id = user.respond_to?(:id) ? user.id : user.object_id
152
+ Tuersteher::TLogger.logger.debug("Tuersteher: path_access?(user.id=#{usr_id}, path=#{path}, method=#{method}) => #{s}")
153
+ end
154
+ !(rule.nil? || rule.deny?)
144
155
  end
145
- !(rule.nil? || rule.deny?)
146
- end
147
156
 
148
157
 
149
- # Pruefen Zugriff auf ein Model-Object
150
- #
151
- # user User, für den der Zugriff geprüft werden soll (muss Methode has_role? haben)
152
- # model das Model-Object
153
- # permission das geforderte Zugriffsrecht (:create, :update, :destroy, :get)
154
- #
155
- # liefert true/false
156
- def self.model_access? user, model, permission
157
- raise "Wrong call! Use: model_access(model-instance-or-class, permission)" unless permission.is_a? Symbol
158
- return false unless model
158
+ # Pruefen Zugriff auf ein Model-Object
159
+ #
160
+ # user User, für den der Zugriff geprüft werden soll (muss Methode has_role? haben)
161
+ # model das Model-Object
162
+ # permission das geforderte Zugriffsrecht (:create, :update, :destroy, :get)
163
+ #
164
+ # liefert true/false
165
+ def model_access? user, model, permission
166
+ raise "Wrong call! Use: model_access(model-instance-or-class, permission)" unless permission.is_a? Symbol
167
+ return false unless model
159
168
 
160
- rule = AccessRulesStorage.instance.model_rules.detect do |rule|
161
- rule.fired? model, permission, user
162
- end
163
- access = rule && !rule.deny?
164
- if Tuersteher::TLogger.logger.debug?
165
- if model.instance_of?(Class)
166
- Tuersteher::TLogger.logger.debug("Tuersteher: model_access?(#{model}, #{permission}) => #{access || 'denied'} #{rule}")
167
- else
168
- Tuersteher::TLogger.logger.debug("Tuersteher: model_access?(#{model.class}(#{model.respond_to?(:id) ? model.id : model.object_id }), #{permission}) => #{access || 'denied'} #{rule}")
169
+ rule = AccessRulesStorage.instance.model_rules.detect do |rule|
170
+ rule.fired? model, permission, user
171
+ end
172
+ access = rule && !rule.deny?
173
+ if Tuersteher::TLogger.logger.debug?
174
+ usr_id = user.respond_to?(:id) ? user.id : user.object_id
175
+ if model.instance_of?(Class)
176
+ Tuersteher::TLogger.logger.debug(
177
+ "Tuersteher: model_access?(user.id=#{usr_id}, model=#{model}, permission=#{permission}) => #{access || 'denied'} #{rule}")
178
+ else
179
+ Tuersteher::TLogger.logger.debug(
180
+ "Tuersteher: model_access?(user.id=#{usr_id}, model=#{model.class}(#{model.respond_to?(:id) ? model.id : model.object_id }), permission=#{permission}) => #{access || 'denied'} #{rule}")
181
+ end
169
182
  end
183
+ access
170
184
  end
171
- access
172
- end
173
185
 
174
- # Bereinigen (entfernen) aller Objecte aus der angebenen Collection,
175
- # wo der angegebene User nicht das angegebene Recht hat
176
- #
177
- # liefert ein neues Array mit den Objecten, wo der spez. Zugriff arlaubt ist
178
- def self.purge_collection user, collection, permission
179
- collection.select{|model| model_access?(user, model, permission)}
180
- end
186
+ # Bereinigen (entfernen) aller Objecte aus der angebenen Collection,
187
+ # wo der angegebene User nicht das angegebene Recht hat
188
+ #
189
+ # liefert ein neues Array mit den Objecten, wo der spez. Zugriff arlaubt ist
190
+ def purge_collection user, collection, permission
191
+ collection.select{|model| model_access?(user, model, permission)}
192
+ end
193
+ end # of Class-Methods
181
194
  end # of AccessRules
182
195
 
183
196
 
@@ -224,7 +237,7 @@ module Tuersteher
224
237
  # wo der akt. User nicht das angegebene Recht hat
225
238
  #
226
239
  # liefert ein neues Array mit den Objecten, wo der spez. Zugriff arlaubt ist
227
- def self.purge_collection collection, permission
240
+ def purge_collection collection, permission
228
241
  AccessRules.purge_collection(current_user, collection, permission)
229
242
  end
230
243
 
@@ -248,10 +261,14 @@ module Tuersteher
248
261
  # Rails3 hat andere url-path-methode
249
262
  @@url_path_method ||= Rails.version[0..1]=='3.' ? :fullpath : :request_uri
250
263
 
264
+ # bind current_user on the current thread
265
+ Thread.current[:user] = current_user
266
+
251
267
  req_method = request.method.downcase.to_sym
252
268
  url_path = request.send(@@url_path_method)
253
269
  unless path_access?(url_path, req_method)
254
- msg = "Tuersteher#check_access: access denied for #{request.request_uri} :#{req_method}"
270
+ usr_id = current_user.respond_to?(:id) ? current_user.id : current_user.object_id
271
+ msg = "Tuersteher#check_access: access denied for #{request.request_uri} :#{req_method} user.id=#{usr_id}"
255
272
  Tuersteher::TLogger.logger.warn msg
256
273
  logger.warn msg # log message also for Rails-Default logger
257
274
  access_denied # Methode aus dem authenticated_system, welche ein redirect zum login auslöst
@@ -261,6 +278,55 @@ module Tuersteher
261
278
  end
262
279
 
263
280
 
281
+
282
+ # Module for include in Model-Object-Classes
283
+ #
284
+ # The module get the current-user from Thread.current[:user]
285
+ #
286
+ # Sample for ActiveRecord-Class
287
+ # class Sample < ActiveRecord::Base
288
+ # include Tuersteher::ModelExtensions
289
+ #
290
+ # def transfer_to account
291
+ # check_model_access :transfer # raise a exception if not allowed
292
+ # ....
293
+ # end
294
+ #
295
+ #
296
+ module ModelExtensions
297
+
298
+ # Check permission for the Model-Object
299
+ #
300
+ # permission the requested permission (sample :create, :update, :destroy, :get)
301
+ #
302
+ # raise a SecurityError-Exception if access denied
303
+ def check_access permission
304
+ user = Thread.current[:user]
305
+ unless AccessRules.model_access? user, self, permission
306
+ raise SecurityError, "Access denied! Current user have no permission '#{permission}' on Model-Object #{self}."
307
+ end
308
+ end
309
+
310
+ def self.included(base)
311
+ base.extend ClassMethods
312
+ end
313
+
314
+ module ClassMethods
315
+
316
+ # Bereinigen (entfernen) aller Objecte aus der angebenen Collection,
317
+ # wo der akt. User nicht das angegebene Recht hat
318
+ #
319
+ # liefert ein neues Array mit den Objecten, wo der spez. Zugriff arlaubt ist
320
+ def purge_collection collection, permission
321
+ user = Thread.current[:user]
322
+ AccessRules.purge_collection(user, collection, permission)
323
+ end
324
+ end # of ClassMethods
325
+
326
+ end # of module ModelExtensions
327
+
328
+
329
+
264
330
  # Astracte base class for Access-Rules
265
331
  class BaseAccessRule
266
332
 
@@ -275,26 +341,33 @@ module Tuersteher
275
341
  self
276
342
  end
277
343
 
278
-
279
- def extension method_name, methode_parameter=nil
344
+ # add extension-definition
345
+ # parmaters:
346
+ # method_name: Symbol with the name of the method to call for addional check
347
+ # expected_value: optional expected value for the result of the with metho_name specified method, defalt is true
348
+ def extension method_name, expected_value=nil
280
349
  @check_extensions ||= {}
281
- @check_extensions[method_name] = methode_parameter
350
+ @check_extensions[method_name] = expected_value
282
351
  self
283
352
  end
284
353
 
354
+ # mark this rule as grant-rule
285
355
  def grant
286
356
  self
287
357
  end
288
358
 
359
+ # mark this rule as deny-rule
289
360
  def deny
290
361
  @deny = true
291
362
  self
292
363
  end
293
364
 
365
+ # is this rule a deny-rule
294
366
  def deny?
295
367
  @deny
296
368
  end
297
369
 
370
+ # negate role-membership
298
371
  def not
299
372
  @not = true
300
373
  self
@@ -302,6 +375,7 @@ module Tuersteher
302
375
 
303
376
  protected
304
377
 
378
+ # check, if this rule granted for specified user
305
379
  def grant_role? user
306
380
  return true if @roles.empty?
307
381
  return false if user.nil?
@@ -384,6 +458,7 @@ module Tuersteher
384
458
 
385
459
  private
386
460
 
461
+ # check, if this rule grant the defined extension (if exist)
387
462
  def grant_extension? user
388
463
  return true if @check_extensions.nil?
389
464
  return false if user.nil? # check_extensions need a user
@@ -426,7 +501,7 @@ module Tuersteher
426
501
  @clazz = clazz.instance_of?(Symbol) ? clazz : clazz.to_s
427
502
  end
428
503
 
429
-
504
+ # set the permission-name
430
505
  def permission permission_name
431
506
  @permission = permission_name
432
507
  self
@@ -445,7 +520,6 @@ module Tuersteher
445
520
  #
446
521
  def fired? model, perm, user
447
522
  user = nil if user==:false # manche Authenticate-System setzen den user auf :false
448
- debugger
449
523
  m_class = model.instance_of?(Class) ? model : model.class
450
524
  if @clazz!=m_class.to_s && @clazz!=:all
451
525
  #Tuersteher::TLogger.logger.debug("#{to_s}.has_access? => false why #{@clazz}!=#{model.class.to_s} && #{@clazz}!=:all")
@@ -471,6 +545,7 @@ module Tuersteher
471
545
 
472
546
  private
473
547
 
548
+ # check, if this rule grant the defined extension (if exist)
474
549
  def grant_extension? user, model
475
550
  return true if @check_extensions.nil?
476
551
  return false if model.nil? # check_extensions need a model
@@ -491,5 +566,4 @@ module Tuersteher
491
566
 
492
567
  end
493
568
 
494
-
495
569
  end
@@ -35,7 +35,7 @@ module Tuersteher
35
35
  @user.stub(:has_role?).and_return(false)
36
36
  end
37
37
 
38
- it "should not be fired for String-Object and access-type :read" do
38
+ specify do
39
39
  @rule.fired?("test", :read, @user).should_not be_true
40
40
  end
41
41
  end
@@ -0,0 +1,58 @@
1
+ require "spec_helper"
2
+
3
+ module Tuersteher
4
+
5
+ describe ModelExtensions do
6
+
7
+ class SampleModel
8
+ include ModelExtensions
9
+
10
+ def deactived
11
+ check_access :deactived
12
+ end
13
+ end
14
+
15
+
16
+ before do
17
+ rules = [ModelAccessRule.new(SampleModel).grant.permission(:deactived).role(:admin)]
18
+ AccessRulesStorage.instance.stub(:model_rules).and_return(rules)
19
+ @user = stub('user')
20
+ Thread.current[:user] = @user
21
+ end
22
+
23
+
24
+ context "check_access" do
25
+
26
+ it "should not raise a Error for user with role :admin" do
27
+ @user.stub(:has_role?){|role| role==:admin}
28
+ model = SampleModel.new
29
+ model.deactived
30
+ end
31
+
32
+ it "should raise a SecurityError for user with not role :admin" do
33
+ @user.stub(:has_role?){|role| role==:user}
34
+ model = SampleModel.new
35
+ expect{ model.deactived }.to raise_error(SecurityError)
36
+ end
37
+
38
+ end # of context "grant with roles"
39
+
40
+
41
+ context "purge_collection" do
42
+
43
+ it "should purge nothing for user with role :admin" do
44
+ @user.stub(:has_role?){|role| role==:admin}
45
+ list = [SampleModel.new]
46
+ SampleModel.purge_collection(list, :deactived).should == list
47
+ end
48
+
49
+ it "should purge all for user with not role :admin" do
50
+ @user.stub(:has_role?){|role| role==:user}
51
+ list = [SampleModel.new]
52
+ SampleModel.purge_collection(list, :deactived).should == []
53
+ end
54
+
55
+ end # of context "purge_collection"
56
+ end
57
+ end
58
+
data/spec/spec_helper.rb CHANGED
@@ -4,3 +4,4 @@ require File.expand_path(File.dirname(__FILE__) + "/../lib/tuersteher")
4
4
 
5
5
  # Logger auf stdout stellen
6
6
  Tuersteher::TLogger.logger = Logger.new(STDOUT)
7
+ Tuersteher::TLogger.logger.level = Logger::ERROR
data/tuersteher.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{tuersteher}
8
- s.version = "0.3.0"
8
+ s.version = "0.3.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bernd Ledig"]
12
- s.date = %q{2010-08-30}
12
+ s.date = %q{2010-09-01}
13
13
  s.description = %q{Security-Layer for Rails-Application acts like a firewall.}
14
14
  s.email = %q{bernd@ledig.info}
15
15
  s.extra_rdoc_files = [
@@ -29,6 +29,7 @@ Gem::Specification.new do |s|
29
29
  "spec/acces_rules_storage_spec.rb",
30
30
  "spec/access_rules_spec.rb",
31
31
  "spec/model_access_rule_spec.rb",
32
+ "spec/model_extensions_spec.rb",
32
33
  "spec/path_access_rule_spec.rb",
33
34
  "spec/spec.opts",
34
35
  "spec/spec_helper.rb",
@@ -40,11 +41,12 @@ Gem::Specification.new do |s|
40
41
  s.rubygems_version = %q{1.3.7}
41
42
  s.summary = %q{Security-Layer for Rails-Application}
42
43
  s.test_files = [
43
- "spec/acces_rules_storage_spec.rb",
44
- "spec/path_access_rule_spec.rb",
44
+ "spec/path_access_rule_spec.rb",
45
45
  "spec/model_access_rule_spec.rb",
46
- "spec/access_rules_spec.rb",
47
- "spec/spec_helper.rb"
46
+ "spec/model_extensions_spec.rb",
47
+ "spec/acces_rules_storage_spec.rb",
48
+ "spec/spec_helper.rb",
49
+ "spec/access_rules_spec.rb"
48
50
  ]
49
51
 
50
52
  if s.respond_to? :specification_version then
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tuersteher
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 21
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 0
10
- version: 0.3.0
9
+ - 3
10
+ version: 0.3.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Bernd Ledig
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-30 00:00:00 +02:00
18
+ date: 2010-09-01 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -41,6 +41,7 @@ files:
41
41
  - spec/acces_rules_storage_spec.rb
42
42
  - spec/access_rules_spec.rb
43
43
  - spec/model_access_rule_spec.rb
44
+ - spec/model_extensions_spec.rb
44
45
  - spec/path_access_rule_spec.rb
45
46
  - spec/spec.opts
46
47
  - spec/spec_helper.rb
@@ -80,8 +81,9 @@ signing_key:
80
81
  specification_version: 3
81
82
  summary: Security-Layer for Rails-Application
82
83
  test_files:
83
- - spec/acces_rules_storage_spec.rb
84
84
  - spec/path_access_rule_spec.rb
85
85
  - spec/model_access_rule_spec.rb
86
- - spec/access_rules_spec.rb
86
+ - spec/model_extensions_spec.rb
87
+ - spec/acces_rules_storage_spec.rb
87
88
  - spec/spec_helper.rb
89
+ - spec/access_rules_spec.rb