tuersteher 0.1.4 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.1
data/lib/tuersteher.rb CHANGED
@@ -53,22 +53,29 @@ module Tuersteher
53
53
  end
54
54
 
55
55
 
56
+ def eval_rules rules_definitions
57
+ @path_rules = []
58
+ @model_rules = []
59
+ eval rules_definitions
60
+ Tuersteher::TLogger.logger.info "Tuersteher::AccessRulesStorage: #{@path_rules.size} path-rules and #{@model_rules.size} model-rules"
61
+ end
62
+
56
63
  # Laden der AccesRules aus den Dateien
57
64
  # config/access_rules.rb
58
65
  def read_rules
59
66
  @rules_config_file ||= File.join(Rails.root, 'config', DEFAULT_RULES_CONFIG_FILE)
60
67
  rules_file = File.new @rules_config_file
61
68
  @was_read = false
69
+ content = nil
62
70
  if @last_mtime.nil? || rules_file.mtime > @last_mtime
63
71
  @last_mtime = rules_file.mtime
64
- @path_rules = []
65
- @model_rules = []
66
72
  content = rules_file.read
67
- eval content
68
- Tuersteher::TLogger.logger.info "Tuersteher::AccessRulesStorage: #{@path_rules.size} path-rules and #{@model_rules.size} model-rules"
69
73
  end
70
74
  rules_file.close
71
- @was_read = true
75
+ if content
76
+ eval_rules content
77
+ @was_read = true
78
+ end
72
79
  rescue => ex
73
80
  Tuersteher::TLogger.logger.error "Tuersteher::AccessRulesStorage - Error in rules: #{ex.message}\n\t"+ex.backtrace.join("\n\t")
74
81
  end
@@ -77,26 +84,13 @@ module Tuersteher
77
84
  #
78
85
  # path: :all fuer beliebig, sonst String mit der http-path beginnen muss,
79
86
  # wird als RegEX-Ausdruck ausgewertet
80
- # method: http-Methode, es sind hier erlaubt :get, :put, :delete, :post, :all
81
- # accepted_roles: Aufzaehlung der erfoderlichen Rolen (oder-Verknuepfung), es sind nur Symbole zulaessig
82
- # hier ist auch ein Array von Symbolen möglich
83
- def grant_path url_path, http_methode, *accepted_roles
84
- @path_rules << PathAccessRule.new(url_path, http_methode, *accepted_roles)
85
- end
86
-
87
- # definiert HTTP-Pfad-basierende Ablehnungsregel
88
- #
89
- # path: :all fuer beliebig, sonst String mit der http-path beginnen muss,
90
- # wird als RegEX-Ausdruck ausgewertet
91
- # method: http-Methode, es sind hier erlaubt :get, :put, :delete, :post, :all
92
- # accepted_roles: Aufzaehlung der erfoderlichen Rolen (oder-Verknuepfung), es sind nur Symbole zulaessig
93
- # hier ist auch ein Array von Symbolen möglich
94
- def deny_path url_path, http_methode, *accepted_roles
95
- rule = PathAccessRule.new(url_path, http_methode, *accepted_roles)
96
- rule.deny = true
87
+ def path url_path
88
+ rule = PathAccessRule.new(url_path)
97
89
  @path_rules << rule
90
+ rule
98
91
  end
99
92
 
93
+
100
94
  # definiert Model-basierende Zugriffsregel
101
95
  #
102
96
  # model_class: Model-Klassenname oder :all fuer alle
@@ -110,30 +104,32 @@ module Tuersteher
110
104
  # grant_model(User, :update, :all){|model,user| model.id==user.id}
111
105
  # </code>
112
106
  #
113
- def grant_model model_class, access_type, *roles, &block
114
- @model_rules << ModelAccessRule.new(model_class, access_type, *roles, &block)
107
+ def model model_class
108
+ if block_given?
109
+ @current_model_class = model_class
110
+ yield
111
+ @current_model_class = nil
112
+ else
113
+ rule = ModelAccessRule.new(model_class)
114
+ @model_rules << rule
115
+ rule
116
+ end
115
117
  end
116
118
 
