declarative_authorization 0.4.1 → 0.5
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/CHANGELOG +15 -0
- data/README.rdoc +8 -7
- data/Rakefile +0 -8
- data/app/controllers/authorization_rules_controller.rb +1 -1
- data/app/helpers/authorization_rules_helper.rb +3 -3
- data/config/routes.rb +5 -2
- data/lib/declarative_authorization.rb +2 -0
- data/lib/declarative_authorization/authorization.rb +20 -14
- data/lib/declarative_authorization/in_controller.rb +2 -5
- data/lib/declarative_authorization/in_model.rb +13 -10
- data/lib/declarative_authorization/maintenance.rb +4 -4
- data/lib/declarative_authorization/obligation_scope.rb +51 -13
- data/lib/declarative_authorization/rails_legacy.rb +9 -1
- data/lib/declarative_authorization/railsengine.rb +6 -0
- data/lib/declarative_authorization/reader.rb +61 -7
- data/lib/tasks/authorization_tasks.rake +82 -0
- data/test/authorization_test.rb +108 -0
- data/test/controller_test.rb +4 -3
- data/test/dsl_reader_test.rb +21 -0
- data/test/helper_test.rb +1 -0
- data/test/model_test.rb +229 -91
- data/test/test_helper.rb +44 -13
- metadata +23 -9
@@ -28,13 +28,19 @@ module Authorization
|
|
28
28
|
# * AuthorizationRulesReader#is,
|
29
29
|
# * AuthorizationRulesReader#is_not,
|
30
30
|
# * AuthorizationRulesReader#is_in,
|
31
|
-
# * AuthorizationRulesReader#is_not_in
|
31
|
+
# * AuthorizationRulesReader#is_not_in,
|
32
|
+
# * AuthorizationRulesReader#lt,
|
33
|
+
# * AuthorizationRulesReader#lte,
|
34
|
+
# * AuthorizationRulesReader#gt,
|
35
|
+
# * AuthorizationRulesReader#gte
|
32
36
|
#
|
33
37
|
# And privilege definition methods
|
34
38
|
# * PrivilegesReader#privilege,
|
35
39
|
# * PrivilegesReader#includes
|
36
40
|
#
|
37
41
|
module Reader
|
42
|
+
# Signals that the specified file to load was not found.
|
43
|
+
class DSLFileNotFoundError < Exception; end
|
38
44
|
# Signals errors that occur while reading and parsing an authorization DSL
|
39
45
|
class DSLError < Exception; end
|
40
46
|
# Signals errors in the syntax of an authorization DSL.
|
@@ -53,6 +59,19 @@ module Authorization
|
|
53
59
|
@auth_rules_reader = AuthorizationRulesReader.new
|
54
60
|
end
|
55
61
|
|
62
|
+
# ensures you get back a DSLReader
|
63
|
+
# if you provide a:
|
64
|
+
# DSLReader - you will get it back.
|
65
|
+
# String or Array - it will treat it as if you have passed a path or an array of paths and attempt to load those.
|
66
|
+
def self.factory(obj)
|
67
|
+
case obj
|
68
|
+
when Reader::DSLReader
|
69
|
+
obj
|
70
|
+
when String, Array
|
71
|
+
load(obj)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
56
75
|
# Parses a authorization DSL specification from the string given
|
57
76
|
# in +dsl_data+. Raises DSLSyntaxError if errors occur on parsing.
|
58
77
|
def parse (dsl_data, file_name = nil)
|
@@ -71,7 +90,11 @@ module Authorization
|
|
71
90
|
reader = new
|
72
91
|
dsl_files = [dsl_files].flatten
|
73
92
|
dsl_files.each do |file|
|
74
|
-
|
93
|
+
begin
|
94
|
+
reader.parse(File.read(file), file)
|
95
|
+
rescue SystemCallError
|
96
|
+
raise ::Authorization::Reader::DSLFileNotFoundError, "Error reading authorization rules file with path '#{file}'! Please ensure it exists and that it is accessible."
|
97
|
+
end
|
75
98
|
end
|
76
99
|
reader
|
77
100
|
end
|
@@ -148,12 +171,13 @@ module Authorization
|
|
148
171
|
|
149
172
|
class AuthorizationRulesReader
|
150
173
|
attr_reader :roles, :role_hierarchy, :auth_rules,
|
151
|
-
:role_descriptions, :role_titles # :nodoc:
|
174
|
+
:role_descriptions, :role_titles, :omnipotent_roles # :nodoc:
|
152
175
|
|
153
176
|
def initialize # :nodoc:
|
154
177
|
@current_role = nil
|
155
178
|
@current_rule = nil
|
156
179
|
@roles = []
|
180
|
+
@omnipotent_roles = []
|
157
181
|
# higher_role => [lower_roles]
|
158
182
|
@role_hierarchy = {}
|
159
183
|
@role_titles = {}
|
@@ -248,7 +272,16 @@ module Authorization
|
|
248
272
|
@current_rule = nil
|
249
273
|
end
|
250
274
|
end
|
251
|
-
|
275
|
+
|
276
|
+
# Removes any permission checks for the current role.
|
277
|
+
# role :admin
|
278
|
+
# has_omnipotence
|
279
|
+
# end
|
280
|
+
def has_omnipotence
|
281
|
+
raise DSLError, "has_omnipotence only allowed in role blocks" if @current_role.nil?
|
282
|
+
@omnipotent_roles << @current_role
|
283
|
+
end
|
284
|
+
|
252
285
|
# Sets a description for the current role. E.g.
|
253
286
|
# role :admin
|
254
287
|
# description "To be assigned to administrative personnel"
|
@@ -279,7 +312,7 @@ module Authorization
|
|
279
312
|
# end
|
280
313
|
def to (*privs)
|
281
314
|
raise DSLError, "to only allowed in has_permission_on blocks" if @current_rule.nil?
|
282
|
-
@current_rule.append_privileges(privs)
|
315
|
+
@current_rule.append_privileges(privs.flatten)
|
283
316
|
end
|
284
317
|
|
285
318
|
# In a has_permission_on block, if_attribute specifies conditions
|
@@ -442,6 +475,26 @@ module Authorization
|
|
442
475
|
[:is_not_in, block]
|
443
476
|
end
|
444
477
|
|
478
|
+
# Less than
|
479
|
+
def lt (&block)
|
480
|
+
[:lt, block]
|
481
|
+
end
|
482
|
+
|
483
|
+
# Less than or equal to
|
484
|
+
def lte (&block)
|
485
|
+
[:lte, block]
|
486
|
+
end
|
487
|
+
|
488
|
+
# Greater than
|
489
|
+
def gt (&block)
|
490
|
+
[:gt, block]
|
491
|
+
end
|
492
|
+
|
493
|
+
# Greater than or equal to
|
494
|
+
def gte (&block)
|
495
|
+
[:gte, block]
|
496
|
+
end
|
497
|
+
|
445
498
|
private
|
446
499
|
def parse_attribute_conditions_hash! (hash)
|
447
500
|
merge_hash = {}
|
@@ -449,9 +502,9 @@ module Authorization
|
|
449
502
|
if value.is_a?(Hash)
|
450
503
|
parse_attribute_conditions_hash!(value)
|
451
504
|
elsif !value.is_a?(Array)
|
452
|
-
merge_hash[key] = [:is,
|
505
|
+
merge_hash[key] = [:is, proc { value }]
|
453
506
|
elsif value.is_a?(Array) and !value[0].is_a?(Symbol)
|
454
|
-
merge_hash[key] = [:is_in,
|
507
|
+
merge_hash[key] = [:is_in, proc { value }]
|
455
508
|
end
|
456
509
|
end
|
457
510
|
hash.merge!(merge_hash)
|
@@ -465,3 +518,4 @@ module Authorization
|
|
465
518
|
end
|
466
519
|
end
|
467
520
|
end
|
521
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
namespace :auth do
|
2
|
+
desc "Lists all privileges used in controllers, views, models"
|
3
|
+
task :used_privileges do
|
4
|
+
# TODO note where privileges are used
|
5
|
+
require File.join(RAILS_ROOT, 'config', 'boot.rb')
|
6
|
+
require File.join(RAILS_ROOT, 'config', 'environment.rb')
|
7
|
+
controllers = [ApplicationController]
|
8
|
+
Dir.new("#{RAILS_ROOT}/app/controllers").entries.each do |controller_file|
|
9
|
+
if controller_file =~ /_controller/
|
10
|
+
controllers << controller_file.gsub(".rb","").camelize.constantize
|
11
|
+
end
|
12
|
+
end
|
13
|
+
perms = controllers.select {|c| c.send(:class_variable_defined?, :@@permissions)}.
|
14
|
+
inject([]) do |all, c|
|
15
|
+
contr_context = c.name.sub("Controller", "").tableize.to_sym
|
16
|
+
contr_perms = c.send(:class_variable_get, :@@permissions).collect do |cp|
|
17
|
+
[cp.privilege, cp.context || contr_context, cp]
|
18
|
+
end
|
19
|
+
if contr_perms.any? {|cp| cp[0].nil?}
|
20
|
+
contr_perms += c.send(:action_methods).collect {|am| am.to_sym}.
|
21
|
+
reject {|am| contr_perms.any? {|cp| cp[2].actions.include?(am)}}.
|
22
|
+
collect {|am| [am, contr_context]}
|
23
|
+
end
|
24
|
+
all += contr_perms.reject {|cp| cp[0].nil?}.collect {|cp| cp[0..1]}
|
25
|
+
end
|
26
|
+
|
27
|
+
model_files = `grep -l "^[[:space:]]*using_access_control" #{RAILS_ROOT}/app/models/*.rb`.split("\n")
|
28
|
+
models_with_ac = model_files.collect {|mf| mf.sub(/^.*\//, "").sub(".rb", "").tableize.to_sym}
|
29
|
+
model_security_privs = [:create, :read, :update, :delete]
|
30
|
+
models_with_ac.each {|m| perms += model_security_privs.collect{|msp| [msp, m]}}
|
31
|
+
|
32
|
+
grep_file_pattern = "#{RAILS_ROOT}/app/models/*.rb #{RAILS_ROOT}/app/views/**/* #{RAILS_ROOT}/app/controllers/*.rb"
|
33
|
+
`grep "permitted_to?" #{grep_file_pattern}`.split("\n").each do |ptu|
|
34
|
+
file, grep_match = ptu.split(':', 2)
|
35
|
+
context = privilege = nil
|
36
|
+
if (match = grep_match.match(/permitted_to\?\(?\s*:(\w+),\s*(:?@?\w+)/))
|
37
|
+
privilege = match[1].to_sym
|
38
|
+
if match[2][0..0] == ':'
|
39
|
+
context = match[2][1..-1].to_sym
|
40
|
+
else
|
41
|
+
c = (match[2][0..0] == '@' ? match[2][1..-1] : match[2]).pluralize.to_sym
|
42
|
+
context = c if perms.any? {|p| p[1] == c}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
if privilege.nil? or context.nil?
|
46
|
+
puts "Could not handle: #{ptu}"
|
47
|
+
else
|
48
|
+
perms << [privilege, context]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
`grep ".with_permissions_to" #{grep_file_pattern}`.split("\n").each do |wpt|
|
53
|
+
file, grep_match = wpt.split(':', 2)
|
54
|
+
context = privilege = nil
|
55
|
+
if match = grep_match.match(/(\w+\.)?with_permissions_to(\(:\w+)?/)
|
56
|
+
c = match[1][0..-2].tableize.to_sym if match[1]
|
57
|
+
c ||= File.basename(file, '.rb').tableize.to_sym
|
58
|
+
context = c if perms.any? {|p| p[1] == c}
|
59
|
+
privilege = match[2] && match[2][(match[2][0..0]=='(' ? 2 : 1)..-1].to_sym
|
60
|
+
privilege ||= :read
|
61
|
+
end
|
62
|
+
if privilege.nil? or context.nil?
|
63
|
+
puts "Could not handle: #{ptu}"
|
64
|
+
else
|
65
|
+
perms << [privilege, context]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
perms.uniq!
|
70
|
+
perm_hash = {}
|
71
|
+
perms.each do |cp|
|
72
|
+
perm_hash[cp[1]] ||= []
|
73
|
+
perm_hash[cp[1]] << cp[0]
|
74
|
+
end
|
75
|
+
|
76
|
+
puts "Privileges currently in use:"
|
77
|
+
perm_hash.each do |context, privileges|
|
78
|
+
puts " #{context.inspect}:\t#{privileges.collect {|p| p.inspect}.sort * ', '}"
|
79
|
+
#privileges.collect {|p| p.inspect}.sort.each {|p| puts " #{p}"}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/test/authorization_test.rb
CHANGED
@@ -34,6 +34,20 @@ class AuthorizationTest < Test::Unit::TestCase
|
|
34
34
|
:user => MockUser.new(:test_role))
|
35
35
|
end
|
36
36
|
|
37
|
+
def test_permit_elevated_people
|
38
|
+
reader = Authorization::Reader::DSLReader.new
|
39
|
+
reader.parse %{
|
40
|
+
authorization do
|
41
|
+
role :admin do
|
42
|
+
has_omnipotence
|
43
|
+
end
|
44
|
+
end
|
45
|
+
}
|
46
|
+
engine = Authorization::Engine.new(reader)
|
47
|
+
assert engine.permit?(:test, :context => :people,
|
48
|
+
:user => MockUser.new(:admin))
|
49
|
+
end
|
50
|
+
|
37
51
|
def test_permit_multiple_contexts
|
38
52
|
reader = Authorization::Reader::DSLReader.new
|
39
53
|
reader.parse %{
|
@@ -539,6 +553,99 @@ class AuthorizationTest < Test::Unit::TestCase
|
|
539
553
|
:object => MockDataObject.new(:test_attrs => [3,4] ))
|
540
554
|
end
|
541
555
|
|
556
|
+
def test_attribute_lte
|
557
|
+
reader = Authorization::Reader::DSLReader.new
|
558
|
+
reader.parse %|
|
559
|
+
authorization do
|
560
|
+
role :test_role do
|
561
|
+
has_permission_on :permissions, :to => :test do
|
562
|
+
if_attribute :test_attr => lte { user.test_attr }
|
563
|
+
if_attribute :test_attr => 3
|
564
|
+
end
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
|
568
|
+
engine = Authorization::Engine.new(reader)
|
569
|
+
# object < user -> pass
|
570
|
+
assert engine.permit?(:test, :context => :permissions,
|
571
|
+
:user => MockUser.new(:test_role, :test_attr => 2),
|
572
|
+
:object => MockDataObject.new(:test_attr => 1))
|
573
|
+
# object > user && object = control -> pass
|
574
|
+
assert engine.permit?(:test, :context => :permissions,
|
575
|
+
:user => MockUser.new(:test_role, :test_attr => 2),
|
576
|
+
:object => MockDataObject.new(:test_attr => 3))
|
577
|
+
# object = user -> pass
|
578
|
+
assert engine.permit?(:test, :context => :permissions,
|
579
|
+
:user => MockUser.new(:test_role, :test_attr => 1),
|
580
|
+
:object => MockDataObject.new(:test_attr => 1))
|
581
|
+
# object > user -> fail
|
582
|
+
assert((not(engine.permit?(:test, :context => :permissions,
|
583
|
+
:user => MockUser.new(:test_role, :test_attr => 1),
|
584
|
+
:object => MockDataObject.new(:test_attr => 2)))))
|
585
|
+
end
|
586
|
+
|
587
|
+
def test_attribute_gt
|
588
|
+
reader = Authorization::Reader::DSLReader.new
|
589
|
+
reader.parse %|
|
590
|
+
authorization do
|
591
|
+
role :test_role do
|
592
|
+
has_permission_on :permissions, :to => :test do
|
593
|
+
if_attribute :test_attr => gt { user.test_attr }
|
594
|
+
if_attribute :test_attr => 3
|
595
|
+
end
|
596
|
+
end
|
597
|
+
end
|
598
|
+
|
|
599
|
+
engine = Authorization::Engine.new(reader)
|
600
|
+
# object > user -> pass
|
601
|
+
assert engine.permit?(:test, :context => :permissions,
|
602
|
+
:user => MockUser.new(:test_role, :test_attr => 1),
|
603
|
+
:object => MockDataObject.new(:test_attr => 2))
|
604
|
+
# object < user && object = control -> pass
|
605
|
+
assert engine.permit?(:test, :context => :permissions,
|
606
|
+
:user => MockUser.new(:test_role, :test_attr => 4),
|
607
|
+
:object => MockDataObject.new(:test_attr => 3))
|
608
|
+
# object = user -> fail
|
609
|
+
assert((not(engine.permit?(:test, :context => :permissions,
|
610
|
+
:user => MockUser.new(:test_role, :test_attr => 1),
|
611
|
+
:object => MockDataObject.new(:test_attr => 1)))))
|
612
|
+
# object < user -> fail
|
613
|
+
assert((not(engine.permit?(:test, :context => :permissions,
|
614
|
+
:user => MockUser.new(:test_role, :test_attr => 2),
|
615
|
+
:object => MockDataObject.new(:test_attr => 1)))))
|
616
|
+
end
|
617
|
+
|
618
|
+
def test_attribute_gte
|
619
|
+
reader = Authorization::Reader::DSLReader.new
|
620
|
+
reader.parse %|
|
621
|
+
authorization do
|
622
|
+
role :test_role do
|
623
|
+
has_permission_on :permissions, :to => :test do
|
624
|
+
if_attribute :test_attr => gte { user.test_attr }
|
625
|
+
if_attribute :test_attr => 3
|
626
|
+
end
|
627
|
+
end
|
628
|
+
end
|
629
|
+
|
|
630
|
+
engine = Authorization::Engine.new(reader)
|
631
|
+
# object > user -> pass
|
632
|
+
assert engine.permit?(:test, :context => :permissions,
|
633
|
+
:user => MockUser.new(:test_role, :test_attr => 1),
|
634
|
+
:object => MockDataObject.new(:test_attr => 2))
|
635
|
+
# object < user && object = control -> pass
|
636
|
+
assert engine.permit?(:test, :context => :permissions,
|
637
|
+
:user => MockUser.new(:test_role, :test_attr => 4),
|
638
|
+
:object => MockDataObject.new(:test_attr => 3))
|
639
|
+
# object = user -> pass
|
640
|
+
assert engine.permit?(:test, :context => :permissions,
|
641
|
+
:user => MockUser.new(:test_role, :test_attr => 1),
|
642
|
+
:object => MockDataObject.new(:test_attr => 1))
|
643
|
+
# object < user -> fail
|
644
|
+
assert((not(engine.permit?(:test, :context => :permissions,
|
645
|
+
:user => MockUser.new(:test_role, :test_attr => 2),
|
646
|
+
:object => MockDataObject.new(:test_attr => 1)))))
|
647
|
+
end
|
648
|
+
|
542
649
|
def test_attribute_deep
|
543
650
|
reader = Authorization::Reader::DSLReader.new
|
544
651
|
reader.parse %|
|
@@ -955,3 +1062,4 @@ class AuthorizationTest < Test::Unit::TestCase
|
|
955
1062
|
cloned_engine.auth_rules[0].attributes[0].send(:instance_variable_get, :@conditions_hash)[:attr].object_id
|
956
1063
|
end
|
957
1064
|
end
|
1065
|
+
|
data/test/controller_test.rb
CHANGED
@@ -201,7 +201,7 @@ class LoadMockObjectsController < MocksController
|
|
201
201
|
filter_access_to :show, :attribute_check => true, :model => LoadMockObject
|
202
202
|
filter_access_to :edit, :attribute_check => true
|
203
203
|
filter_access_to :update, :delete, :attribute_check => true,
|
204
|
-
:load_method =>
|
204
|
+
:load_method => proc {MockDataObject.new(:test => 1)}
|
205
205
|
filter_access_to :create do
|
206
206
|
permitted_to! :edit, :load_mock_objects
|
207
207
|
end
|
@@ -220,7 +220,8 @@ class LoadObjectControllerTest < ActionController::TestCase
|
|
220
220
|
authorization do
|
221
221
|
role :test_role do
|
222
222
|
has_permission_on :load_mock_objects, :to => [:show, :edit] do
|
223
|
-
if_attribute :id =>
|
223
|
+
if_attribute :id => 1
|
224
|
+
if_attribute :id => "1"
|
224
225
|
end
|
225
226
|
end
|
226
227
|
end
|
@@ -372,7 +373,7 @@ class CommonChild1Controller < CommonController
|
|
372
373
|
end
|
373
374
|
class CommonChild2Controller < CommonController
|
374
375
|
filter_access_to :delete
|
375
|
-
define_action_methods :show
|
376
|
+
define_action_methods :show, :delete
|
376
377
|
end
|
377
378
|
class HierachicalControllerTest < ActionController::TestCase
|
378
379
|
tests CommonChild2Controller
|
data/test/dsl_reader_test.rb
CHANGED
@@ -90,6 +90,10 @@ class DSLReaderTest < Test::Unit::TestCase
|
|
90
90
|
if_attribute :test_attr_4 => does_not_contain { user.test_attr }
|
91
91
|
if_attribute :test_attr_5 => is_in { user.test_attr }
|
92
92
|
if_attribute :test_attr_5 => is_not_in { user.test_attr }
|
93
|
+
if_attribute :test_attr_6 => lt { user.test_attr }
|
94
|
+
if_attribute :test_attr_6 => lte { user.test_attr }
|
95
|
+
if_attribute :test_attr_6 => gt { user.test_attr }
|
96
|
+
if_attribute :test_attr_6 => gte { user.test_attr }
|
93
97
|
end
|
94
98
|
end
|
95
99
|
end
|
@@ -154,4 +158,21 @@ class DSLReaderTest < Test::Unit::TestCase
|
|
154
158
|
}
|
155
159
|
end
|
156
160
|
end
|
161
|
+
|
162
|
+
def test_factory_returns_self
|
163
|
+
reader = Authorization::Reader::DSLReader.new
|
164
|
+
assert_equal(Authorization::Reader::DSLReader.factory(reader).object_id, reader.object_id)
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_factory_loads_file
|
168
|
+
reader = Authorization::Reader::DSLReader.factory((DA_ROOT + "authorization_rules.dist.rb").to_s)
|
169
|
+
assert_equal(Authorization::Reader::DSLReader, reader.class)
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_load_file_not_found
|
173
|
+
assert_raise(Authorization::Reader::DSLFileNotFoundError) do
|
174
|
+
Authorization::Reader::DSLReader.load("nonexistent_file.rb")
|
175
|
+
end
|
176
|
+
end
|
157
177
|
end
|
178
|
+
|
data/test/helper_test.rb
CHANGED
data/test/model_test.rb
CHANGED
@@ -26,14 +26,21 @@ class TestModel < ActiveRecord::Base
|
|
26
26
|
:class_name => "TestAttrThrough", :source => :test_attr_throughs,
|
27
27
|
:conditions => "test_attrs.attr = 1"
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
# TODO currently not working in Rails 3
|
30
|
+
if Rails.version < "3"
|
31
|
+
has_and_belongs_to_many :test_attr_throughs_habtm, :join_table => :test_attrs,
|
32
|
+
:class_name => "TestAttrThrough"
|
33
|
+
end
|
31
34
|
|
32
|
-
|
35
|
+
if Rails.version < "3"
|
36
|
+
named_scope :with_content, :conditions => "test_models.content IS NOT NULL"
|
37
|
+
else
|
38
|
+
scope :with_content, :conditions => "test_models.content IS NOT NULL"
|
39
|
+
end
|
33
40
|
|
34
41
|
# Primary key test
|
35
|
-
#
|
36
|
-
|
42
|
+
# :primary_key only available from Rails 2.2
|
43
|
+
unless Rails.version < "2.2"
|
37
44
|
has_many :test_attrs_with_primary_id, :class_name => "TestAttr",
|
38
45
|
:primary_key => :test_attr_through_id, :foreign_key => :test_attr_through_id
|
39
46
|
has_many :test_attr_throughs_with_primary_id,
|
@@ -274,32 +281,43 @@ class NamedScopeModelTest < Test::Unit::TestCase
|
|
274
281
|
authorization do
|
275
282
|
role :test_role do
|
276
283
|
has_permission_on :test_models, :to => :read do
|
277
|
-
if_attribute :
|
284
|
+
if_attribute :test_attr_through_id => 1
|
285
|
+
end
|
286
|
+
has_permission_on :test_attrs, :to => :read do
|
287
|
+
if_permitted_to :read, :test_model
|
278
288
|
end
|
279
289
|
end
|
280
290
|
end
|
281
291
|
}
|
282
292
|
Authorization::Engine.instance(reader)
|
283
293
|
|
284
|
-
|
285
|
-
TestModel.create!(:
|
286
|
-
|
294
|
+
country = Country.create!
|
295
|
+
model_1 = TestModel.create!(:test_attr_through_id => 1, :content => "Content")
|
296
|
+
country.test_models << model_1
|
297
|
+
TestModel.create!(:test_attr_through_id => 1)
|
298
|
+
TestModel.create!(:test_attr_through_id => 2, :content => "Content")
|
287
299
|
|
288
300
|
user = MockUser.new(:test_role)
|
289
301
|
|
302
|
+
# TODO implement query_count for Rails 3
|
290
303
|
TestModel.query_count = 0
|
291
304
|
assert_equal 2, TestModel.with_permissions_to(:read, :user => user).length
|
292
|
-
assert_equal 1, TestModel.query_count
|
305
|
+
assert_equal 1, TestModel.query_count if Rails.version < "3"
|
293
306
|
|
294
307
|
TestModel.query_count = 0
|
295
308
|
assert_equal 1, TestModel.with_content.with_permissions_to(:read, :user => user).length
|
296
|
-
assert_equal 1, TestModel.query_count
|
309
|
+
assert_equal 1, TestModel.query_count if Rails.version < "3"
|
297
310
|
|
298
311
|
TestModel.query_count = 0
|
299
312
|
assert_equal 1, TestModel.with_permissions_to(:read, :user => user).with_content.length
|
300
|
-
assert_equal 1, TestModel.query_count
|
313
|
+
assert_equal 1, TestModel.query_count if Rails.version < "3"
|
314
|
+
|
315
|
+
TestModel.query_count = 0
|
316
|
+
assert_equal 1, country.test_models.with_permissions_to(:read, :user => user).length
|
317
|
+
assert_equal 1, TestModel.query_count if Rails.version < "3"
|
301
318
|
|
302
319
|
TestModel.delete_all
|
320
|
+
Country.delete_all
|
303
321
|
end
|
304
322
|
|
305
323
|
def test_with_modified_context
|
@@ -372,6 +390,110 @@ class NamedScopeModelTest < Test::Unit::TestCase
|
|
372
390
|
TestModel.delete_all
|
373
391
|
end
|
374
392
|
|
393
|
+
def test_with_lt
|
394
|
+
reader = Authorization::Reader::DSLReader.new
|
395
|
+
reader.parse %{
|
396
|
+
authorization do
|
397
|
+
role :test_role do
|
398
|
+
has_permission_on :test_models, :to => :read do
|
399
|
+
if_attribute :id => lt { user.test_attr_value }
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
}
|
404
|
+
Authorization::Engine.instance(reader)
|
405
|
+
|
406
|
+
test_model_1 = TestModel.create!
|
407
|
+
TestModel.create!
|
408
|
+
|
409
|
+
user = MockUser.new(:test_role, :test_attr_value => test_model_1.id + 1)
|
410
|
+
assert_equal 1, TestModel.with_permissions_to(:read,
|
411
|
+
:context => :test_models, :user => user).length
|
412
|
+
assert_equal 1, TestModel.with_permissions_to(:read, :user => user).length
|
413
|
+
assert_raise Authorization::NotAuthorized do
|
414
|
+
TestModel.with_permissions_to(:update_test_models, :user => user)
|
415
|
+
end
|
416
|
+
TestModel.delete_all
|
417
|
+
end
|
418
|
+
|
419
|
+
def test_with_lte
|
420
|
+
reader = Authorization::Reader::DSLReader.new
|
421
|
+
reader.parse %{
|
422
|
+
authorization do
|
423
|
+
role :test_role do
|
424
|
+
has_permission_on :test_models, :to => :read do
|
425
|
+
if_attribute :id => lte { user.test_attr_value }
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|
429
|
+
}
|
430
|
+
Authorization::Engine.instance(reader)
|
431
|
+
|
432
|
+
test_model_1 = TestModel.create!
|
433
|
+
2.times { TestModel.create! }
|
434
|
+
|
435
|
+
user = MockUser.new(:test_role, :test_attr_value => test_model_1.id + 1)
|
436
|
+
assert_equal 2, TestModel.with_permissions_to(:read,
|
437
|
+
:context => :test_models, :user => user).length
|
438
|
+
assert_equal 2, TestModel.with_permissions_to(:read, :user => user).length
|
439
|
+
assert_raise Authorization::NotAuthorized do
|
440
|
+
TestModel.with_permissions_to(:update_test_models, :user => user)
|
441
|
+
end
|
442
|
+
TestModel.delete_all
|
443
|
+
end
|
444
|
+
|
445
|
+
def test_with_gt
|
446
|
+
reader = Authorization::Reader::DSLReader.new
|
447
|
+
reader.parse %{
|
448
|
+
authorization do
|
449
|
+
role :test_role do
|
450
|
+
has_permission_on :test_models, :to => :read do
|
451
|
+
if_attribute :id => gt { user.test_attr_value }
|
452
|
+
end
|
453
|
+
end
|
454
|
+
end
|
455
|
+
}
|
456
|
+
Authorization::Engine.instance(reader)
|
457
|
+
|
458
|
+
TestModel.create!
|
459
|
+
test_model_1 = TestModel.create!
|
460
|
+
|
461
|
+
user = MockUser.new(:test_role, :test_attr_value => test_model_1.id - 1)
|
462
|
+
assert_equal 1, TestModel.with_permissions_to(:read,
|
463
|
+
:context => :test_models, :user => user).length
|
464
|
+
assert_equal 1, TestModel.with_permissions_to(:read, :user => user).length
|
465
|
+
assert_raise Authorization::NotAuthorized do
|
466
|
+
TestModel.with_permissions_to(:update_test_models, :user => user)
|
467
|
+
end
|
468
|
+
TestModel.delete_all
|
469
|
+
end
|
470
|
+
|
471
|
+
def test_with_gte
|
472
|
+
reader = Authorization::Reader::DSLReader.new
|
473
|
+
reader.parse %{
|
474
|
+
authorization do
|
475
|
+
role :test_role do
|
476
|
+
has_permission_on :test_models, :to => :read do
|
477
|
+
if_attribute :id => gte { user.test_attr_value }
|
478
|
+
end
|
479
|
+
end
|
480
|
+
end
|
481
|
+
}
|
482
|
+
Authorization::Engine.instance(reader)
|
483
|
+
|
484
|
+
2.times { TestModel.create! }
|
485
|
+
test_model_1 = TestModel.create!
|
486
|
+
|
487
|
+
user = MockUser.new(:test_role, :test_attr_value => test_model_1.id - 1)
|
488
|
+
assert_equal 2, TestModel.with_permissions_to(:read,
|
489
|
+
:context => :test_models, :user => user).length
|
490
|
+
assert_equal 2, TestModel.with_permissions_to(:read, :user => user).length
|
491
|
+
assert_raise Authorization::NotAuthorized do
|
492
|
+
TestModel.with_permissions_to(:update_test_models, :user => user)
|
493
|
+
end
|
494
|
+
TestModel.delete_all
|
495
|
+
end
|
496
|
+
|
375
497
|
def test_with_empty_obligations
|
376
498
|
reader = Authorization::Reader::DSLReader.new
|
377
499
|
reader.parse %{
|
@@ -703,71 +825,78 @@ class NamedScopeModelTest < Test::Unit::TestCase
|
|
703
825
|
TestAttr.delete_all
|
704
826
|
end
|
705
827
|
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
828
|
+
# TODO fails in Rails 3 because TestModel.scoped.joins(:test_attr_throughs_with_attr)
|
829
|
+
# does not work
|
830
|
+
if Rails.version < "3"
|
831
|
+
def test_with_contains_through_conditions
|
832
|
+
reader = Authorization::Reader::DSLReader.new
|
833
|
+
reader.parse %{
|
834
|
+
authorization do
|
835
|
+
role :test_role do
|
836
|
+
has_permission_on :test_models, :to => :read do
|
837
|
+
if_attribute :test_attr_throughs_with_attr => contains { user }
|
838
|
+
end
|
713
839
|
end
|
714
840
|
end
|
715
|
-
|
716
|
-
|
717
|
-
Authorization::Engine.instance(reader)
|
841
|
+
}
|
842
|
+
Authorization::Engine.instance(reader)
|
718
843
|
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
844
|
+
test_model_1 = TestModel.create!
|
845
|
+
test_model_2 = TestModel.create!
|
846
|
+
test_model_1.test_attrs.create!(:attr => 1).test_attr_throughs.create!
|
847
|
+
test_model_1.test_attrs.create!(:attr => 2).test_attr_throughs.create!
|
848
|
+
test_model_2.test_attrs.create!(:attr => 1).test_attr_throughs.create!
|
849
|
+
test_model_2.test_attrs.create!(:attr => 2).test_attr_throughs.create!
|
725
850
|
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
851
|
+
#assert_equal 1, test_model_1.test_attrs_with_attr.length
|
852
|
+
user = MockUser.new(:test_role,
|
853
|
+
:id => test_model_1.test_attr_throughs.first.id)
|
854
|
+
assert_equal 1, TestModel.with_permissions_to(:read, :user => user).length
|
855
|
+
user = MockUser.new(:test_role,
|
856
|
+
:id => test_model_1.test_attr_throughs.last.id)
|
857
|
+
assert_equal 0, TestModel.with_permissions_to(:read, :user => user).length
|
733
858
|
|
734
|
-
|
735
|
-
|
736
|
-
|
859
|
+
TestModel.delete_all
|
860
|
+
TestAttrThrough.delete_all
|
861
|
+
TestAttr.delete_all
|
862
|
+
end
|
737
863
|
end
|
738
864
|
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
865
|
+
if Rails.version < "3"
|
866
|
+
def test_with_contains_habtm
|
867
|
+
reader = Authorization::Reader::DSLReader.new
|
868
|
+
reader.parse %{
|
869
|
+
authorization do
|
870
|
+
role :test_role do
|
871
|
+
has_permission_on :test_models, :to => :read do
|
872
|
+
if_attribute :test_attr_throughs_habtm => contains { user.test_attr_through_id }
|
873
|
+
end
|
746
874
|
end
|
747
875
|
end
|
748
|
-
|
749
|
-
|
750
|
-
Authorization::Engine.instance(reader)
|
876
|
+
}
|
877
|
+
Authorization::Engine.instance(reader)
|
751
878
|
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
879
|
+
# TODO habtm currently not working in Rails 3
|
880
|
+
test_model_1 = TestModel.create!
|
881
|
+
test_model_2 = TestModel.create!
|
882
|
+
test_attr_through_1 = TestAttrThrough.create!
|
883
|
+
test_attr_through_2 = TestAttrThrough.create!
|
884
|
+
TestAttr.create! :test_model_id => test_model_1.id, :test_attr_through_id => test_attr_through_1.id
|
885
|
+
TestAttr.create! :test_model_id => test_model_2.id, :test_attr_through_id => test_attr_through_2.id
|
758
886
|
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
887
|
+
user = MockUser.new(:test_role,
|
888
|
+
:test_attr_through_id => test_model_1.test_attr_throughs_habtm.first.id)
|
889
|
+
assert_equal 1, TestModel.with_permissions_to(:read, :user => user).length
|
890
|
+
assert_equal test_model_1, TestModel.with_permissions_to(:read, :user => user)[0]
|
763
891
|
|
764
|
-
|
765
|
-
|
766
|
-
|
892
|
+
TestModel.delete_all
|
893
|
+
TestAttrThrough.delete_all
|
894
|
+
TestAttr.delete_all
|
895
|
+
end
|
767
896
|
end
|
768
897
|
|
769
|
-
#
|
770
|
-
if
|
898
|
+
# :primary_key not available in Rails prior to 2.2
|
899
|
+
if Rails.version > "2.2"
|
771
900
|
def test_with_contains_through_primary_key
|
772
901
|
reader = Authorization::Reader::DSLReader.new
|
773
902
|
reader.parse %{
|
@@ -854,37 +983,41 @@ class NamedScopeModelTest < Test::Unit::TestCase
|
|
854
983
|
TestAttr.delete_all
|
855
984
|
end
|
856
985
|
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
986
|
+
# TODO fails in Rails 3 because TestModel.scoped.joins(:test_attr_throughs_with_attr)
|
987
|
+
# does not work
|
988
|
+
if Rails.version < "3"
|
989
|
+
def test_with_is_and_has_one_through_conditions
|
990
|
+
reader = Authorization::Reader::DSLReader.new
|
991
|
+
reader.parse %{
|
992
|
+
authorization do
|
993
|
+
role :test_role do
|
994
|
+
has_permission_on :test_models, :to => :read do
|
995
|
+
if_attribute :test_attr_throughs_with_attr_and_has_one => is { user }
|
996
|
+
end
|
864
997
|
end
|
865
998
|
end
|
866
|
-
|
867
|
-
|
868
|
-
Authorization::Engine.instance(reader)
|
999
|
+
}
|
1000
|
+
Authorization::Engine.instance(reader)
|
869
1001
|
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
1002
|
+
test_model_1 = TestModel.create!
|
1003
|
+
test_model_2 = TestModel.create!
|
1004
|
+
test_model_1.test_attrs.create!(:attr => 1).test_attr_throughs.create!
|
1005
|
+
test_model_1.test_attrs.create!(:attr => 2).test_attr_throughs.create!
|
1006
|
+
test_model_2.test_attrs.create!(:attr => 1).test_attr_throughs.create!
|
1007
|
+
test_model_2.test_attrs.create!(:attr => 2).test_attr_throughs.create!
|
876
1008
|
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
1009
|
+
#assert_equal 1, test_model_1.test_attrs_with_attr.length
|
1010
|
+
user = MockUser.new(:test_role,
|
1011
|
+
:id => test_model_1.test_attr_throughs.first.id)
|
1012
|
+
assert_equal 1, TestModel.with_permissions_to(:read, :user => user).length
|
1013
|
+
user = MockUser.new(:test_role,
|
1014
|
+
:id => test_model_1.test_attr_throughs.last.id)
|
1015
|
+
assert_equal 0, TestModel.with_permissions_to(:read, :user => user).length
|
884
1016
|
|
885
|
-
|
886
|
-
|
887
|
-
|
1017
|
+
TestModel.delete_all
|
1018
|
+
TestAttr.delete_all
|
1019
|
+
TestAttrThrough.delete_all
|
1020
|
+
end
|
888
1021
|
end
|
889
1022
|
|
890
1023
|
def test_with_is_in
|
@@ -1504,7 +1637,9 @@ class ModelTest < Test::Unit::TestCase
|
|
1504
1637
|
assert_nothing_raised do
|
1505
1638
|
object.update_attributes(:attr_2 => 2)
|
1506
1639
|
end
|
1507
|
-
|
1640
|
+
without_access_control do
|
1641
|
+
object.reload
|
1642
|
+
end
|
1508
1643
|
assert_equal 2, object.attr_2
|
1509
1644
|
object.destroy
|
1510
1645
|
assert_raise ActiveRecord::RecordNotFound do
|
@@ -1539,7 +1674,9 @@ class ModelTest < Test::Unit::TestCase
|
|
1539
1674
|
test_model.update_attributes(params[:model_data])
|
1540
1675
|
end
|
1541
1676
|
end
|
1542
|
-
|
1677
|
+
without_access_control do
|
1678
|
+
assert_equal params[:model_data][:attr], test_model.reload.attr
|
1679
|
+
end
|
1543
1680
|
|
1544
1681
|
TestAttr.delete_all
|
1545
1682
|
TestModelSecurityModel.delete_all
|
@@ -1669,3 +1806,4 @@ class ModelTest < Test::Unit::TestCase
|
|
1669
1806
|
assert !allowed_read_company.permitted_to?(:update, :user => user)
|
1670
1807
|
end
|
1671
1808
|
end
|
1809
|
+
|