annotation_security 1.0.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/CHANGELOG +2 -0
- data/HOW-TO +261 -0
- data/MIT-LICENSE +18 -0
- data/README +39 -0
- data/Rakefile +56 -0
- data/assets/app/helpers/annotation_security_helper.rb +9 -0
- data/assets/config/initializers/annotation_security.rb +12 -0
- data/assets/config/security/relations.rb +20 -0
- data/assets/config/security/rights.yml +16 -0
- data/assets/vendor/plugins/annotation_security/init.rb +14 -0
- data/bin/annotation_security +8 -0
- data/lib/annotation_security/exceptions.rb +125 -0
- data/lib/annotation_security/exec.rb +189 -0
- data/lib/annotation_security/filters.rb +38 -0
- data/lib/annotation_security/includes/action_controller.rb +144 -0
- data/lib/annotation_security/includes/active_record.rb +28 -0
- data/lib/annotation_security/includes/helper.rb +215 -0
- data/lib/annotation_security/includes/resource.rb +85 -0
- data/lib/annotation_security/includes/role.rb +31 -0
- data/lib/annotation_security/includes/user.rb +27 -0
- data/lib/annotation_security/manager/policy_factory.rb +30 -0
- data/lib/annotation_security/manager/policy_manager.rb +80 -0
- data/lib/annotation_security/manager/relation_loader.rb +273 -0
- data/lib/annotation_security/manager/resource_manager.rb +36 -0
- data/lib/annotation_security/manager/right_loader.rb +88 -0
- data/lib/annotation_security/model_observer.rb +61 -0
- data/lib/annotation_security/policy/abstract_policy.rb +345 -0
- data/lib/annotation_security/policy/abstract_static_policy.rb +76 -0
- data/lib/annotation_security/policy/all_resources_policy.rb +21 -0
- data/lib/annotation_security/policy/rule.rb +340 -0
- data/lib/annotation_security/policy/rule_set.rb +139 -0
- data/lib/annotation_security/rails.rb +39 -0
- data/lib/annotation_security/user_wrapper.rb +74 -0
- data/lib/annotation_security/utils.rb +142 -0
- data/lib/annotation_security.rb +98 -0
- data/lib/extensions/action_controller.rb +33 -0
- data/lib/extensions/active_record.rb +35 -0
- data/lib/extensions/filter.rb +134 -0
- data/lib/extensions/object.rb +11 -0
- data/lib/security_context.rb +551 -0
- data/spec/annotation_security/exceptions_spec.rb +17 -0
- data/spec/annotation_security/includes/helper_spec.rb +82 -0
- data/spec/annotation_security/manager/policy_manager_spec.rb +15 -0
- data/spec/annotation_security/manager/resource_manager_spec.rb +17 -0
- data/spec/annotation_security/manager/right_loader_spec.rb +17 -0
- data/spec/annotation_security/policy/abstract_policy_spec.rb +17 -0
- data/spec/annotation_security/policy/all_resources_policy_spec.rb +24 -0
- data/spec/annotation_security/policy/rule_set_spec.rb +112 -0
- data/spec/annotation_security/policy/rule_spec.rb +78 -0
- data/spec/annotation_security/policy/test_policy_spec.rb +81 -0
- data/spec/annotation_security/security_context_spec.rb +78 -0
- data/spec/annotation_security/utils_spec.rb +74 -0
- data/spec/helper/test_controller.rb +66 -0
- data/spec/helper/test_helper.rb +5 -0
- data/spec/helper/test_relations.rb +7 -0
- data/spec/helper/test_resource.rb +39 -0
- data/spec/helper/test_rights.yml +5 -0
- data/spec/helper/test_role.rb +22 -0
- data/spec/helper/test_user.rb +32 -0
- data/spec/rails_stub.rb +38 -0
- data/spec/spec_helper.rb +43 -0
- metadata +157 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe AnnotationSecurity::AbstractPolicy do
|
4
|
+
# For more tests see test_policy_spec.rb
|
5
|
+
|
6
|
+
it 'should create a subclass for a resource type' do
|
7
|
+
klass = AnnotationSecurity::AbstractPolicy.new_subclass(:abs_policy_test)
|
8
|
+
(defined? AbsPolicyTestPolicy).should_not be_nil
|
9
|
+
klass.should eql(AbsPolicyTestPolicy)
|
10
|
+
klass.static?.should be_false
|
11
|
+
|
12
|
+
(defined? AbsPolicyTestStaticPolicy).should_not be_nil
|
13
|
+
klass.static_policy_class.should eql(AbsPolicyTestStaticPolicy)
|
14
|
+
klass.static_policy_class.static?.should be_true
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe AllResourcesPolicy do
|
4
|
+
|
5
|
+
it 'should provide :__self__ relation' do
|
6
|
+
user = TestUser.new
|
7
|
+
user2 = TestUser.new
|
8
|
+
policy = AllResourcesPolicy.new(user)
|
9
|
+
policy.with_resource(user).__self__?.should be_true
|
10
|
+
policy.with_resource(user.as_one_role).__self__?.should be_true
|
11
|
+
policy.with_resource(user2).__self__?.should be_false
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should provide :logged_in relation' do
|
15
|
+
AllResourcesPolicy.new(TestUser.new).logged_in?.should be_true
|
16
|
+
AllResourcesPolicy.new(nil).logged_in?.should be_false
|
17
|
+
|
18
|
+
AllResourcesPolicy.has_static_rule?(:logged_in).should be_true
|
19
|
+
AllResourcesPolicy.has_dynamic_rule?(:logged_in).should be_false
|
20
|
+
rule = AllResourcesPolicy.rule_set.get_static_rule(:logged_in)
|
21
|
+
rule.requires_credential?.should be_false
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe AnnotationSecurity::RuleSet do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
AnnotationSecurity.define_relations(:rule_set_test,:rule_set_test2) do
|
7
|
+
sys_relation :system, "true"
|
8
|
+
res_relation :resource, "true"
|
9
|
+
pre_relation :pretest, "true"
|
10
|
+
end
|
11
|
+
# This rule set is not to be modified during the tests!
|
12
|
+
@rule_set2 = RuleSetTest2Policy.rule_set
|
13
|
+
end
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
# Use a fresh rule set for each test.
|
17
|
+
# This will break some functions of RuleSet,
|
18
|
+
# in these cases @rule_set2 is used for testing.
|
19
|
+
@rule_set = AnnotationSecurity::RuleSet.new(RuleSetTestPolicy)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should have a self explaining name' do
|
23
|
+
@rule_set.to_s.should eql('<RuleSet of RuleSetTestPolicy>')
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should manage static relations' do
|
27
|
+
rule = @rule_set.add_rule(:sys_relation, :system) { true }
|
28
|
+
rule.should be_instance_of(AnnotationSecurity::Rule)
|
29
|
+
@rule_set.get_rule(:sys_relation, true).should eql(rule)
|
30
|
+
@rule_set.get_rule(:sys_relation, false).should be_nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should manage dynamic relations' do
|
34
|
+
rule = @rule_set.add_rule(:res_relation, :resource) { true }
|
35
|
+
rule.should be_instance_of(AnnotationSecurity::Rule)
|
36
|
+
@rule_set.get_rule(:res_relation, false).should eql(rule)
|
37
|
+
@rule_set.get_rule(:res_relation, true).should be_nil
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should manage pretest relations' do
|
41
|
+
rule = @rule_set.add_rule(:pre_relation, :pretest) { true }
|
42
|
+
rule.should be_instance_of(AnnotationSecurity::Rule)
|
43
|
+
@rule_set.get_rule(:pre_relation, true).should eql(rule)
|
44
|
+
@rule_set.get_rule(:pre_relation, false).should eql(rule)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should manage dynamic rights' do
|
48
|
+
rule = @rule_set.add_rule(:res_right, :right, "if res_relation")
|
49
|
+
rule.should be_instance_of(AnnotationSecurity::Rule)
|
50
|
+
@rule_set.get_rule(:res_right,false).should eql(rule)
|
51
|
+
@rule_set.get_rule(:res_right,true).should be_nil
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should manage static rights' do
|
55
|
+
rule = @rule_set.add_rule(:sys_right, :right, "if sys_relation")
|
56
|
+
rule.should be_instance_of(AnnotationSecurity::Rule)
|
57
|
+
@rule_set.get_rule(:sys_right,true).should eql(rule)
|
58
|
+
@rule_set.get_rule(:sys_right,false).should be_nil
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should manage pretest rights' do
|
62
|
+
rule = @rule_set.add_rule(:pre_right, :right, "if pre_relation")
|
63
|
+
rule.should be_instance_of(AnnotationSecurity::Rule)
|
64
|
+
@rule_set.get_rule(:pre_right,true).should eql(rule)
|
65
|
+
@rule_set.get_rule(:pre_right,false).should eql(rule)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should be able to copy dynamic rules from other rule sets' do
|
69
|
+
rule = @rule_set.copy_rule_from(:res_relation, @rule_set2, false)
|
70
|
+
rule.should be_instance_of(AnnotationSecurity::Rule)
|
71
|
+
@rule_set.get_rule(:res_relation, false).should eql(rule)
|
72
|
+
@rule_set2.get_rule(:res_relation, false).should_not eql(rule)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should not create dynamic copies of static rules from other rule sets' do
|
76
|
+
rule = @rule_set.copy_rule_from(:sys_relation, @rule_set2, false)
|
77
|
+
rule.should be_nil
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should be able to copy static rules from other rule sets' do
|
81
|
+
rule = @rule_set.copy_rule_from(:sys_relation, @rule_set2, true)
|
82
|
+
rule.should be_instance_of(AnnotationSecurity::Rule)
|
83
|
+
@rule_set.get_rule(:sys_relation, true).should eql(rule)
|
84
|
+
@rule_set2.get_rule(:sys_relation, true).should_not eql(rule)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should not create static copies of dynamic rules from other rule sets' do
|
88
|
+
rule = @rule_set.copy_rule_from(:res_relation, @rule_set2, true)
|
89
|
+
rule.should be_nil
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should not allow rules with forbidden names' do
|
93
|
+
lambda {
|
94
|
+
@rule_set.add_rule(:get_rule) { }
|
95
|
+
}.should raise_error(AnnotationSecurity::RuleError)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should not allow rules to be defined twice' do
|
99
|
+
@rule_set.add_rule(:test_rule) { }
|
100
|
+
lambda {
|
101
|
+
@rule_set.add_rule(:test_rule) { }
|
102
|
+
}.should raise_error(AnnotationSecurity::RuleError)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should allow rules to be defined both statically and dynamically' do
|
106
|
+
r1 = @rule_set.add_rule(:test_rule, :system) { }
|
107
|
+
r2 = @rule_set.add_rule(:test_rule, :resource) { }
|
108
|
+
@rule_set.get_rule(:test_rule,true).should eql(r1)
|
109
|
+
@rule_set.get_rule(:test_rule,false).should eql(r2)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe AnnotationSecurity::Rule do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
AnnotationSecurity.define_relations(:rule_test_res) do
|
7
|
+
res_dummy
|
8
|
+
sys_dummy(:system) { false }
|
9
|
+
pre_dummy :pretest
|
10
|
+
noc_dummy :system, :require_credential => false
|
11
|
+
|
12
|
+
res_dummy_test { has_res_dummy }
|
13
|
+
sys_dummy_test "if is_sys_dummy"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should create valid dynamic relations' do
|
18
|
+
rule = AnnotationSecurity::Rule.new(:res_proc, RuleTestResPolicy) { |u,r| true }
|
19
|
+
rule.to_s.should == '<RuleTestResPolicy#res_proc[--du]>'
|
20
|
+
rule = AnnotationSecurity::Rule.new(:res, RuleTestResPolicy, :resource)
|
21
|
+
rule.to_s.should == '<RuleTestResPolicy#res[--du]>'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should create valid static relations' do
|
25
|
+
rule = AnnotationSecurity::Rule.new(:sys_proc, RuleTestResPolicy, :system) { true }
|
26
|
+
rule.to_s.should == '<RuleTestResPolicy#sys_proc[-s-u]>'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should create valid pretest relations' do
|
30
|
+
rule = AnnotationSecurity::Rule.new(:pre_proc, RuleTestResPolicy, :pretest) { true }
|
31
|
+
rule.to_s.should == '<RuleTestResPolicy#pre_proc[-sdu]>'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should create valid relations without user' do
|
35
|
+
rule = AnnotationSecurity::Rule.new(:no_u, RuleTestResPolicy, :require_credential => false)
|
36
|
+
rule.to_s.should == '<RuleTestResPolicy#no_u[--d-]>'
|
37
|
+
rule = AnnotationSecurity::Rule.new(:no_u, RuleTestResPolicy,
|
38
|
+
:system, :require_credential => false)
|
39
|
+
rule.to_s.should == '<RuleTestResPolicy#no_u[-s--]>'
|
40
|
+
rule = AnnotationSecurity::Rule.new(:no_u, RuleTestResPolicy,
|
41
|
+
:pretest, :require_credential => false)
|
42
|
+
rule.to_s.should == '<RuleTestResPolicy#no_u[-sd-]>'
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should create valid rights' do
|
46
|
+
{
|
47
|
+
'if res_dummy' => '-du',
|
48
|
+
'if sys_dummy' => 's-u',
|
49
|
+
'if pre_dummy' => 'sdu',
|
50
|
+
'if res_dummy or sys_dummy' => '-du',
|
51
|
+
'if res_dummy or pre_dummy' => '-du',
|
52
|
+
'if sys_dummy or pre_dummy' => 'sdu',
|
53
|
+
'if noc_dummy' => 's--',
|
54
|
+
'if noc_dummy or sys_dummy' => 's-u',
|
55
|
+
'if noc_dummy or res_dummy' => '-du',
|
56
|
+
'if self' => '-du',
|
57
|
+
'if other_right: resource_property' => '-du',
|
58
|
+
'true' => 's--',
|
59
|
+
'false or nil' => 's--'
|
60
|
+
}.each_pair do |condition,flags|
|
61
|
+
right = AnnotationSecurity::Rule.new(:right, RuleTestResPolicy, :right, condition)
|
62
|
+
right.flag_s.should == 'r???'
|
63
|
+
right.static? # trigger lazy initialization
|
64
|
+
right.flag_s.should == 'r'+flags
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should call referred rules when being executed' do
|
69
|
+
policy = RuleTestResPolicy.new(:user,:res)
|
70
|
+
|
71
|
+
policy.expects(:res_dummy).returns(true)
|
72
|
+
policy.res_dummy_test.should be_true
|
73
|
+
|
74
|
+
policy.expects(:sys_dummy).returns(false)
|
75
|
+
policy.sys_dummy_test?.should be_false
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
AnnotationSecurity.define_relations(:a_test) do
|
4
|
+
sys_relation :system
|
5
|
+
res_relation :resource
|
6
|
+
pre_relation :pretest
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ATestPolicy do
|
10
|
+
|
11
|
+
it 'should be dynamic' do
|
12
|
+
ATestPolicy.static?.should be_false
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should have a static partner' do
|
16
|
+
ATestPolicy.static_policy_class.should eql(ATestStaticPolicy)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should know its resource type' do
|
20
|
+
ATestPolicy.resource_type.should eql(:a_test)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should have all rules' do
|
24
|
+
ATestPolicy.has_rule?(:sys_relation).should be_true
|
25
|
+
ATestPolicy.has_rule?(:res_relation).should be_true
|
26
|
+
ATestPolicy.has_rule?(:pre_relation).should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should be aware of the evaluation time of a rule' do
|
30
|
+
ATestPolicy.has_dynamic_rule?(:sys_relation).should be_false
|
31
|
+
ATestPolicy.has_dynamic_rule?(:res_relation).should be_true
|
32
|
+
ATestPolicy.has_dynamic_rule?(:pre_relation).should be_true
|
33
|
+
|
34
|
+
ATestPolicy.has_static_rule?(:sys_relation).should be_true
|
35
|
+
ATestPolicy.has_static_rule?(:res_relation).should be_false
|
36
|
+
ATestPolicy.has_static_rule?(:pre_relation).should be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should have access to rules defined for all resources' do
|
40
|
+
ATestPolicy.has_rule?(:__self__).should be_true
|
41
|
+
ATestPolicy.has_rule?(:logged_in).should be_true
|
42
|
+
end
|
43
|
+
#
|
44
|
+
# it 'should be possible to add rules'
|
45
|
+
#
|
46
|
+
# it 'should be possible to evaluate a list of rules (static/dynamic/both)'
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
describe ATestStaticPolicy do
|
51
|
+
|
52
|
+
it 'should be static' do
|
53
|
+
ATestStaticPolicy.static?.should be_true
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should not have a static partner' do
|
57
|
+
lambda {
|
58
|
+
ATestStaticPolicy.static_policy_class
|
59
|
+
}.should raise_error(NameError)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should know its resource type' do
|
63
|
+
ATestStaticPolicy.resource_type.should eql(:a_test)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should use the rule set of the dynamic policy' do
|
67
|
+
ATestStaticPolicy.rule_set.should eql(ATestPolicy.rule_set)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should have all static rules' do
|
71
|
+
ATestStaticPolicy.has_rule?(:sys_relation).should be_true
|
72
|
+
ATestStaticPolicy.has_rule?(:res_relation).should be_false
|
73
|
+
ATestStaticPolicy.has_rule?(:pre_relation).should be_true
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should have access to static rules defined for all resources' do
|
77
|
+
ATestStaticPolicy.has_rule?(:__self__).should be_false
|
78
|
+
ATestStaticPolicy.has_rule?(:logged_in).should be_true
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe SecurityContext do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@user1 = TestUser.new 'theuser'
|
7
|
+
@user2 = TestUser.new 'otheruser'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should check 'logged_in' for 'show'" do
|
11
|
+
request(@user1, :show, { :id => 'theuser' }).should succeed
|
12
|
+
request(@user2, :show, { :id => 'theuser' }).should succeed
|
13
|
+
request(nil, :show, { :id => 'theuser' }).should fail
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should check 'owner' for 'edit'" do
|
17
|
+
request(@user1, :edit, { :id => 'theuser' }).should succeed
|
18
|
+
request(@user2, :edit, { :id => 'theuser' }).should fail
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should check 'logged_in' and 'owner' for 'show_edit'" do
|
22
|
+
request(@user1, :show_edit, { :id => 'theuser' }).should succeed
|
23
|
+
request(@user2, :show_edit, { :id => 'theuser' }).should fail
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should check 'owner' for 'delete' based on :id" do
|
27
|
+
request(@user1, :delete, { :id => 'theuser' }).should succeed
|
28
|
+
request(@user2, :delete, { :id => 'theuser' }).should fail
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should not call action if check based on :id fails" do
|
32
|
+
TestController.expects(:enter_delete).never
|
33
|
+
request(@user2, :delete, { :id => 'theuser' }).should fail
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should check 'owner' for 'list' based on @list" do
|
37
|
+
request(@user1, :list, { :id1 => 'theuser', :id2 => 'theuser' }).should succeed
|
38
|
+
request(@user1, :list, { :id1 => 'theuser', :id2 => 'otheruser' }).should fail
|
39
|
+
request(@user1, :list, { :id1 => 'otheruser', :id2 => 'theuser' }).should fail
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should not be disturbed by calls to #render" do
|
43
|
+
TestController.expects(:exit_render).twice
|
44
|
+
request(@user1, :edit_with_render,
|
45
|
+
{ :id1 => 'theuser', :id2 => 'theuser' }).should succeed
|
46
|
+
request(@user1, :edit_with_render,
|
47
|
+
{ :id1 => 'theuser', :id2 => 'otheruser' }).should fail
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should check rules before #render" do
|
51
|
+
TestController.expects(:exit_render).never
|
52
|
+
request(@user1, :edit_with_render,
|
53
|
+
{ :id1 => 'otheruser', :id2 => 'theuser' }).should fail
|
54
|
+
end
|
55
|
+
|
56
|
+
# simulates an action invokation in rails
|
57
|
+
def request(user, action, params)
|
58
|
+
controller = TestController.new
|
59
|
+
controller.test_init(action, params)
|
60
|
+
SecurityContext.initialize(controller)
|
61
|
+
SecurityContext.credential = user
|
62
|
+
rules = controller.class.descriptions_of(action)
|
63
|
+
SecurityContext.current.send_with_security(rules, controller, action)
|
64
|
+
'no_error'
|
65
|
+
rescue SecurityViolationError => sve
|
66
|
+
sve
|
67
|
+
end
|
68
|
+
|
69
|
+
def succeed
|
70
|
+
eql 'no_error'
|
71
|
+
end
|
72
|
+
|
73
|
+
def fail
|
74
|
+
be_instance_of SecurityViolationError
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe AnnotationSecurity::Utils do
|
4
|
+
|
5
|
+
it 'should remove prefixes of the method body' do
|
6
|
+
%w{may_rule is_rule can_rule has_rule}.each do |method|
|
7
|
+
AnnotationSecurity::Utils.method_body(method).should eql('rule')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should remove suffixes of the method body' do
|
12
|
+
%w{rule_for rule_of rule_in rule_to rule?}.each do |method|
|
13
|
+
AnnotationSecurity::Utils.method_body(method).should eql('rule')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should return nil if the method body is clean' do
|
18
|
+
AnnotationSecurity::Utils.method_body('rule').should be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should ignore prefixes and suffixes without underscore in method body' do
|
22
|
+
%w{mayrule isrule rulefor ruleof canrulein hasruleto}.each do |method|
|
23
|
+
AnnotationSecurity::Utils.method_body(method).should eql(nil)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should remove only prefix or suffix from the method body at a time' do
|
28
|
+
AnnotationSecurity::Utils.method_body('may_is_rule').should eql('is_rule')
|
29
|
+
AnnotationSecurity::Utils.method_body('rule_of_for').should eql('rule_of')
|
30
|
+
AnnotationSecurity::Utils.method_body('can_has_rule_to?').should eql('has_rule_to')
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should parse descriptions without bindings correctly' do
|
34
|
+
['show a resource', 'show with some text ignored a resource',
|
35
|
+
'show pluralized resources', '(ignoring comments) show a resource',
|
36
|
+
'show a resource (with comment at the end)'].each do |s|
|
37
|
+
AnnotationSecurity::Utils.parse_description(s).
|
38
|
+
should == {:action => :show, :resource => :resource}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should detect bindings of a description' do
|
43
|
+
{
|
44
|
+
'show the resource in @res' =>
|
45
|
+
{:action => :show,:resource => :resource, :source => '@res'},
|
46
|
+
'show the resource from :id' =>
|
47
|
+
{:action => :show,:resource => :resource, :source => :id},
|
48
|
+
}.each_pair do |key, value|
|
49
|
+
AnnotationSecurity::Utils.parse_description(key,true).should == value
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should raise an error if an unexpected binding is detected in a description' do
|
54
|
+
lambda {
|
55
|
+
AnnotationSecurity::Utils.parse_description('show the resource :id')
|
56
|
+
}.should raise_error(StandardError)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should parse policy arguments like specified in SecurityContext.allowed?' do
|
60
|
+
obj = Object.new
|
61
|
+
def obj.__is_resource?; true; end
|
62
|
+
def obj.resource_type; :o_resource; end
|
63
|
+
{
|
64
|
+
[:show, :resource, obj] => [:show, :resource, obj],
|
65
|
+
[:show, obj] => [:show, :o_resource, obj],
|
66
|
+
['show resource', obj] => [:show, :resource, obj],
|
67
|
+
[:show, :resource] => [:show, :resource],
|
68
|
+
[:administrate] => [:administrate, :all_resources]
|
69
|
+
}.each_pair do |key, value|
|
70
|
+
AnnotationSecurity::Utils.parse_policy_arguments(key).should == value
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class TestController < ActionController::Base
|
2
|
+
|
3
|
+
describe :show, 'shows a test_resource'
|
4
|
+
describe :edit, 'edit some test_resources'
|
5
|
+
describe :show_edit, 'shows a test_resource', 'edits a test_resource'
|
6
|
+
describe :edit_with_render, 'edits the test_resource in @resource'
|
7
|
+
describe :delete, 'delete test_resource by :id'
|
8
|
+
describe :list, 'list all test_resources in @list'
|
9
|
+
|
10
|
+
|
11
|
+
def test_init(action, params)
|
12
|
+
@action = action
|
13
|
+
@params = params
|
14
|
+
end
|
15
|
+
|
16
|
+
def action_name
|
17
|
+
@action
|
18
|
+
end
|
19
|
+
|
20
|
+
def params
|
21
|
+
@params
|
22
|
+
end
|
23
|
+
|
24
|
+
def show
|
25
|
+
@resource = TestResource.find params[:id]
|
26
|
+
end
|
27
|
+
|
28
|
+
def edit
|
29
|
+
@resource = TestResource.find params[:id]
|
30
|
+
end
|
31
|
+
|
32
|
+
def show_edit
|
33
|
+
@resource = TestResource.find params[:id]
|
34
|
+
end
|
35
|
+
|
36
|
+
def edit_with_render
|
37
|
+
@resource = TestResource.find params[:id1]
|
38
|
+
render 'view'
|
39
|
+
@resource = TestResource.find params[:id2]
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete
|
43
|
+
self.class.enter_delete
|
44
|
+
@resource = TestResource.find params[:id]
|
45
|
+
end
|
46
|
+
|
47
|
+
def list
|
48
|
+
r1 = TestResource.find params[:id1]
|
49
|
+
r2 = TestResource.find params[:id2]
|
50
|
+
@list = [r1, r2]
|
51
|
+
end
|
52
|
+
|
53
|
+
def render(*args)
|
54
|
+
super(*args)
|
55
|
+
self.class.exit_render
|
56
|
+
end
|
57
|
+
|
58
|
+
# callbacks used for mocking
|
59
|
+
|
60
|
+
def self.enter_delete
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.exit_render
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class TestResource
|
2
|
+
|
3
|
+
include AnnotationSecurity::Resource
|
4
|
+
|
5
|
+
self.resource_type = :test_resource
|
6
|
+
|
7
|
+
def self.find(arg)
|
8
|
+
obj = new arg
|
9
|
+
|
10
|
+
# normally, this is done by a model observer
|
11
|
+
SecurityContext.observe obj
|
12
|
+
|
13
|
+
obj
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.get_resource(arg)
|
17
|
+
return nil if arg.nil?
|
18
|
+
return arg if arg.is_a? self
|
19
|
+
new arg
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(name = "")
|
23
|
+
@name = name
|
24
|
+
end
|
25
|
+
|
26
|
+
def name
|
27
|
+
@name
|
28
|
+
end
|
29
|
+
|
30
|
+
def ==(other)
|
31
|
+
return false unless other.is_a? self.class
|
32
|
+
name == other.name
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
"<TestResource:#{name}>"
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class TestUser
|
2
|
+
|
3
|
+
include AnnotationSecurity::User
|
4
|
+
|
5
|
+
def initialize(name='user_name')
|
6
|
+
@name = name
|
7
|
+
@one_role = TestRole.new(:one,self)
|
8
|
+
@many_roles = [
|
9
|
+
TestRole.new(:a,self), TestRole.new(:b,self), TestRole.new(:c,self)]
|
10
|
+
end
|
11
|
+
|
12
|
+
def user_name
|
13
|
+
@name
|
14
|
+
end
|
15
|
+
|
16
|
+
def name
|
17
|
+
user_name
|
18
|
+
end
|
19
|
+
|
20
|
+
def as_one_role
|
21
|
+
@one_role
|
22
|
+
end
|
23
|
+
|
24
|
+
def as_many_roles
|
25
|
+
@many_roles
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
"<TestUser:#{name}>"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/spec/rails_stub.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# AnnoationSecurity requires rails.
|
2
|
+
# Here are some stubs to simulate a rails environment for testing.
|
3
|
+
#
|
4
|
+
|
5
|
+
RAILS_ROOT = ''
|
6
|
+
RAILS_ENV = {}
|
7
|
+
|
8
|
+
class ConfigStub
|
9
|
+
def config
|
10
|
+
self
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ActiveRecord
|
15
|
+
class Observer
|
16
|
+
def self.observe(*args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module ActionController
|
22
|
+
class Base
|
23
|
+
def render(*args)
|
24
|
+
end
|
25
|
+
def redirect_to(*args)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
module Routing
|
29
|
+
class Routes
|
30
|
+
end
|
31
|
+
end
|
32
|
+
module Filters
|
33
|
+
class Filter
|
34
|
+
end
|
35
|
+
class AroundFilter < Filter
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|