mongoid_ability 1.0.0 → 2.0.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/CHANGELOG.md +4 -0
- data/Gemfile +7 -0
- data/README.md +55 -23
- data/lib/cancancan/model_adapters/mongoid_adapter.rb +156 -0
- data/lib/cancancan/model_additions.rb +30 -0
- data/lib/mongoid_ability.rb +12 -12
- data/lib/mongoid_ability/ability.rb +67 -26
- data/lib/mongoid_ability/find_lock.rb +71 -0
- data/lib/mongoid_ability/lock.rb +25 -16
- data/lib/mongoid_ability/locks_decorator.rb +45 -0
- data/lib/mongoid_ability/owner.rb +23 -3
- data/lib/mongoid_ability/subject.rb +10 -22
- data/lib/mongoid_ability/version.rb +1 -1
- data/test/cancancan/model_adapters/mongoid_adapter_options_test.rb +102 -0
- data/test/cancancan/model_adapters/mongoid_adapter_test.rb +207 -0
- data/test/mongoid_ability/ability_basic_benchmark.rb +30 -0
- data/test/mongoid_ability/ability_basic_test.rb +44 -13
- data/test/mongoid_ability/ability_marshal_test.rb +17 -0
- data/test/mongoid_ability/ability_options_test.rb +93 -0
- data/test/mongoid_ability/ability_test.rb +87 -106
- data/test/mongoid_ability/find_lock_test.rb +67 -0
- data/test/mongoid_ability/lock_test.rb +32 -40
- data/test/mongoid_ability/owner_locks_test.rb +14 -21
- data/test/mongoid_ability/owner_test.rb +4 -14
- data/test/mongoid_ability/subject_test.rb +32 -58
- data/test/support/test_classes/my_lock.rb +8 -13
- data/test/support/test_classes/my_owner.rb +13 -15
- data/test/support/test_classes/my_role.rb +9 -11
- data/test/support/test_classes/my_subject.rb +16 -9
- data/test/test_helper.rb +12 -2
- metadata +18 -25
- data/lib/mongoid_ability/accessible_query_builder.rb +0 -64
- data/lib/mongoid_ability/resolve_default_locks.rb +0 -17
- data/lib/mongoid_ability/resolve_inherited_locks.rb +0 -35
- data/lib/mongoid_ability/resolve_locks.rb +0 -12
- data/lib/mongoid_ability/resolve_owner_locks.rb +0 -35
- data/lib/mongoid_ability/resolver.rb +0 -24
- data/lib/mongoid_ability/values_for_accessible_query.rb +0 -74
- data/test/mongoid_ability/ability_syntactic_sugar_test.rb +0 -32
- data/test/mongoid_ability/accessible_query_builder_test.rb +0 -119
- data/test/mongoid_ability/can_options_test.rb +0 -17
- data/test/mongoid_ability/resolve_default_locks_test.rb +0 -41
- data/test/mongoid_ability/resolve_inherited_locks_test.rb +0 -50
- data/test/mongoid_ability/resolve_owner_locks_test.rb +0 -56
- data/test/mongoid_ability/resolver_test.rb +0 -23
- data/test/mongoid_ability/subject_accessible_by_test.rb +0 -147
@@ -1,17 +0,0 @@
|
|
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
|
-
let(:default_locks) { [MyLock1.new(action: :read, outcome: false)] }
|
9
|
-
|
10
|
-
it 'allows to pass options to a can? block' do
|
11
|
-
MySubject.stub :default_locks, default_locks do
|
12
|
-
ability.can?(:read, MySubject, {}).must_equal false
|
13
|
-
ability.can?(:read, MySubject, override: true).must_equal true
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
module MongoidAbility
|
4
|
-
describe ResolveDefaultLocks do
|
5
|
-
describe '.call' do
|
6
|
-
let(:options) { {} }
|
7
|
-
|
8
|
-
let(:my_subject_default_locks) do
|
9
|
-
[
|
10
|
-
MyLock.new(subject_type: MySubject, action: :read, outcome: true),
|
11
|
-
MyLock.new(subject_type: MySubject, action: :update, outcome: false)
|
12
|
-
]
|
13
|
-
end
|
14
|
-
|
15
|
-
let(:my_subject_1_default_locks) do
|
16
|
-
[
|
17
|
-
MyLock.new(subject_type: MySubject1, action: :read, outcome: false),
|
18
|
-
MyLock.new(subject_type: MySubject1, action: :update, outcome: true)
|
19
|
-
]
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'resolves on self' do
|
23
|
-
MySubject.stub :default_locks, my_subject_default_locks do
|
24
|
-
MySubject1.stub :default_locks, my_subject_1_default_locks do
|
25
|
-
ResolveDefaultLocks.call(nil, :read, MySubject, nil, options).must_equal MySubject.default_locks.first
|
26
|
-
ResolveDefaultLocks.call(nil, :update, MySubject, nil, options).must_equal MySubject.default_locks.last
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'resolves on subclass' do
|
32
|
-
MySubject.stub :default_locks, my_subject_default_locks do
|
33
|
-
MySubject1.stub :default_locks, my_subject_1_default_locks do
|
34
|
-
ResolveDefaultLocks.call(nil, :read, MySubject1, nil, options).must_equal MySubject1.default_locks.first
|
35
|
-
ResolveDefaultLocks.call(nil, :update, MySubject1, nil, options).must_equal MySubject1.default_locks.last
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
module MongoidAbility
|
4
|
-
describe ResolveInheritedLocks do
|
5
|
-
describe 'when defined on class' do
|
6
|
-
let(:owner) { MyOwner.new }
|
7
|
-
let(:my_subject) { MySubject.new }
|
8
|
-
|
9
|
-
let(:default_locks) { [MyLock.new(subject_type: MySubject, action: :my_read, outcome: true)] }
|
10
|
-
|
11
|
-
it 'returns it' do
|
12
|
-
MySubject.stub :default_locks, default_locks do
|
13
|
-
ResolveInheritedLocks.call(owner, :my_read, MySubject, nil).calculated_outcome.must_equal true
|
14
|
-
ResolveInheritedLocks.call(owner, :my_read, MySubject, my_subject).calculated_outcome.must_equal true
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
describe 'when defined on one of the inherited owners' do
|
19
|
-
let(:inherited_owner_1) { MyOwner.new }
|
20
|
-
let(:inherited_owner_2) { MyOwner.new }
|
21
|
-
let(:owner) { MyOwner.new(my_roles: [inherited_owner_1, inherited_owner_2]) }
|
22
|
-
let(:my_subject) { MySubject.new }
|
23
|
-
|
24
|
-
let(:lock) { MyLock.new(action: :my_read, subject_type: MySubject, outcome: false) }
|
25
|
-
|
26
|
-
before { inherited_owner_1.my_locks = [lock] }
|
27
|
-
|
28
|
-
it 'returns it' do
|
29
|
-
MySubject.stub :default_locks, default_locks do
|
30
|
-
ResolveInheritedLocks.call(owner, :my_read, MySubject, nil).must_equal lock
|
31
|
-
ResolveInheritedLocks.call(owner, :my_read, MySubject, my_subject.id).must_equal lock
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
describe 'when defined on user' do
|
36
|
-
let(:lock) { MyLock.new(action: :my_read, subject_type: MySubject, outcome: false) }
|
37
|
-
|
38
|
-
before { owner.my_locks = [lock] }
|
39
|
-
|
40
|
-
it 'returns it' do
|
41
|
-
MySubject.stub :default_locks, default_locks do
|
42
|
-
ResolveInheritedLocks.call(owner, :my_read, MySubject, nil).must_equal lock
|
43
|
-
ResolveInheritedLocks.call(owner, :my_read, MySubject, my_subject.id).must_equal lock
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,56 +0,0 @@
|
|
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.id) }
|
10
|
-
let(:default_locks) { [MyLock.new(subject_type: MySubject, action: :read, outcome: false)] }
|
11
|
-
|
12
|
-
describe '#lock' do
|
13
|
-
describe 'no locks' do
|
14
|
-
it 'must be nil' do
|
15
|
-
MySubject.stub :default_locks, default_locks do
|
16
|
-
subject.must_be_nil
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe 'id locks' do
|
22
|
-
it 'returns outcome' do
|
23
|
-
MySubject.stub :default_locks, default_locks do
|
24
|
-
owner.my_locks = [MyLock.new(action: :read, subject: my_subject, outcome: true)]
|
25
|
-
resolver_for_subject_id.calculated_outcome.must_equal true
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'prefers negative outcome' do
|
30
|
-
MySubject.stub :default_locks, default_locks do
|
31
|
-
owner.my_locks = [MyLock.new(action: :read, subject: my_subject, outcome: true),
|
32
|
-
MyLock.new(action: :read, subject: my_subject, outcome: false)]
|
33
|
-
resolver_for_subject_id.calculated_outcome.must_equal false
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe 'class locks' do
|
39
|
-
it 'returns outcome' do
|
40
|
-
MySubject.stub :default_locks, default_locks do
|
41
|
-
owner.my_locks = [MyLock.new(action: :read, subject_type: MySubject, outcome: true)]
|
42
|
-
subject.calculated_outcome.must_equal true
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'prefers negative outcome' do
|
47
|
-
MySubject.stub :default_locks, default_locks do
|
48
|
-
owner.my_locks = [MyLock.new(action: :read, subject_type: MySubject, outcome: true),
|
49
|
-
MyLock.new(action: :read, subject_type: MySubject, outcome: false)]
|
50
|
-
subject.calculated_outcome.must_equal false
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
module MongoidAbility
|
4
|
-
describe Resolver do
|
5
|
-
let(:owner) { MyOwner.new }
|
6
|
-
|
7
|
-
describe 'errors' do
|
8
|
-
it 'raises NameError for invalid subject_type' do
|
9
|
-
-> { Resolver.call(owner, :read, 'Foo') }.must_raise NameError
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'raises StandardError when subject_type does not have default_locks' do
|
13
|
-
-> { Resolver.call(owner, :read, Object) }.must_raise StandardError
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'raises StandardError when subject_type class or its ancestors does not have default_lock' do
|
17
|
-
MySubject.stub(:default_locks, []) do
|
18
|
-
-> { Resolver.call(owner, :read, MySubject) }.must_raise StandardError
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,147 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
module MongoidAbility
|
4
|
-
describe '.accessible_by' do
|
5
|
-
let(:my_subject) { MySubject.create! }
|
6
|
-
let(:my_subject1) { MySubject1.create! }
|
7
|
-
let(:my_subject2) { MySubject2.create! }
|
8
|
-
|
9
|
-
let(:role_1) { MyRole.new }
|
10
|
-
let(:role_2) { MyRole.new }
|
11
|
-
let(:owner) { MyOwner.new(my_roles: [role_1, role_2]) }
|
12
|
-
let(:ability) { Ability.new(owner) }
|
13
|
-
|
14
|
-
let(:my_subject_default_locks) { [] }
|
15
|
-
let(:my_subject_1_default_locks) { [] }
|
16
|
-
let(:my_subject_2_default_locks) { [] }
|
17
|
-
|
18
|
-
before { my_subject; my_subject1; my_subject2 }
|
19
|
-
|
20
|
-
describe 'default open locks' do
|
21
|
-
# NOTE: we might need to use the .default_lock macro in case we propagate down directly
|
22
|
-
let(:my_subject_default_locks) { [MyLock.new(subject_type: MySubject, action: :update, outcome: true)] }
|
23
|
-
|
24
|
-
it 'propagates from superclass to all subclasses' do
|
25
|
-
MySubject.stub :default_locks, my_subject_default_locks do
|
26
|
-
MySubject1.stub :default_locks, my_subject_1_default_locks do
|
27
|
-
MySubject2.stub :default_locks, my_subject_2_default_locks do
|
28
|
-
MySubject.accessible_by(ability, :update).to_a.must_include my_subject
|
29
|
-
MySubject.accessible_by(ability, :update).to_a.must_include my_subject1
|
30
|
-
MySubject.accessible_by(ability, :update).to_a.must_include my_subject2
|
31
|
-
|
32
|
-
MySubject1.accessible_by(ability, :update).to_a.wont_include my_subject
|
33
|
-
MySubject1.accessible_by(ability, :update).to_a.must_include my_subject1
|
34
|
-
MySubject1.accessible_by(ability, :update).to_a.must_include my_subject2
|
35
|
-
|
36
|
-
MySubject2.accessible_by(ability, :update).to_a.wont_include my_subject
|
37
|
-
MySubject2.accessible_by(ability, :update).to_a.wont_include my_subject1
|
38
|
-
MySubject2.accessible_by(ability, :update).to_a.must_include my_subject2
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe 'default closed locks' do
|
46
|
-
# NOTE: we might need to use the .default_lock macro in case we propagate down directly
|
47
|
-
let(:my_subject_default_locks) { [MyLock.new(subject_type: MySubject, action: :update, outcome: false)] }
|
48
|
-
|
49
|
-
it 'propagates from superclass to all subclasses' do
|
50
|
-
MySubject.stub :default_locks, my_subject_default_locks do
|
51
|
-
MySubject1.stub :default_locks, my_subject_1_default_locks do
|
52
|
-
MySubject2.stub :default_locks, my_subject_2_default_locks do
|
53
|
-
MySubject.accessible_by(ability, :update).to_a.wont_include my_subject
|
54
|
-
MySubject.accessible_by(ability, :update).to_a.wont_include my_subject1
|
55
|
-
MySubject.accessible_by(ability, :update).to_a.wont_include my_subject2
|
56
|
-
|
57
|
-
MySubject1.accessible_by(ability, :update).to_a.wont_include my_subject
|
58
|
-
MySubject1.accessible_by(ability, :update).to_a.wont_include my_subject1
|
59
|
-
MySubject1.accessible_by(ability, :update).to_a.wont_include my_subject2
|
60
|
-
|
61
|
-
MySubject2.accessible_by(ability, :update).to_a.wont_include my_subject
|
62
|
-
MySubject2.accessible_by(ability, :update).to_a.wont_include my_subject1
|
63
|
-
MySubject2.accessible_by(ability, :update).to_a.wont_include my_subject2
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe 'default combined locks' do
|
71
|
-
# NOTE: we might need to use the .default_lock macro in case we propagate down directly
|
72
|
-
let(:my_subject_default_locks) { [MyLock.new(subject_type: MySubject, action: :update, outcome: false)] }
|
73
|
-
let(:my_subject_1_default_locks) { [MyLock.new(subject_type: MySubject, action: :update, outcome: true)] }
|
74
|
-
let(:my_subject_2_default_locks) { [MyLock.new(subject_type: MySubject, action: :update, outcome: false)] }
|
75
|
-
|
76
|
-
it 'propagates from superclass to all subclasses' do
|
77
|
-
MySubject.stub :default_locks, my_subject_default_locks do
|
78
|
-
MySubject1.stub :default_locks, my_subject_1_default_locks do
|
79
|
-
MySubject2.stub :default_locks, my_subject_2_default_locks do
|
80
|
-
MySubject.accessible_by(ability, :update).to_a.wont_include my_subject
|
81
|
-
MySubject.accessible_by(ability, :update).to_a.must_include my_subject1
|
82
|
-
MySubject.accessible_by(ability, :update).to_a.wont_include my_subject2
|
83
|
-
|
84
|
-
MySubject1.accessible_by(ability, :update).to_a.wont_include my_subject
|
85
|
-
MySubject1.accessible_by(ability, :update).to_a.must_include my_subject1
|
86
|
-
MySubject1.accessible_by(ability, :update).to_a.wont_include my_subject2
|
87
|
-
|
88
|
-
MySubject2.accessible_by(ability, :update).to_a.wont_include my_subject
|
89
|
-
MySubject2.accessible_by(ability, :update).to_a.wont_include my_subject1
|
90
|
-
MySubject2.accessible_by(ability, :update).to_a.wont_include my_subject2
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
describe 'closed id locks' do
|
98
|
-
let(:role_1) { MyRole.new(my_locks: [MyLock.new(subject: my_subject, action: :update, outcome: false)]) }
|
99
|
-
let(:my_subject_default_locks) { [MyLock.new(subject_type: MySubject, action: :update, outcome: true)] }
|
100
|
-
|
101
|
-
it 'applies id locks' do
|
102
|
-
MySubject.stub :default_locks, my_subject_default_locks do
|
103
|
-
MySubject1.stub :default_locks, my_subject_1_default_locks do
|
104
|
-
MySubject2.stub :default_locks, my_subject_2_default_locks do
|
105
|
-
MySubject.accessible_by(ability, :update).to_a.wont_include my_subject
|
106
|
-
MySubject.accessible_by(ability, :update).to_a.must_include my_subject1
|
107
|
-
MySubject.accessible_by(ability, :update).to_a.must_include my_subject2
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
describe 'open id locks' do
|
115
|
-
let(:role_1) { MyRole.new(my_locks: [MyLock.new(subject: my_subject1, action: :update, outcome: true)]) }
|
116
|
-
let(:my_subject_default_locks) { [MyLock.new(subject_type: MySubject, action: :update, outcome: false)] }
|
117
|
-
|
118
|
-
it 'applies id locks' do
|
119
|
-
MySubject.stub :default_locks, my_subject_default_locks do
|
120
|
-
MySubject1.stub :default_locks, my_subject_1_default_locks do
|
121
|
-
MySubject2.stub :default_locks, my_subject_2_default_locks do
|
122
|
-
MySubject.accessible_by(ability, :update).to_a.wont_include my_subject
|
123
|
-
MySubject1.accessible_by(ability, :update).to_a.must_include my_subject1
|
124
|
-
MySubject2.accessible_by(ability, :update).to_a.wont_include my_subject2
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
describe 'prefix' do
|
132
|
-
let(:prefix) { :subject }
|
133
|
-
let(:my_subject_default_locks) { [MyLock.new(subject_type: MySubject, action: :update, outcome: true)] }
|
134
|
-
|
135
|
-
it 'allows to pass prefix' do
|
136
|
-
MySubject.stub :default_locks, my_subject_default_locks do
|
137
|
-
MySubject1.stub :default_locks, my_subject_1_default_locks do
|
138
|
-
MySubject2.stub :default_locks, my_subject_2_default_locks do
|
139
|
-
selector = MySubject.accessible_by(ability, :update, prefix: prefix).selector
|
140
|
-
selector.must_equal('$and' => [{ '$or' => [{ "#{prefix}_type" => { '$nin' => [] } }, { "#{prefix}_type" => { '$in' => [] }, "#{prefix}_id" => { '$in' => [] } }] }, { "#{prefix}_id" => { '$nin' => [] } }])
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|