117
- # definiert Model-basierende Zugriffsregel
118
- #
119
- # model_class: Model-Klassenname oder :all fuer alle
120
- # access_type: Zugriffsart (:create, :update, :destroy, :all o.A. selbst definierte Typen)
121
- # roles Aufzählung der erforderliche Rolen (:all für ist egal),
122
- # hier ist auch ein Array von Symbolen möglich
123
- # block optionaler Block, wird mit model und user aufgerufen und muss true oder false liefern
124
- # hier ein Beispiel mit Block:
125
- # <code>
126
- # # Regel, in der sich jeder User selbst aendern darf
127
- # grant_model(User, :update, :all){|model,user| model.id==user.id}
128
- # </code>
129
- #
130
- def deny_model model_class, access_type, *roles, &block
131
- rule = ModelAccessRule.new(model_class, access_type, *roles, &block)
132
- rule.deny = true
119
+ def grant
120
+ rule = ModelAccessRule.new(@current_model_class)
133
121
  @model_rules << rule
122
+ rule.grant
134
123
  end
135
124
 
136
- end
125
+ def deny
126
+ rule = ModelAccessRule.new(@current_model_class)
127
+ @model_rules << rule
128
+ rule.deny
129
+ end
130
+
131
+ end # of AccessRulesStorage
132
+
137
133
 
138
134
  class AccessRules
139
135
 
@@ -149,14 +145,14 @@ module Tuersteher
149
145
  if Tuersteher::TLogger.logger.debug?
150
146
  if rule.nil?
151
147
  s = 'denied'
152
- elsif rule.deny
148
+ elsif rule.deny?
153
149
  s = "denied with #{rule}"
154
150
  else
155
151
  s = "granted with #{rule}"
156
152
  end
157
153
  Tuersteher::TLogger.logger.debug("Tuersteher: path_access?(#{path}, #{method}) => #{s}")
158
154
  end
159
- rule!=nil && !rule.deny
155
+ rule!=nil && !rule.deny?
160
156
  end
161
157
 
162
158
 
@@ -174,7 +170,7 @@ module Tuersteher
174
170
  rule = AccessRulesStorage.instance.model_rules.detect do |rule|
175
171
  rule.fired? model, permission, user
176
172
  end
177
- access = rule && !rule.deny
173
+ access = rule && !rule.deny?
178
174
  if Tuersteher::TLogger.logger.debug?
179
175
  if model.instance_of?(Class)
180
176
  Tuersteher::TLogger.logger.debug("Tuersteher: model_access?(#{model}, #{permission}) => #{access || 'denied'} #{rule}")
@@ -192,7 +188,7 @@ module Tuersteher
192
188
  def self.purge_collection user, collection, permission
193
189
  collection.select{|model| model_access?(user, model, permission)}
194
190
  end
195
- end
191
+ end # of AccessRules
196
192
 
197
193
 
198
194
 
@@ -204,7 +200,7 @@ module Tuersteher
204
200
  #
205
201
  # Der Loginuser muss fuer die hier benoetigte Funktionalitaet
206
202
  # die Methode:
207
- # has_role?(*roles) # roles is Array of Symbols
203
+ # has_role?(role) # role the Name of the Role as Symbol
208
204
  # besitzen.
209
205
  #
210
206
  # Beispiel der Einbindung in den ApplicationController
@@ -274,10 +270,55 @@ module Tuersteher
274
270
 
275
271
  end
276
272
 
273
+ # Astracte base class for Access-Rules
274
+ class BaseAccessRule
275
+
276
+ def initialize
277
+ @roles = []
278
+ end
279
+
280
+ # add role
281
+ def role(role_name)
282
+ raise "wrong role '#{role_name}'! Must be a symbol " unless role_name.is_a?(Symbol)
283
+ @roles << role_name
284
+ self
285
+ end
277
286
 
278
- class PathAccessRule
279
- attr_reader :path, :method, :roles
280
- attr_accessor :deny
287
+
288
+ def extension method_name, methode_parameter=nil
289
+ @check_extensions ||= {}
290
+ @check_extensions[method_name] = methode_parameter
291
+ self
292
+ end
293
+
294
+ def grant
295
+ self
296
+ end
297
+
298
+ def deny
299
+ @deny = true
300
+ self
301
+ end
302
+
303
+ def deny?
304
+ @deny
305
+ end
306
+
307
+ protected
308
+
309
+ def grant_role? user
310
+ return true if @roles.empty?
311
+ return false if user.nil?
312
+ @roles.each do |role|
313
+ return true if user.has_role?(role)
314
+ end
315
+ false
316
+ end
317
+
318
+ end # of BaseAccessRule
319
+
320
+
321
+ class PathAccessRule < BaseAccessRule
281
322
 
282
323
  METHOD_NAMES = [:get, :edit, :put, :delete, :post, :all].freeze
283
324
 
@@ -285,17 +326,10 @@ module Tuersteher
285
326
  # Zugriffsregel
286
327
  #
