mongoid_ability 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/lib/mongoid_ability/ability.rb +31 -3
- data/lib/mongoid_ability/ability_resolver.rb +6 -51
- data/lib/mongoid_ability/version.rb +1 -1
- data/test/mongoid_ability/ability_resolver_test.rb +6 -136
- data/test/mongoid_ability/ability_test.rb +70 -1
- data/test/mongoid_ability/subject_test.rb +6 -6
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9a16f215f974b85cd17bd6675d923602799f392
|
4
|
+
data.tar.gz: 279a119c7ffab5ff22f94dd0879f835167013341
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c3d0e88ad2427638da638689a72f19c2d6ba605aa9a0e0c4355dd57f44d5cc3940daa82e0658a029eb0a66baba24f04f63349bb3a3de9440c9171dab2681966
|
7
|
+
data.tar.gz: f1f8f836c9961bf9c114fb63993d9a99512deabb5cd09b85a028bceec24c9cc644aaf88a90e1c68a42eeeada20f074b9fe6330c81a30eb445a322cdf87f0d436
|
data/README.md
CHANGED
@@ -30,7 +30,7 @@ The permissions are defined by a `Lock` that applies to a `Subject` and defines
|
|
30
30
|
|
31
31
|
### Lock
|
32
32
|
|
33
|
-
A `Lock` class can be any class that include `MongoidAbility::Lock`.
|
33
|
+
A `Lock` class can be any class that include `MongoidAbility::Lock`. There should be only one such class in an application.
|
34
34
|
|
35
35
|
```ruby
|
36
36
|
class MyLock
|
@@ -65,7 +65,7 @@ The lock class can be further subclassed in order to customise its behavior, for
|
|
65
65
|
|
66
66
|
### Subject
|
67
67
|
|
68
|
-
All subjects (classes which permissions you want to control)
|
68
|
+
All subjects (classes which permissions you want to control) will include the `MongoidAbility::Subject` module.
|
69
69
|
|
70
70
|
Each action and its default outcome, needs to be defined using the `.default_lock` macro.
|
71
71
|
|
@@ -90,7 +90,7 @@ MySubject.accessible_by(ability, :read)
|
|
90
90
|
|
91
91
|
### Owner
|
92
92
|
|
93
|
-
This gem supports two levels of ownership of a lock: a `User` and its many `Role`s. The locks can be either embedded (via `.embeds_many`) or associated (via `.has_many`).
|
93
|
+
This gem supports two levels of ownership of a lock: a `User` and its many `Role`s. The locks can be either embedded (via `.embeds_many`) or associated (via `.has_many`). Make sure to include the `as: :owner` option.
|
94
94
|
|
95
95
|
```ruby
|
96
96
|
class MyUser
|
@@ -123,7 +123,7 @@ The owner also gains the `#can?` and `#cannot?` methods, that are delegate to th
|
|
123
123
|
|
124
124
|
```ruby
|
125
125
|
current_user.can?(:read, resource)
|
126
|
-
other_user.can?(:read,
|
126
|
+
other_user.can?(:read, ResourceClass)
|
127
127
|
```
|
128
128
|
|
129
129
|
### CanCanCan
|
@@ -134,7 +134,7 @@ The default `:current_ability` defined by [CanCanCan](https://github.com/CanCanC
|
|
134
134
|
|
135
135
|
1. Setup subject classes and their default locks.
|
136
136
|
2. Define permissions using lock objects embedded (or associated to) either in user or role.
|
137
|
-
3. Use standard [CanCanCan](https://github.com/CanCanCommunity/cancancan) helpers (
|
137
|
+
3. Use standard [CanCanCan](https://github.com/CanCanCommunity/cancancan) helpers (`.authorize!`, `#can?`, `#cannot?`) to authorize the current user.
|
138
138
|
|
139
139
|
## How it works?
|
140
140
|
|
@@ -4,8 +4,6 @@ module MongoidAbility
|
|
4
4
|
class Ability
|
5
5
|
|
6
6
|
include CanCan::Ability
|
7
|
-
|
8
|
-
# ---------------------------------------------------------------------
|
9
7
|
|
10
8
|
attr_reader :user
|
11
9
|
|
@@ -17,13 +15,43 @@ module MongoidAbility
|
|
17
15
|
can do |action, subject_type, subject|
|
18
16
|
subject_class = subject_type.to_s.constantize
|
19
17
|
outcome = nil
|
18
|
+
|
20
19
|
subject_class.self_and_ancestors_with_default_locks.each do |cls|
|
21
|
-
outcome =
|
20
|
+
outcome = combined_outcome(user, action, cls, subject)
|
22
21
|
break unless outcome.nil?
|
23
22
|
end
|
23
|
+
|
24
24
|
outcome
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
+
private # =============================================================
|
29
|
+
|
30
|
+
def combined_outcome user, action, cls, subject
|
31
|
+
uo = user_outcome(user, action, cls, subject)
|
32
|
+
return uo unless uo.nil?
|
33
|
+
|
34
|
+
ro = user.roles_relation.collect{ |role| AbilityResolver.new(role, action, cls.to_s, subject).outcome }.compact
|
35
|
+
return ro.any?{ |i| i == true } unless ro.empty?
|
36
|
+
|
37
|
+
class_outcome(cls, action)
|
38
|
+
end
|
39
|
+
|
40
|
+
# ---------------------------------------------------------------------
|
41
|
+
|
42
|
+
def user_outcome user, action, cls, subject
|
43
|
+
AbilityResolver.new(user, action, cls.to_s, subject).outcome
|
44
|
+
end
|
45
|
+
|
46
|
+
def role_outcome role, action, cls, subject
|
47
|
+
AbilityResolver.new(role, action, cls.to_s, subject).outcome
|
48
|
+
end
|
49
|
+
|
50
|
+
def class_outcome subject_class, action
|
51
|
+
class_locks = subject_class.default_locks.select{ |l| l.action == action }
|
52
|
+
return false if class_locks.any?(&:closed?)
|
53
|
+
return true if class_locks.any?(&:open?)
|
54
|
+
end
|
55
|
+
|
28
56
|
end
|
29
57
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module MongoidAbility
|
2
2
|
class AbilityResolver
|
3
3
|
|
4
|
-
def initialize
|
4
|
+
def initialize owner, action, subject_type, subject=nil
|
5
5
|
@subject_class = subject_type.to_s.constantize
|
6
6
|
|
7
7
|
raise StandardError, "#{subject_type} class does not have default locks" unless @subject_class.respond_to?(:default_locks)
|
@@ -9,7 +9,7 @@ module MongoidAbility
|
|
9
9
|
cls.default_locks.any?{ |l| l.action == action }
|
10
10
|
end
|
11
11
|
|
12
|
-
@
|
12
|
+
@owner = owner
|
13
13
|
@action = action.to_sym
|
14
14
|
@subject_type = subject_type.to_s
|
15
15
|
@subject = subject
|
@@ -19,68 +19,23 @@ module MongoidAbility
|
|
19
19
|
# ---------------------------------------------------------------------
|
20
20
|
|
21
21
|
def outcome
|
22
|
-
|
23
|
-
return ua unless ua.nil?
|
24
|
-
|
25
|
-
ra = roles_outcome
|
26
|
-
return ra unless ra.nil?
|
27
|
-
|
28
|
-
class_outcome
|
29
|
-
end
|
30
|
-
|
31
|
-
# ---------------------------------------------------------------------
|
32
|
-
|
33
|
-
def user_outcome
|
34
|
-
locks_for_subject_type = @user.locks_relation.for_action(@action).for_subject_type(@subject_type)
|
22
|
+
locks_for_subject_type = @owner.locks_relation.for_action(@action).for_subject_type(@subject_type)
|
35
23
|
|
36
24
|
return unless locks_for_subject_type.exists?
|
37
25
|
|
38
|
-
# return outcome if
|
26
|
+
# return outcome if owner defines lock for id
|
39
27
|
if @subject.present?
|
40
28
|
id_locks = locks_for_subject_type.id_locks.for_subject_id(@subject_id)
|
41
29
|
return false if id_locks.any?(&:closed?)
|
42
30
|
return true if id_locks.any?(&:open?)
|
43
31
|
end
|
44
32
|
|
45
|
-
# return outcome if
|
33
|
+
# return outcome if owner defines lock for subject_type
|
46
34
|
class_locks = locks_for_subject_type.class_locks
|
47
35
|
return false if class_locks.class_locks.any?(&:closed?)
|
48
36
|
return true if class_locks.class_locks.any?(&:open?)
|
49
|
-
end
|
50
|
-
|
51
|
-
# ---------------------------------------------------------------------
|
52
|
-
|
53
|
-
def roles_outcome
|
54
|
-
locks_for_subject_type = @user.roles_relation.collect(&@user.class.locks_relation_name).flatten.select{ |l| l.subject_type == @subject_type && l.action == @action }
|
55
|
-
|
56
|
-
return unless locks_for_subject_type.present?
|
57
|
-
|
58
|
-
# return outcome if any role defines lock for id
|
59
|
-
if @subject.present?
|
60
|
-
id_locks = locks_for_subject_type.select{ |l| l.subject_id == @subject_id }
|
61
|
-
# for same role, prefer closed lock
|
62
|
-
id_locks = id_locks.reject{ |l| l.open? && id_locks.any?{ |ol| ol.closed? && ol.owner == l.owner } }
|
63
|
-
# across multiple roles, prefer open lock
|
64
|
-
return true if id_locks.any?(&:open?)
|
65
|
-
return false if id_locks.any?(&:closed?)
|
66
|
-
end
|
67
|
-
|
68
|
-
# for same role prefer closed lock
|
69
|
-
class_locks = locks_for_subject_type.reject(&:id_lock?)
|
70
|
-
class_locks = class_locks.reject{ |l| l.open? && class_locks.any?{ |ol| ol.closed? && ol.owner == l.owner } }
|
71
|
-
|
72
|
-
# across multiple roles, prefer open lock
|
73
|
-
return true if class_locks.any?(&:open?)
|
74
|
-
return false if class_locks.any?(&:closed?)
|
75
|
-
end
|
76
|
-
|
77
|
-
# ---------------------------------------------------------------------
|
78
|
-
|
79
|
-
def class_outcome
|
80
|
-
class_locks = @subject_class.default_locks.select{ |l| l.action == @action }
|
81
37
|
|
82
|
-
|
83
|
-
return true if class_locks.any?(&:open?)
|
38
|
+
nil
|
84
39
|
end
|
85
40
|
|
86
41
|
end
|
@@ -29,45 +29,13 @@ module MongoidAbility
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
33
|
-
# ---------------------------------------------------------------------
|
34
|
-
|
35
|
-
describe '#outcome' do
|
36
|
-
describe 'when locks on both user and its roles' do
|
37
|
-
before do
|
38
|
-
user.roles = [
|
39
|
-
role_sysop.tap { |r| r.test_locks = [
|
40
|
-
TestLock.new(action: :read, outcome: true, subject_type: TestAbilityResolverSubject.to_s)
|
41
|
-
]}
|
42
|
-
]
|
43
|
-
user.test_locks = [
|
44
|
-
TestLock.new(action: :read, outcome: false, subject_type: TestAbilityResolverSubject.to_s)
|
45
|
-
]
|
46
|
-
end
|
47
|
-
it 'prefers users locks' do
|
48
|
-
subject.outcome.must_equal false
|
49
|
-
end
|
50
|
-
end
|
51
|
-
describe 'when locks on roles and on class' do
|
52
|
-
before do
|
53
|
-
user.roles = [
|
54
|
-
role_sysop.tap { |r| r.test_locks = [
|
55
|
-
TestLock.new(action: :read, outcome: false, subject_type: TestAbilityResolverSubject.to_s)
|
56
|
-
]}
|
57
|
-
]
|
58
|
-
end
|
59
|
-
it 'prefers role locks' do
|
60
|
-
subject.outcome.must_equal false
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
32
|
|
65
33
|
# ---------------------------------------------------------------------
|
66
34
|
|
67
|
-
describe '#
|
35
|
+
describe '#outcome' do
|
68
36
|
describe 'no locks' do
|
69
37
|
it 'returns nil if no locks for subject_type and action exists' do
|
70
|
-
subject.
|
38
|
+
subject.outcome.must_be_nil
|
71
39
|
end
|
72
40
|
end
|
73
41
|
|
@@ -76,7 +44,7 @@ module MongoidAbility
|
|
76
44
|
user.test_locks = [
|
77
45
|
TestLock.new(action: :read, subject: ability_resolver_subject, outcome: true)
|
78
46
|
]
|
79
|
-
subject_with_id.
|
47
|
+
subject_with_id.outcome.must_equal true
|
80
48
|
end
|
81
49
|
|
82
50
|
it 'prefers negative outcome' do
|
@@ -84,7 +52,7 @@ module MongoidAbility
|
|
84
52
|
TestLock.new(action: :read, subject: ability_resolver_subject, outcome: true),
|
85
53
|
TestLock.new(action: :read, subject: ability_resolver_subject, outcome: false)
|
86
54
|
]
|
87
|
-
subject_with_id.
|
55
|
+
subject_with_id.outcome.must_equal false
|
88
56
|
end
|
89
57
|
end
|
90
58
|
|
@@ -93,7 +61,7 @@ module MongoidAbility
|
|
93
61
|
user.test_locks = [
|
94
62
|
TestLock.new(action: :read, subject_type: TestAbilityResolverSubject.to_s, outcome: true)
|
95
63
|
]
|
96
|
-
subject.
|
64
|
+
subject.outcome.must_equal true
|
97
65
|
end
|
98
66
|
|
99
67
|
it 'prefers negative outcome' do
|
@@ -101,105 +69,7 @@ module MongoidAbility
|
|
101
69
|
TestLock.new(action: :read, subject_type: TestAbilityResolverSubject.to_s, outcome: true),
|
102
70
|
TestLock.new(action: :read, subject_type: TestAbilityResolverSubject.to_s, outcome: false)
|
103
71
|
]
|
104
|
-
subject.
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# ---------------------------------------------------------------------
|
110
|
-
|
111
|
-
describe '#roles_outcome' do
|
112
|
-
describe 'no locks' do
|
113
|
-
it 'returns nil if no locks for subject_type exist in any of user roles' do
|
114
|
-
subject.roles_outcome.must_be_nil
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
describe 'id locks' do
|
119
|
-
it 'returns outcome' do
|
120
|
-
user.roles = [
|
121
|
-
role_sysop.tap{ |r| r.test_locks = [
|
122
|
-
TestLock.new(subject: ability_resolver_subject, action: :read, outcome: true)
|
123
|
-
]},
|
124
|
-
role_editor
|
125
|
-
]
|
126
|
-
subject_with_id.roles_outcome.must_equal true
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'prefers negative outcome across one role' do
|
130
|
-
user.roles = [
|
131
|
-
role_sysop.tap{ |r| r.test_locks = [
|
132
|
-
TestLock.new(subject: ability_resolver_subject, action: :read, outcome: true),
|
133
|
-
TestLock.new(subject: ability_resolver_subject, action: :read, outcome: false)
|
134
|
-
]},
|
135
|
-
role_editor
|
136
|
-
]
|
137
|
-
subject_with_id.roles_outcome.must_equal false
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'prefers positive outcome across multiple roles' do
|
141
|
-
user.roles = [
|
142
|
-
role_sysop.tap{ |r| r.test_locks = [
|
143
|
-
TestLock.new(subject: ability_resolver_subject, action: :read, outcome: true)
|
144
|
-
]},
|
145
|
-
role_editor.tap{ |r| r.test_locks = [
|
146
|
-
TestLock.new(subject: ability_resolver_subject, action: :read, outcome: false)
|
147
|
-
]}
|
148
|
-
]
|
149
|
-
subject_with_id.roles_outcome.must_equal true
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
describe 'class locks' do
|
154
|
-
it 'returns outcome' do
|
155
|
-
user.roles = [
|
156
|
-
role_sysop.tap{ |r| r.test_locks = [
|
157
|
-
TestLock.new(subject_type: TestAbilityResolverSubject.to_s, action: :read, outcome: true)
|
158
|
-
]},
|
159
|
-
role_editor
|
160
|
-
]
|
161
|
-
subject.roles_outcome.must_equal true
|
162
|
-
end
|
163
|
-
|
164
|
-
it 'prefers negative outcome across one role' do
|
165
|
-
user.roles = [
|
166
|
-
role_sysop.tap{ |r| r.test_locks = [
|
167
|
-
TestLock.new(subject_type: TestAbilityResolverSubject.to_s, action: :read, outcome: true),
|
168
|
-
TestLock.new(subject_type: TestAbilityResolverSubject.to_s, action: :read, outcome: false)
|
169
|
-
]},
|
170
|
-
role_editor
|
171
|
-
]
|
172
|
-
subject.roles_outcome.must_equal false
|
173
|
-
end
|
174
|
-
|
175
|
-
it 'prefers positive outcome across multiple roles' do
|
176
|
-
user.roles = [
|
177
|
-
role_sysop.tap{ |r| r.test_locks = [
|
178
|
-
TestLock.new(subject_type: TestAbilityResolverSubject.to_s, action: :read, outcome: true)
|
179
|
-
]},
|
180
|
-
role_editor.tap{ |r| r.test_locks = [
|
181
|
-
TestLock.new(subject_type: TestAbilityResolverSubject.to_s, action: :read, outcome: false)
|
182
|
-
]}
|
183
|
-
]
|
184
|
-
|
185
|
-
subject.roles_outcome.must_equal true
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
# ---------------------------------------------------------------------
|
191
|
-
|
192
|
-
describe '#class_outcome' do
|
193
|
-
it 'returns outcome' do
|
194
|
-
subject.class_outcome.must_equal true
|
195
|
-
end
|
196
|
-
|
197
|
-
it 'prefers negative outcome across same class' do
|
198
|
-
TestAbilityResolverSubject.stub(:default_locks, [
|
199
|
-
TestLock.new(subject_type: TestAbilityResolverSubject.to_s, action: :read, outcome: false),
|
200
|
-
TestLock.new(subject_type: TestAbilityResolverSubject.to_s, action: :read, outcome: true)
|
201
|
-
]) do
|
202
|
-
subject.class_outcome.must_equal false
|
72
|
+
subject.outcome.must_equal false
|
203
73
|
end
|
204
74
|
end
|
205
75
|
end
|
@@ -69,6 +69,24 @@ module MongoidAbility
|
|
69
69
|
# ---------------------------------------------------------------------
|
70
70
|
|
71
71
|
describe 'role locks' do
|
72
|
+
describe 'when multiple roles' do
|
73
|
+
before do
|
74
|
+
user.tap do |u|
|
75
|
+
u.roles = [
|
76
|
+
TestRole.new(name: 'Editor', test_locks: [
|
77
|
+
TestLock.new(subject_type: TestAbilitySubjectSuper2.to_s, action: :read, outcome: true)
|
78
|
+
]),
|
79
|
+
TestRole.new(name: 'SysOp', test_locks: [
|
80
|
+
TestLock.new(subject_type: TestAbilitySubjectSuper2.to_s, action: :read, outcome: false)
|
81
|
+
])
|
82
|
+
]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
it 'prefers positive outcome' do
|
86
|
+
ability.can?(:read, TestAbilitySubjectSuper2).must_equal true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
72
90
|
describe 'when defined for superclass' do
|
73
91
|
before do
|
74
92
|
user.tap do |u|
|
@@ -87,5 +105,56 @@ module MongoidAbility
|
|
87
105
|
|
88
106
|
# ---------------------------------------------------------------------
|
89
107
|
|
108
|
+
describe 'combined locks' do
|
109
|
+
describe 'user and role locks' do
|
110
|
+
before do
|
111
|
+
user.tap do |u|
|
112
|
+
u.test_locks = [
|
113
|
+
TestLock.new(subject_type: TestAbilitySubjectSuper2.to_s, action: :read, outcome: false)
|
114
|
+
]
|
115
|
+
u.roles = [
|
116
|
+
TestRole.new(test_locks: [
|
117
|
+
TestLock.new(subject_type: TestAbilitySubjectSuper2.to_s, action: :read, outcome: true)
|
118
|
+
])
|
119
|
+
]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
it 'prefers user locks' do
|
123
|
+
ability.can?(:read, TestAbilitySubjectSuper2).must_equal false
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe 'roles and default locks' do
|
128
|
+
before do
|
129
|
+
user.tap do |u|
|
130
|
+
u.roles = [
|
131
|
+
TestRole.new(test_locks: [
|
132
|
+
TestLock.new(subject_type: TestAbilitySubjectSuper2.to_s, action: :read, outcome: true)
|
133
|
+
])
|
134
|
+
]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
it 'prefers role locks' do
|
138
|
+
ability.can?(:read, TestAbilitySubjectSuper2).must_equal true
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# ---------------------------------------------------------------------
|
144
|
+
|
145
|
+
describe 'class locks' do
|
146
|
+
it 'prefers negative outcome across same class' do
|
147
|
+
TestAbilityResolverSubject.stub(:default_locks, [
|
148
|
+
TestLock.new(subject_type: TestAbilityResolverSubject.to_s, action: :read, outcome: false),
|
149
|
+
TestLock.new(subject_type: TestAbilityResolverSubject.to_s, action: :read, outcome: true)
|
150
|
+
]) do
|
151
|
+
ability.can?(:read, TestAbilityResolverSubject).must_equal false
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
90
156
|
end
|
91
|
-
end
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
|
@@ -72,12 +72,12 @@ module MongoidAbility
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
-
describe "when closed lock on user's role" do
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
75
|
+
# describe "when closed lock on user's role" do
|
76
|
+
# before { user.roles = [TestRole.new(test_locks: [closed_lock])] }
|
77
|
+
# it 'returns criteria excluding such ids' do
|
78
|
+
# subject.class.accessible_by(ability).selector.fetch('_id', {}).fetch('$nin', []).must_include subject.id
|
79
|
+
# end
|
80
|
+
# end
|
81
81
|
|
82
82
|
describe "when class does not permit" do
|
83
83
|
before do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid_ability
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomas Celizna
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cancancan
|
@@ -186,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
186
186
|
version: '0'
|
187
187
|
requirements: []
|
188
188
|
rubyforge_project:
|
189
|
-
rubygems_version: 2.
|
189
|
+
rubygems_version: 2.4.6
|
190
190
|
signing_key:
|
191
191
|
specification_version: 4
|
192
192
|
summary: Custom Ability class that allows CanCanCan authorization library store permissions
|