mongoid_ability 0.0.11 → 0.1.0
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.
- checksums.yaml +4 -4
- data/README.md +18 -13
- data/lib/mongoid_ability.rb +8 -2
- data/lib/mongoid_ability/ability.rb +32 -30
- data/lib/mongoid_ability/accessible_query_builder.rb +61 -41
- data/lib/mongoid_ability/lock.rb +16 -29
- data/lib/mongoid_ability/owner.rb +6 -22
- data/lib/mongoid_ability/resolve_default_locks.rb +15 -0
- data/lib/mongoid_ability/resolve_inherited_locks.rb +32 -0
- data/lib/mongoid_ability/resolve_locks.rb +34 -0
- data/lib/mongoid_ability/resolve_owner_locks.rb +25 -0
- data/lib/mongoid_ability/subject.rb +28 -32
- data/lib/mongoid_ability/version.rb +1 -1
- data/test/mongoid_ability/ability_role_test.rb +11 -5
- data/test/mongoid_ability/ability_test.rb +67 -91
- data/test/mongoid_ability/accessible_query_builder_test.rb +9 -5
- data/test/mongoid_ability/can_options_test.rb +17 -0
- data/test/mongoid_ability/lock_test.rb +51 -70
- data/test/mongoid_ability/owner_locks_test.rb +42 -0
- data/test/mongoid_ability/owner_test.rb +12 -39
- data/test/mongoid_ability/resolve_default_locks_test.rb +27 -0
- data/test/mongoid_ability/resolve_inherited_locks_test.rb +49 -0
- data/test/mongoid_ability/resolve_locks_test.rb +25 -0
- data/test/mongoid_ability/resolve_owner_locks_test.rb +50 -0
- data/test/mongoid_ability/subject_accessible_by_test.rb +135 -0
- data/test/mongoid_ability/subject_test.rb +20 -201
- data/test/support/test_classes.rb +136 -61
- data/test/test_helper.rb +3 -2
- metadata +20 -5
- data/lib/mongoid_ability/ability_resolver.rb +0 -42
- data/test/mongoid_ability/ability_resolver_test.rb +0 -78
@@ -3,18 +3,22 @@ require "test_helper"
|
|
3
3
|
module MongoidAbility
|
4
4
|
describe AccessibleQueryBuilder do
|
5
5
|
|
6
|
-
let(:base_class) {
|
7
|
-
|
8
|
-
let(:
|
9
|
-
let(:ability) { Ability.new(
|
6
|
+
let(:base_class) { MySubject }
|
7
|
+
|
8
|
+
let(:owner) { MyOwner.new }
|
9
|
+
let(:ability) { Ability.new(owner) }
|
10
10
|
|
11
11
|
let(:action) { :read }
|
12
12
|
|
13
13
|
subject { AccessibleQueryBuilder.call(base_class, ability, action) }
|
14
14
|
|
15
|
+
before do
|
16
|
+
MySubject.default_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: false) ]
|
17
|
+
end
|
18
|
+
|
15
19
|
it 'returns Mongoid::Criteria' do
|
16
20
|
subject.must_be_kind_of Mongoid::Criteria
|
17
21
|
end
|
18
22
|
|
19
23
|
end
|
20
|
-
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MongoidAbility
|
4
|
+
describe 'can options test' do
|
5
|
+
let(:owner) { MyOwner.new }
|
6
|
+
let(:ability) { Ability.new(owner) }
|
7
|
+
|
8
|
+
before do
|
9
|
+
MySubject.default_locks = [ MyLock1.new(action: :read, outcome: false) ]
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'allows to pass options to a can? block' do
|
13
|
+
ability.can?(:read, MySubject, {}).must_equal false
|
14
|
+
ability.can?(:read, MySubject, { override: true }).must_equal true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -3,92 +3,73 @@ require 'test_helper'
|
|
3
3
|
module MongoidAbility
|
4
4
|
describe Lock do
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# =====================================================================
|
10
|
-
|
11
|
-
describe 'fields' do
|
12
|
-
it 'has :action' do
|
13
|
-
subject.must_respond_to :action
|
14
|
-
subject.action.must_be_kind_of Symbol
|
15
|
-
end
|
6
|
+
subject { MyLock.new }
|
7
|
+
let(:my_subject) { MySubject.new }
|
8
|
+
let(:inherited_lock) { MyLock1.new }
|
16
9
|
|
17
|
-
|
18
|
-
subject.must_respond_to :outcome
|
19
|
-
subject.outcome.must_equal false
|
20
|
-
end
|
21
|
-
end
|
10
|
+
# ---------------------------------------------------------------------
|
22
11
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
12
|
+
it { subject.must_respond_to :action }
|
13
|
+
it { subject.must_respond_to :outcome }
|
14
|
+
it { subject.must_respond_to :subject }
|
15
|
+
it { subject.must_respond_to :subject_id }
|
16
|
+
it { subject.must_respond_to :subject_type }
|
17
|
+
it { subject.must_respond_to :owner }
|
30
18
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
19
|
+
# ---------------------------------------------------------------------
|
20
|
+
|
21
|
+
it '#open?' do
|
22
|
+
subject.must_respond_to :open?
|
23
|
+
subject.open?.must_equal false
|
24
|
+
end
|
25
|
+
it '#closed?' do
|
26
|
+
subject.must_respond_to :closed?
|
27
|
+
subject.closed?.must_equal true
|
28
|
+
end
|
29
|
+
it '#class_lock?' do
|
30
|
+
subject.must_respond_to :class_lock?
|
31
|
+
end
|
32
|
+
it '#id_lock?' do
|
33
|
+
subject.must_respond_to :id_lock?
|
36
34
|
end
|
37
|
-
|
38
|
-
# =====================================================================
|
39
35
|
|
40
|
-
|
41
|
-
it 'has #open?' do
|
42
|
-
subject.must_respond_to :open?
|
43
|
-
subject.open?.must_equal false
|
44
|
-
end
|
45
|
-
it 'has #closed?' do
|
46
|
-
subject.must_respond_to :closed?
|
47
|
-
subject.closed?.must_equal true
|
48
|
-
end
|
49
|
-
it 'has #class_lock?' do
|
50
|
-
subject.must_respond_to :class_lock?
|
51
|
-
end
|
52
|
-
it 'has #id_lock?' do
|
53
|
-
subject.must_respond_to :id_lock?
|
54
|
-
end
|
36
|
+
# ---------------------------------------------------------------------
|
55
37
|
|
56
|
-
|
57
|
-
|
58
|
-
|
38
|
+
describe '#criteria' do
|
39
|
+
let(:open_subject_type_lock) { MyLock.new(subject_type: MySubject, action: :read, outcome: true) }
|
40
|
+
let(:closed_subject_type_lock) { MyLock.new(subject_type: MySubject, action: :read, outcome: false) }
|
59
41
|
|
60
|
-
|
61
|
-
|
42
|
+
let(:open_subject_lock) { MyLock.new(subject: my_subject, action: :read, outcome: true) }
|
43
|
+
let(:closed_subject_lock) { MyLock.new(subject: my_subject, action: :read, outcome: false) }
|
62
44
|
|
63
|
-
|
64
|
-
|
65
|
-
|
45
|
+
it 'returns conditions Hash' do
|
46
|
+
open_subject_type_lock.conditions.must_be_kind_of Hash
|
47
|
+
closed_subject_type_lock.conditions.must_be_kind_of Hash
|
66
48
|
|
67
|
-
|
68
|
-
|
69
|
-
|
49
|
+
open_subject_lock.conditions.must_be_kind_of Hash
|
50
|
+
closed_subject_lock.conditions.must_be_kind_of Hash
|
51
|
+
end
|
70
52
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
53
|
+
describe 'when open' do
|
54
|
+
it 'includes subject_type' do
|
55
|
+
open_subject_type_lock.conditions.must_equal({ _type: open_subject_type_lock.subject_type })
|
56
|
+
end
|
75
57
|
|
76
|
-
|
77
|
-
|
78
|
-
end
|
58
|
+
it 'includes id' do
|
59
|
+
open_subject_lock.conditions.must_equal({ _type: open_subject_type_lock.subject_type, _id: open_subject_lock.subject_id })
|
79
60
|
end
|
61
|
+
end
|
80
62
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
63
|
+
describe 'when closed' do
|
64
|
+
it 'excludes subject_type' do
|
65
|
+
closed_subject_type_lock.conditions.must_equal({ '$not' => { _type: open_subject_type_lock.subject_type }})
|
66
|
+
end
|
85
67
|
|
86
|
-
|
87
|
-
|
88
|
-
end
|
68
|
+
it 'includes id' do
|
69
|
+
closed_subject_lock.conditions.must_equal({ '$not' => { _type: open_subject_type_lock.subject_type, _id: open_subject_lock.subject_id }})
|
89
70
|
end
|
90
71
|
end
|
91
72
|
end
|
92
73
|
|
93
74
|
end
|
94
|
-
end
|
75
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MongoidAbility
|
4
|
+
describe 'owner locks test' do
|
5
|
+
subject { MySubject.new }
|
6
|
+
|
7
|
+
let(:subject_lock) { MyLock.new(action: :read, subject: subject, outcome: false) }
|
8
|
+
let(:subject_type_lock) { MyLock.new(action: :read, subject_type: subject.class, outcome: false) }
|
9
|
+
|
10
|
+
let(:owner) { MyOwner.new }
|
11
|
+
let(:ability) { Ability.new(owner) }
|
12
|
+
|
13
|
+
# ---------------------------------------------------------------------
|
14
|
+
|
15
|
+
before do
|
16
|
+
MySubject.default_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: true) ]
|
17
|
+
end
|
18
|
+
|
19
|
+
# ---------------------------------------------------------------------
|
20
|
+
|
21
|
+
describe 'when lock for subject' do
|
22
|
+
before { owner.my_locks = [ subject_lock ] }
|
23
|
+
|
24
|
+
it 'applies it' do
|
25
|
+
ability.can?(:read, subject.class).must_equal true
|
26
|
+
ability.can?(:read, subject).must_equal false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# ---------------------------------------------------------------------
|
31
|
+
|
32
|
+
describe 'when lock for subject type' do
|
33
|
+
before { owner.my_locks = [ subject_type_lock ] }
|
34
|
+
|
35
|
+
it 'applies it' do
|
36
|
+
ability.can?(:read, subject.class).must_equal false
|
37
|
+
ability.can?(:read, subject).must_equal false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -2,52 +2,25 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
module MongoidAbility
|
4
4
|
describe Owner do
|
5
|
+
subject { MyOwner.new }
|
5
6
|
|
6
|
-
|
7
|
+
describe '#cleanup_locks' do
|
8
|
+
let(:closed_lock) { MyLock.new(action: :read, outcome: false, subject_type: Object.to_s) }
|
9
|
+
let(:open_lock) { MyLock1.new(action: :read, outcome: true, subject_type: Object.to_s) }
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
# =====================================================================
|
14
|
-
|
15
|
-
describe 'associations' do
|
16
|
-
end
|
17
|
-
|
18
|
-
# =====================================================================
|
19
|
-
|
20
|
-
describe 'class methods' do
|
21
|
-
describe 'lock_class_name' do
|
22
|
-
it 'finds class that includes the MongoidAbility::Lock module' do
|
23
|
-
TestOwner.lock_class_name.must_equal 'TestLock'
|
24
|
-
end
|
11
|
+
before do
|
12
|
+
subject.my_locks = [open_lock, closed_lock].shuffle
|
13
|
+
subject.run_callbacks(:save)
|
25
14
|
end
|
26
15
|
|
27
|
-
|
28
|
-
|
29
|
-
TestOwner.locks_relation_name.must_equal :test_locks
|
30
|
-
end
|
16
|
+
it 'prefers closed locks' do
|
17
|
+
subject.my_locks.sort.must_equal [closed_lock].sort
|
31
18
|
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# =====================================================================
|
35
19
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
let(:open_lock) { TestLock.new(action: :read, outcome: true, subject_type: Object.to_s) }
|
40
|
-
|
41
|
-
before do
|
42
|
-
subject.test_locks = [open_lock, closed_lock].shuffle
|
43
|
-
subject.run_callbacks(:save)
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'prefers closed locks' do
|
47
|
-
subject.test_locks.sort.must_equal [closed_lock].sort
|
48
|
-
end
|
20
|
+
describe 'locks relation' do
|
21
|
+
it { subject.class.locks_relation_name.must_equal :my_locks }
|
22
|
+
it { subject.locks_relation.metadata[:name].must_equal :my_locks }
|
49
23
|
end
|
50
24
|
end
|
51
|
-
|
52
25
|
end
|
53
26
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
module MongoidAbility
|
4
|
+
describe ResolveDefaultLocks do
|
5
|
+
|
6
|
+
describe '.call' do
|
7
|
+
before do
|
8
|
+
MySubject.default_locks = [
|
9
|
+
MyLock.new(subject_type: MySubject, action: :read, outcome: true),
|
10
|
+
MyLock.new(subject_type: MySubject, action: :update, outcome: false)
|
11
|
+
]
|
12
|
+
|
13
|
+
MySubject1.default_locks = [
|
14
|
+
MyLock.new(subject_type: MySubject1, action: :read, outcome: false),
|
15
|
+
MyLock.new(subject_type: MySubject1, action: :update, outcome: true)
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
it { ResolveDefaultLocks.call(nil, :read, MySubject, nil, {}).must_equal true }
|
20
|
+
it { ResolveDefaultLocks.call(nil, :update, MySubject, nil, {}).must_equal false }
|
21
|
+
|
22
|
+
it { ResolveDefaultLocks.call(nil, :read, MySubject1, nil, {}).must_equal false }
|
23
|
+
it { ResolveDefaultLocks.call(nil, :update, MySubject1, nil, {}).must_equal true }
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
module MongoidAbility
|
4
|
+
describe ResolveInheritedLocks do
|
5
|
+
|
6
|
+
describe 'when defined on class' do
|
7
|
+
let(:owner) { MyOwner.new }
|
8
|
+
let(:my_subject) { MySubject.new }
|
9
|
+
|
10
|
+
before { MySubject.default_locks = [ MyLock.new(subject_type: MySubject, action: :my_read, outcome: true) ] }
|
11
|
+
|
12
|
+
# ---------------------------------------------------------------------
|
13
|
+
|
14
|
+
it 'returns it' do
|
15
|
+
ResolveInheritedLocks.call(owner, :my_read, MySubject, nil).must_equal true
|
16
|
+
ResolveInheritedLocks.call(owner, :my_read, MySubject, my_subject).must_equal true
|
17
|
+
end
|
18
|
+
|
19
|
+
# ---------------------------------------------------------------------
|
20
|
+
|
21
|
+
describe 'when defined on one of the inherited owners' do
|
22
|
+
let(:inherited_owner_1) { MyOwner.new }
|
23
|
+
let(:inherited_owner_2) { MyOwner.new }
|
24
|
+
let(:owner) { MyOwner.new(my_roles: [inherited_owner_1, inherited_owner_2]) }
|
25
|
+
let(:my_subject) { MySubject.new }
|
26
|
+
|
27
|
+
before { inherited_owner_1.my_locks = [ MyLock.new(action: :my_read, subject_type: MySubject, outcome: false) ] }
|
28
|
+
|
29
|
+
it 'returns it' do
|
30
|
+
ResolveInheritedLocks.call(owner, :my_read, MySubject, nil).must_equal false
|
31
|
+
ResolveInheritedLocks.call(owner, :my_read, MySubject, my_subject).must_equal false
|
32
|
+
end
|
33
|
+
|
34
|
+
# ---------------------------------------------------------------------
|
35
|
+
|
36
|
+
describe 'when defined on user' do
|
37
|
+
before { owner.my_locks = [ MyLock.new(action: :my_read, subject_type: MySubject, outcome: true) ] }
|
38
|
+
|
39
|
+
it 'returns it' do
|
40
|
+
ResolveInheritedLocks.call(owner, :my_read, MySubject, nil).must_equal true
|
41
|
+
ResolveInheritedLocks.call(owner, :my_read, MySubject, my_subject).must_equal true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module MongoidAbility
|
4
|
+
describe ResolveLocks do
|
5
|
+
|
6
|
+
let(:owner) { MyOwner.new }
|
7
|
+
|
8
|
+
describe 'errors' do
|
9
|
+
it 'raises NameError for invalid subject_type' do
|
10
|
+
-> { ResolveLocks.call(owner, :read, 'Foo') }.must_raise NameError
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'raises StandardError when subject_type does not have default_locks' do
|
14
|
+
-> { ResolveLocks.call(owner, :read, Object) }.must_raise StandardError
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'raises StandardError when subject_type class or its ancestors does not have default_lock' do
|
18
|
+
MySubject.stub(:default_locks, []) do
|
19
|
+
-> { ResolveLocks.call(owner, :read, MySubject) }.must_raise StandardError
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
module MongoidAbility
|
4
|
+
describe ResolveOwnerLocks do
|
5
|
+
let(:owner) { MyOwner.new }
|
6
|
+
let(:my_subject) { MySubject.new }
|
7
|
+
|
8
|
+
subject { ResolveOwnerLocks.call(owner, :read, MySubject, nil) }
|
9
|
+
let(:resolver_for_subject_id) { ResolveOwnerLocks.call(owner, :read, MySubject, my_subject) }
|
10
|
+
|
11
|
+
# =====================================================================
|
12
|
+
|
13
|
+
describe '#outcome' do
|
14
|
+
before do
|
15
|
+
MySubject.default_locks = [ MyLock.new(subject_type: MySubject, action: :read, outcome: false) ]
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'no locks' do
|
19
|
+
it { subject.must_be_nil }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'id locks' do
|
23
|
+
it 'returns outcome' do
|
24
|
+
owner.my_locks = [ MyLock.new(action: :read, subject: my_subject, outcome: true) ]
|
25
|
+
resolver_for_subject_id.must_equal true
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'prefers negative outcome' do
|
29
|
+
owner.my_locks = [ MyLock.new(action: :read, subject: my_subject, outcome: true),
|
30
|
+
MyLock.new(action: :read, subject: my_subject, outcome: false) ]
|
31
|
+
resolver_for_subject_id.must_equal false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'class locks' do
|
36
|
+
it 'returns outcome' do
|
37
|
+
owner.my_locks = [ MyLock.new(action: :read, subject_type: MySubject, outcome: true) ]
|
38
|
+
subject.must_equal true
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'prefers negative outcome' do
|
42
|
+
owner.my_locks = [ MyLock.new(action: :read, subject_type: MySubject, outcome: true),
|
43
|
+
MyLock.new(action: :read, subject_type: MySubject, outcome: false) ]
|
44
|
+
subject.must_equal false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|