287
328
  # path :all fuer beliebig, sonst String mit der http-path beginnen muss
288
- # method http-Methode, es sind hier erlaubt :get, :put, :delete, :post, :all
289
- # needed_roles Aufzaehlung der erfoderlichen Rolen (oder-Verknuepfung), es sind nur Symbole zulaessig
290
329
  #
291
- def initialize(path, method, *needed_roles)
330
+ def initialize(path)
292
331
  raise "wrong path '#{path}'! Must be a String or :all ." unless path==:all or path.is_a?(String)
293
- raise "wrong method '#{method}'! Must be #{METHOD_NAMES.join(', ')} !" unless METHOD_NAMES.include?(method)
294
- raise "needed_roles expected!" if needed_roles.empty?
295
- @roles = needed_roles.flatten
296
- for r in @roles
297
- raise "wrong role '#{r}'! Must be a symbol " unless r.is_a?(Symbol)
298
- end
332
+ super()
299
333
  @path = path
300
334
  if path != :all
301
335
  # path in regex ^#{path} wandeln ausser bei "/",
@@ -307,10 +341,19 @@ module Tuersteher
307
341
  @path = /^#{path}/
308
342
  end
309
343
  end
310
- @method = method
344
+ @http_method = :all
345
+ end
346
+
347
+ # set http-methode
348
+ # http_method http-Method, allowed is :get, :put, :delete, :post, :all
349
+ def method(http_method)
350
+ raise "wrong method '#{http_method}'! Must be #{METHOD_NAMES.join(', ')} !" unless METHOD_NAMES.include?(http_method)
351
+ @http_method = http_method
352
+ self
311
353
  end
312
354
 
313
355
 
356
+
314
357
  # pruefen, ob Zugriff fuer angegebenen
315
358
  # path / method fuer den current_user erlaubt ist
316
359
  #
@@ -320,35 +363,57 @@ module Tuersteher
320
363
  #
321
364
  def fired?(path, method, user)
322
365
  user = nil if user==:false # manche Authenticate-System setzen den user auf :false
366
+
323
367
  if @path!=:all && !(@path =~ path)
324
368
  return false
325
369
  end
326
370
 
327
- if @method!=:all && @method != method
371
+ if @http_method!=:all && @http_method != method
328
372
  return false
329
373
  end
330
374
 
331
- # ist jetzt role :all, dann prinzipiell Zugriff erlaubt
332
- return true if @roles.first == :all
333
-
334
- if user && user.has_role?(*@roles)
335
- return true
375
+ if !@roles.empty? && (user.nil? || !user.has_role?(*@roles))
376
+ #Tuersteher::TLogger.logger.debug("#{to_s}.has_access? => false why #{@roles.first}!=:all && #{!user.has_role?(*@roles)}")
377
+ return false
336
378
  end
337
- false
379
+
380
+ return false unless grant_extension?(user)
381
+
382
+ true
338
383
  end
339
384
 
340
385
 
341
386
  def to_s
342
- "PathAccesRule[#{@path}, #{@method}, #{@roles.join(' ')}#{@deny ? ' deny' : ''}]"
387
+ s = "PathAccesRule[#{@deny ? 'DENY ' : ''}#{@path}, #{@http_method}, #{@roles.join(' ')}"
388
+ s << " #{@check_extensions.inspect}" if @check_extensions
389
+ s << ']'
390
+ s
391
+ end
392
+
393
+ private
394
+
395
+ def grant_extension? user
396
+ return true if @check_extensions.nil?
397
+ return false if user.nil? # check_extensions need a user
398
+ @check_extensions.each do |key, value|
399
+ unless user.respond_to?(key)
400
+ Tuersteher::TLogger.logger.warn("#{to_s}.fired? => false why user have not check-extension method '#{key}'!")
401
+ return false
402
+ end
403
+ if value
404
+ return false unless user.send(key,value)
405
+ else
406
+ return false unless user.send(key)
407
+ end
408
+ end
409
+ true
343
410
  end
344
411
 
345
412
  end
346
413
 
347
414
 
348
415
 
349
- class ModelAccessRule
350
- attr_reader :clazz, :access_type, :roles, :block
351
- attr_accessor :deny
416
+ class ModelAccessRule < BaseAccessRule
352
417
 
353
418
  # erzeugt neue Object-Zugriffsregel
354
419
  #
@@ -363,16 +428,16 @@ module Tuersteher
363
428
  # ModelAccessRule.new(User, :update, :all){|model,user| model.id==user.id}
364
429
  # </code>
365
430
  #
