tuersteher 0.1.4 → 0.2.1

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/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