tuersteher 0.3.0 → 0.3.3
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 +1 -1
- data/lib/tuersteher.rb +132 -58
- data/spec/model_access_rule_spec.rb +1 -1
- data/spec/model_extensions_spec.rb +58 -0
- data/spec/spec_helper.rb +1 -0
- data/tuersteher.gemspec +8 -6
- metadata +8 -6
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
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
|
-
#
|
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
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
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
|
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
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
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
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
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
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
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
|
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
|
-
|
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
|
-
|
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] =
|
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
|
@@ -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
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.
|
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-
|
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/
|
44
|
-
"spec/path_access_rule_spec.rb",
|
44
|
+
"spec/path_access_rule_spec.rb",
|
45
45
|
"spec/model_access_rule_spec.rb",
|
46
|
-
"spec/
|
47
|
-
"spec/
|
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:
|
4
|
+
hash: 21
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
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-
|
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/
|
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
|