366
- def initialize(clazz, access_type, *roles, &block)
431
+ def initialize(clazz)
367
432
  raise "wrong clazz '#{clazz}'! Must be a Class or :all ." unless clazz==:all or clazz.is_a?(Class)
368
- raise "wrong access_type '#{ access_type}'! Must be a Symbol ." unless access_type.is_a?(Symbol)
369
- @roles = roles.flatten
370
- for r in @roles
371
- raise "wrong role '#{r}'! Must be a symbol " unless r.is_a?(Symbol)
372
- end
433
+ super()
373
434
  @clazz = clazz.instance_of?(Symbol) ? clazz : clazz.to_s
374
- @access_type = access_type
375
- @block = block
435
+ end
436
+
437
+
438
+ def permission permission_name
439
+ @permission = permission_name
440
+ self
376
441
  end
377
442
 
378
443
  # liefert true, wenn zugriff fuer das angegebene model mit
@@ -388,36 +453,50 @@ module Tuersteher
388
453
  #
389
454
  def fired? model, perm, user
390
455
  user = nil if user==:false # manche Authenticate-System setzen den user auf :false
456
+ debugger
391
457
  m_class = model.instance_of?(Class) ? model : model.class
392
458
  if @clazz!=m_class.to_s && @clazz!=:all
393
459
  #Tuersteher::TLogger.logger.debug("#{to_s}.has_access? => false why #{@clazz}!=#{model.class.to_s} && #{@clazz}!=:all")
394
460
  return false
395
461
  end
396
462
 
397
- if @access_type!=:all && @access_type!=perm
463
+ if @permission!=:all && @permission!=perm
398
464
  #Tuersteher::TLogger.logger.debug("#{to_s}.has_access? => false why #{@access_type}!=:all && #{@access_type}!=#{perm}")
399
465
  return false
400
466
  end
401
467
 
402
- if @roles.first!=:all && (user.nil? || !user.has_role?(*@roles))
403
- #Tuersteher::TLogger.logger.debug("#{to_s}.has_access? => false why #{@roles.first}!=:all && #{!user.has_role?(*@roles)}")
404
- return false
405
- end
468
+ return false unless grant_role?(user)
469
+ return false unless grant_extension?(user, model)
470
+ true
471
+ end
472
+
473
+ def to_s
474
+ s = "ModelAccessRule[#{@deny ? 'DENY ' : ''}#{@clazz}, #{@permission}, #{@roles.join(' ')}"
475
+ s << " #{@check_extensions.inspect}" if @check_extensions
476
+ s << ']'
477
+ s
478
+ end
479
+
480
+ private
406
481
 
407
- if @block
408
- return false if model.instance_of?(Class) # kein Block-Call wenn Classe als model übergeben wurde
409
- unless @block.call(model, user)
410
- #Tuersteher::TLogger.logger.debug("#{to_s}.has_access? => false why block return false")
482
+ def grant_extension? user, model
483
+ return true if @check_extensions.nil?
484
+ return false if model.nil? # check_extensions need a model
485
+ return false if model.instance_of?(Class) # no Extension-Call if model is a Class-Instance
486
+ @check_extensions.each do |key, value|
487
+ unless model.respond_to?(key)
488
+ Tuersteher::TLogger.logger.warn("#{to_s}.fired? => false why model-onject have not check-extension method '#{key}'!")
411
489
  return false
412
490
  end
491
+ if value
492
+ return false unless model.send(key,user,value)
493
+ else
494
+ return false unless model.send(key,user)
495
+ end
413
496
  end
414
497
  true
415
498
  end
416
499
 
417
- def to_s
418
- "ModelAccessRule[#{@clazz}, #{@access_type}, #{@roles.join(' ')}#{@deny ? ' deny' : ''}]"
419
- end
420
-
421
500
  end
422
501
 
423
502
 
@@ -12,9 +12,11 @@
12
12
  # Methode : :all, :get, :put, :post, :delete oder :edit
13
13
  # roles :Liste der berechtigten Rollen (es können mehrere Rollen durch Komma getrennt angegeben werden)
14
14
  #
15
- grant_path '/', :get, :all
16
- grant_path :all, :all, :ADMIN
17
- deny_path '/user/lock', :user
15
+
16
+ path('/').grant.method(:get)
17
+ path(:all).grant.role(:ADMIN)
18
+ path('/user/lock').deny.role(:USER).role(:APPROVER)
19
+ path('/special').grant.extension(:special?, :area1)
18
20
 
19
21
  #
20
22
  # Model-Object-Zugriffsregeln
@@ -24,7 +26,14 @@ deny_path '/user/lock', :user
24
26
  # Roles : Aufzählung der Rollen
25
27
  # Block : optionaler Block, diesem wird die Model-Instance und der User als Parameter bereitgestellt
26
28
 
27
- grant_model String, :view, :all
28
- grant_model String, :view, :ADMIN, :EDITOR
29
- grant_model String, :update, :EDITOR do |model, user| model == user.name end
29
+ #grant_model String, :view, :all
30
+ #grant_model String, :view, :ADMIN, :EDITOR
31
+ #grant_model String, :update, :EDITOR do |model, user| model == user.name end
32
+
33
+ model(Dashboard).grant.permission(:view)
30
34
 
35
+ model(Todo) do
36
+ grant.permission(:view)
37
+ grant.permission(:full_view).role(:ADMIN)
38
+ grant.permission(:update).role(:EDITOR).extension(:owned_by?) # calls Todo.owned_by?(current_user)
39
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ module Tuersteher
4
+
5
+ class Dashboard; end
6
+ class Todo; end
7
+
8
+ describe AccessRulesStorage do
9
+
10
+ context "eval_rules" do
11
+ before(:all) do
12
+ rule_defs = <<-EOR
13
+ path('/').grant.method(:get)
14
+ path(:all).grant.role(:ADMIN)
15
+ path('/special').grant.extension(:special?, :area1)
16
+
17
+ model(Dashboard).grant.permission(:view)
18
+ model(Todo) do
19
+ grant.permission(:view)
20
+ grant.permission(:full_view).role(:ADMIN)
21
+ grant.permission(:update).role(:EDITOR).extension(:owned_by?) # calls Todo.owned_by?(current_user)
22
+ end
23
+ EOR
24
+ AccessRulesStorage.instance.eval_rules rule_defs
25
+ @path_rules = AccessRulesStorage.instance.path_rules
26
+ @model_rules = AccessRulesStorage.instance.model_rules
27
+ end
28
+
29
+ it "should have 3 path-rules" do
30
+ @path_rules.should have(3).items
31
+ end
32
+
33
+ it "should have 4 model-rules" do
34
+ @model_rules.should have(4).items
35
+ end
36
+
37
+ end # of context "eval_rules"
38
+
39
+ end # of describe AccessRulesStorage
40
+ end
@@ -0,0 +1,170 @@
1
+ require "spec_helper"
2
+
3
+
4
+
5
+ module Tuersteher
6
+
7
+ describe AccessRules do
8
+
9
+ context 'path_access?' do
10
+ before do
11
+ rules = [
12
+ PathAccessRule.new('/'),
13
+ PathAccessRule.new('/admin').role(:admin),
14
+ PathAccessRule.new('/images').method(:get),
15
+ PathAccessRule.new('/status').method(:get).role(:system)
16
+ ]
17
+ AccessRulesStorage.instance.stub(:path_rules).and_return(rules)
18
+ @user = stub('user')
19
+ end
20
+
21
+
22
+ context "User with role :user" do
23
+ before do
24
+ @user.stub(:has_role?){|role| role==:user}
25
+ end
26
+
27
+ it "should be true for this paths" do
28
+ AccessRules.path_access?(@user, '/', :get).should be_true
29
+ AccessRules.path_access?(@user, '/', :post).should be_true
30
+ AccessRules.path_access?(@user, '/images', :get).should be_true
31
+ end
32
+
33
+ it "should not be true for this paths" do
34
+ AccessRules.path_access?(@user, '/admin', :get).should_not be_true
35
+ AccessRules.path_access?(@user, '/images', :post).should_not be_true
36
+ AccessRules.path_access?(@user, '/status', :get).should_not be_true
37
+ end
38
+ end
39
+
40
+
41
+ context "User with role :admin" do
42
+ before do
43
+ @user.stub(:has_role?){|role| role==:admin}
44
+ end
45
+
46
+ it "should be true for this paths" do
47
+ AccessRules.path_access?(@user, '/', :get).should be_true
48
+ AccessRules.path_access?(@user, '/admin', :post).should be_true
49
+ AccessRules.path_access?(@user, '/images', :get).should be_true
50
+ end
51
+
52
+ it "should not be true for this paths" do
53
+ AccessRules.path_access?(@user, '/xyz', :get).should_not be_true
54
+ AccessRules.path_access?(@user, '/images', :post).should_not be_true
55
+ AccessRules.path_access?(@user, '/status', :get).should_not be_true
56
+ end
57
+ end
58
+
59
+
60
+ context "User with role :system" do
61
+ before do
62
+ @user.stub(:has_role?){|role| role==:system}
63
+ end
64
+
65
+ it "should be true for this paths" do
66
+ AccessRules.path_access?(@user, '/', :get).should be_true
67
+ AccessRules.path_access?(@user, '/status', :get).should be_true
68
+ end
69
+
70
+ it "should not be true for this paths" do
71
+ AccessRules.path_access?(@user, '/xyz', :get).should_not be_true
72
+ AccessRules.path_access?(@user, '/admin', :post).should_not be_true
73
+ end
74
+ end
75
+ end
76
+
77
+
78
+ context 'model_access?' do
79
+
80
+ class SampleModel1; end
81
+ class SampleModel2; end
82
+
83
+ before do
84
+ rules = [
85
+ ModelAccessRule.new(SampleModel1).grant.permission(:all),
86
+ ModelAccessRule.new(SampleModel2).grant.permission(:read),
87
+ ModelAccessRule.new(SampleModel2).grant.permission(:update).role(:user).extension(:owner?),
88
+ ModelAccessRule.new(SampleModel2).deny.permission(:create),
89
+ ModelAccessRule.new(SampleModel2).grant.permission(:all).role(:admin),
90
+ ]
91
+ AccessRulesStorage.instance.stub(:model_rules).and_return(rules)
92
+ @user = stub('user')
93
+ @model1 = SampleModel1.new
94
+ @model2 = SampleModel2.new
95
+ @model2.stub(:owner?).and_return(false)
96
+ end
97
+
98
+
99
+ context "User with role :user" do
100
+ before do
101
+ @user.stub(:has_role?){|role| role==:user}
102
+ end
103
+
104
+ it "should be true for this" do
105
+ AccessRules.model_access?(@user, @model1, :xyz).should be_true
106
+ @model2.stub(:owner?).and_return true
107
+ AccessRules.model_access?(@user, @model2, :read).should be_true
108
+ AccessRules.model_access?(@user, @model2, :update).should be_true
109
+ end
110
+
111
+ it "should not be true for this" do
112
+ AccessRules.model_access?(@user, @model2, :update).should_not be_true
113
+ AccessRules.model_access?(@user, @model2, :delete).should_not be_true
114
+ end
115
+ end
116
+
117
+
118
+ context "User with role :admin" do
119
+ before do
120
+ @user.stub(:has_role?){|role| role==:admin}
121
+ end
122
+
123
+ it "should be true for this" do
124
+ AccessRules.model_access?(@user, @model1, :xyz).should be_true
125
+ AccessRules.model_access?(@user, @model2, :read).should be_true
126
+ AccessRules.model_access?(@user, @model2, :update).should be_true
127
+ AccessRules.model_access?(@user, @model2, :delete).should be_true
128
+ end
129
+
130
+ it "should not be true for this" do
131
+ AccessRules.model_access?(@user, @model2, :create).should_not be_true
132
+ end
133
+ end
134
+ end
135
+
136
+
137
+
138
+ context 'purge_collection' do
139
+
140
+ class SampleModel
141
+ def owner? user; false; end
142
+ end
143
+
144
+ before do
145
+ rules = [
146
+ ModelAccessRule.new(SampleModel).permission(:update).role(:admin),
147
+ ModelAccessRule.new(SampleModel).permission(:update).role(:user).extension(:owner?),
148
+ ]
149
+ AccessRulesStorage.instance.stub(:model_rules).and_return(rules)
150
+ @user = stub('user')
151
+ @model1 = SampleModel.new
152
+ @model2 = SampleModel.new
153
+ @model3 = SampleModel.new
154
+ @model3.stub(:owner?).and_return(true)
155
+ @collection = [@model1, @model2, @model3]
156
+ end
157
+
158
+ it "Should return [@model3] for user with role=:user" do
159
+ @user.stub(:has_role?){|role| role==:user}
160
+ AccessRules.purge_collection(@user, @collection, :update).should == [@model3]
161
+ end
162
+
163
+ it "Should return all for user with role=:admin" do
164
+ @user.stub(:has_role?){|role| role==:admin}
165
+ AccessRules.purge_collection(@user, @collection, :update).should == @collection
166
+ end
167
+ end
168
+
169
+ end
170
+ end
@@ -0,0 +1,42 @@
1
+ require "spec_helper"
2
+
3
+ module Tuersteher
4
+
5
+ describe ModelAccessRule do
6
+
7
+ before(:all) do
8
+ @rule = ModelAccessRule.new(String).grant.permission(:read).role(:sysadmin).role(:admin)
9
+ end
10
+
11
+ context "for User with role :admin" do
12
+ before do
13
+ @user = stub('user')
14
+ @user.stub(:has_role?){|role| role==:admin}
15
+ end
16
+
17
+ it "should be fired for String-Object and access-type :read" do
18
+ @rule.fired?("test", :read, @user).should be_true
19
+ end
20
+
21
+ it "should not be fired for Non-String-Object" do
22
+ @rule.fired?(12345, :read, @user).should_not be_true
23
+ end
24
+
25
+ it "should not be fired for String-Object and other access-type as :read" do
26
+ @rule.fired?("test", :delete, @user).should_not be_true
27
+ end
28
+ end
29
+
30
+ context "for User without role :admin" do
31
+ before do
32
+ @user = stub('user')
33
+ @user.stub(:has_role?).and_return(false)
34
+ end
35
+
36
+ it "should not be fired for String-Object and access-type :read" do
37
+ @rule.fired?("test", :read, @user).should_not be_true
38
+ end
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,129 @@
1
+ require "spec_helper"
2
+
3
+ module Tuersteher
4
+
5
+ describe PathAccessRule do
6
+
7
+ before(:all) do
8
+ @rule = PathAccessRule.new('/admin').method(:get).role(:sysadmin).role(:admin)
9
+ end
10
+
11
+
12
+ context "for User with role :admin" do
13
+ before do
14
+ @user = stub('user')
15
+ @user.stub(:has_role?).with(:sysadmin, :admin).and_return(true)
16
+ end
17
+
18
+ it "should be fired for path='/admin/xyz' and method :get" do
19
+ @rule.fired?("/admin/xyz", :get, @user).should be_true
20
+ end
21
+
22
+ it "should not be fired for other path" do
23
+ @rule.fired?('/todos/admin', :get, @user).should_not be_true
24
+ end
25
+
26
+ it "should not be fired for other method as :get" do
27
+ @rule.fired?("/admin/xyz", :post, @user).should_not be_true
28
+ end
29
+ end
30
+
31
+
32
+ context "for User without role :admin" do
33
+ before do
34
+ @user = stub('user')
35
+ @user.stub(:has_role?).and_return(false)
36
+ end
37
+
38
+ it "should not be fired for correct path and method" do
39
+ @rule.fired?("/admin/xyz", :get, @user).should_not be_true
40
+ end
41
+ end
42
+
43
+
44
+ context "Rule with :all as Path-Matcher" do
45
+ before(:all) do
46
+ @rule = PathAccessRule.new(:all).method(:get).role(:sysadmin).role(:admin)
47
+ @user = stub('user')
48
+ @user.stub(:has_role?).and_return(true)
49
+ end
50
+
51
+ it "should fired for several paths" do
52
+ @rule.fired?("/admin/xyz", :get, @user).should be_true
53
+ @rule.fired?("/xyz", :get, @user).should be_true
54
+ @rule.fired?("/", :get, @user).should be_true
55
+ end
56
+
57
+ it "should not be fired with other method" do
58
+ @rule.fired?("/admin/xyz", :post, @user).should_not be_true
59
+ end
60
+ end
61
+
62
+
63
+ context "Rule with no Methode spezifed => all methods allowed" do
64
+ before(:all) do
65
+ @rule = PathAccessRule.new('/admin').role(:sysadmin).role(:admin)
66
+ @user = stub('user')
67
+ @user.stub(:has_role?).and_return(true)
68
+ end
69
+
70
+ it "should fired for several methods" do
71
+ @rule.fired?("/admin/xyz", :get, @user).should be_true
72
+ @rule.fired?("/admin/xyz", :post, @user).should be_true
73
+ @rule.fired?("/admin/xyz", :put, @user).should be_true
74
+ @rule.fired?("/admin/xyz", :delete, @user).should be_true
75
+ end
76
+
77
+ it "should not be fired with other path" do
78
+ @rule.fired?("/xyz", :post, @user).should_not be_true
79
+ end
80
+ end
81
+
82
+
83
+ context "Rule with no role spezifed => now role needed" do
84
+ before(:all) do
85
+ @rule = PathAccessRule.new('/admin').method(:get)
86
+ @user = stub('user')
87
+ @user.stub(:has_role?).and_return(false)
88
+ end
89
+
90
+ it "should fired for user with no roles" do
91
+ @rule.fired?("/admin/xyz", :get, @user).should be_true
92
+ end
93
+
94
+ it "should not be fired with other path" do
95
+ @rule.fired?("/xyz", :get, @user).should_not be_true
96
+ end
97
+ end
98
+
99
+
100
+ context "Rule with extension" do
101
+ before(:all) do
102
+ @rule = PathAccessRule.new('/admin').method(:get).extension(:modul_function?, :testvalue)
103
+ @rule2 = PathAccessRule.new('/admin').method(:get).extension(:modul_function2?)
104
+ @user = stub('user')
105
+ @user.stub(:has_role?).and_return(false)
106
+ end
107
+
108
+ it "should not be fired with user have not the check_extension" do
109
+ @rule.fired?("/admin", :get, @user).should_not be_true
110
+ end
111
+
112
+ it "should fired for user with true for check-extension" do
113
+ @user.should_receive(:modul_function?).with(:testvalue).and_return(true)
114
+ @rule.fired?("/admin/xyz", :get, @user).should be_true
115
+ end
116
+
117
+ it "should not be fired for user with false for check-extension" do
118
+ @user.should_receive(:modul_function?).with(:testvalue).and_return(false)
119
+ @rule.fired?("/admin/xyz", :get, @user).should_not be_true
120
+ end
121
+
122
+ it "should fired for rule2 and user with true for check-extension" do
123
+ @user.should_receive(:modul_function2?).and_return(true)
124
+ @rule2.fired?("/admin/xyz", :get, @user).should be_true
125
+ end
126
+ end
127
+
128
+ end
129
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,5 @@
1
+ --colour
2
+ --format
3
+ progress
4
+ --loadby
5
+ mtime
@@ -0,0 +1,6 @@
1
+ require 'spec'
2
+ require 'logger'
3
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/tuersteher")
4
+
5
+ # Logger auf stdout stellen
6
+ Tuersteher::TLogger.logger = Logger.new(STDOUT)
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.1.4"
8
+ s.version = "0.2.1"
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-22}
12
+ s.date = %q{2010-08-28}
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 = [
@@ -26,19 +26,32 @@ Gem::Specification.new do |s|
26
26
  "license.txt",
27
27
  "samples/access_rules.rb",
28
28
  "samples/application_controller.rb",
29
+ "spec/acces_rules_storage_spec.rb",
30
+ "spec/access_rules_spec.rb",
31
+ "spec/model_access_rule_spec.rb",
32
+ "spec/path_access_rule_spec.rb",
33
+ "spec/spec.opts",
34
+ "spec/spec_helper.rb",
29
35
  "tuersteher.gemspec"
30
36
  ]
31
37
  s.homepage = %q{http://github.com/bledig/tuersteher}
32
38
  s.rdoc_options = ["--charset=UTF-8"]
33
39
  s.require_paths = ["lib"]
34
- s.rubygems_version = %q{1.3.6}
40
+ s.rubygems_version = %q{1.3.7}
35
41
  s.summary = %q{Security-Layer for Rails-Application}
42
+ s.test_files = [
43
+ "spec/spec_helper.rb",
44
+ "spec/access_rules_spec.rb",
45
+ "spec/path_access_rule_spec.rb",
46
+ "spec/model_access_rule_spec.rb",
47
+ "spec/acces_rules_storage_spec.rb"
48
+ ]
36
49
 
37
50
  if s.respond_to? :specification_version then
38
51
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
39
52
  s.specification_version = 3
40
53
 
41
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
54
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
42
55
  else
43
56
  end
44
57
  else
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
+ - 2
8
9
  - 1
9
- - 4
10
- version: 0.1.4
10
+ version: 0.2.1
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-22 00:00:00 +02:00
18
+ date: 2010-08-28 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -38,6 +38,12 @@ files:
38
38
  - license.txt
39
39
  - samples/access_rules.rb
40
40
  - samples/application_controller.rb
41
+ - spec/acces_rules_storage_spec.rb
42
+ - spec/access_rules_spec.rb
43
+ - spec/model_access_rule_spec.rb
44
+ - spec/path_access_rule_spec.rb
45
+ - spec/spec.opts
46
+ - spec/spec_helper.rb
41
47
  - tuersteher.gemspec
42
48
  has_rdoc: true
43
49
  homepage: http://github.com/bledig/tuersteher
@@ -73,5 +79,9 @@ rubygems_version: 1.3.7
73
79
  signing_key:
74
80
  specification_version: 3
75
81
  summary: Security-Layer for Rails-Application
76
- test_files: []
77
-
82
+ test_files:
83
+ - spec/spec_helper.rb
84
+ - spec/access_rules_spec.rb
85
+ - spec/path_access_rule_spec.rb
86
+ - spec/model_access_rule_spec.rb
87
+ - spec/acces_rules_storage_spec.rb