cancancan 3.0.0 → 3.2.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.
- checksums.yaml +4 -4
- data/lib/cancan.rb +2 -0
- data/lib/cancan/ability.rb +5 -1
- data/lib/cancan/class_matcher.rb +26 -0
- data/lib/cancan/conditions_matcher.rb +6 -3
- data/lib/cancan/config.rb +54 -0
- data/lib/cancan/exceptions.rb +8 -0
- data/lib/cancan/model_adapters/abstract_adapter.rb +1 -1
- data/lib/cancan/model_adapters/active_record_4_adapter.rb +2 -4
- data/lib/cancan/model_adapters/active_record_5_adapter.rb +12 -10
- data/lib/cancan/model_adapters/active_record_adapter.rb +9 -2
- data/lib/cancan/model_adapters/conditions_normalizer.rb +5 -1
- data/lib/cancan/model_adapters/sti_normalizer.rb +39 -0
- data/lib/cancan/relevant.rb +29 -0
- data/lib/cancan/rule.rb +26 -20
- data/lib/cancan/unauthorized_message_resolver.rb +4 -2
- data/lib/cancan/version.rb +1 -1
- metadata +22 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d109d94a089119e1183b6ed77e78316e212b3d78506b8ed10aabb1e8e0e090ce
|
4
|
+
data.tar.gz: '09d6acb72b55c2892be6d7c614bbf9a55b4f60ca3eee1e6aa898e1213e0e807d'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c708dbbefc7a0d120cf9dbacb3d478e2a6155dbb72800563be83b2fced563118b79454a6d9f6eb372bad88f7c4835ebefa636058d055f161b395a6076d154781
|
7
|
+
data.tar.gz: 269ff0d42f16aff0db8882473364fee508504c5f8dd5e4e8d271810d7420e76bebf3c64a16b58a81ed2754e9b1c7fdb9f576c5bc3804c6d26d5b19386e3e9f8e
|
data/lib/cancan.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'cancan/version'
|
4
|
+
require 'cancan/config'
|
4
5
|
require 'cancan/parameter_validators'
|
5
6
|
require 'cancan/ability'
|
6
7
|
require 'cancan/rule'
|
@@ -16,6 +17,7 @@ require 'cancan/rules_compressor'
|
|
16
17
|
if defined? ActiveRecord
|
17
18
|
require 'cancan/model_adapters/conditions_extractor'
|
18
19
|
require 'cancan/model_adapters/conditions_normalizer'
|
20
|
+
require 'cancan/model_adapters/sti_normalizer'
|
19
21
|
require 'cancan/model_adapters/active_record_adapter'
|
20
22
|
require 'cancan/model_adapters/active_record_4_adapter'
|
21
23
|
require 'cancan/model_adapters/active_record_5_adapter'
|
data/lib/cancan/ability.rb
CHANGED
@@ -302,7 +302,11 @@ module CanCan
|
|
302
302
|
|
303
303
|
def alternative_subjects(subject)
|
304
304
|
subject = subject.class unless subject.is_a?(Module)
|
305
|
-
|
305
|
+
if subject.respond_to?(:subclasses) && defined?(ActiveRecord::Base) && subject < ActiveRecord::Base
|
306
|
+
[:all, *(subject.ancestors + subject.subclasses), subject.class.to_s]
|
307
|
+
else
|
308
|
+
[:all, *subject.ancestors, subject.class.to_s]
|
309
|
+
end
|
306
310
|
end
|
307
311
|
end
|
308
312
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# This class is responsible for matching classes and their subclasses as well as
|
2
|
+
# upmatching classes to their ancestors.
|
3
|
+
# This is used to generate sti connections
|
4
|
+
class SubjectClassMatcher
|
5
|
+
def self.matches_subject_class?(subjects, subject)
|
6
|
+
subjects.any? do |sub|
|
7
|
+
has_subclasses = subject.respond_to?(:subclasses)
|
8
|
+
matching_class_check(subject, sub, has_subclasses)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.matching_class_check(subject, sub, has_subclasses)
|
13
|
+
matches = matches_class_or_is_related(subject, sub)
|
14
|
+
if has_subclasses
|
15
|
+
matches || subject.subclasses.include?(sub)
|
16
|
+
else
|
17
|
+
matches
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.matches_class_or_is_related(subject, sub)
|
22
|
+
sub.is_a?(Module) && (subject.is_a?(sub) ||
|
23
|
+
subject.class.to_s == sub.to_s ||
|
24
|
+
(subject.is_a?(Module) && subject.ancestors.include?(sub)))
|
25
|
+
end
|
26
|
+
end
|
@@ -21,7 +21,7 @@ module CanCan
|
|
21
21
|
def matches_block_conditions(subject, *extra_args)
|
22
22
|
return @base_behavior if subject_class?(subject)
|
23
23
|
|
24
|
-
@block.call(subject, *extra_args)
|
24
|
+
@block.call(subject, *extra_args.compact)
|
25
25
|
end
|
26
26
|
|
27
27
|
def matches_non_block_conditions(subject)
|
@@ -78,7 +78,7 @@ module CanCan
|
|
78
78
|
|
79
79
|
def hash_condition_match?(attribute, value)
|
80
80
|
if attribute.is_a?(Array) || (defined?(ActiveRecord) && attribute.is_a?(ActiveRecord::Relation))
|
81
|
-
attribute.any? { |element| matches_conditions_hash?(element, value) }
|
81
|
+
attribute.to_a.any? { |element| matches_conditions_hash?(element, value) }
|
82
82
|
else
|
83
83
|
attribute && matches_conditions_hash?(attribute, value)
|
84
84
|
end
|
@@ -97,7 +97,10 @@ module CanCan
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def conditions_empty?
|
100
|
-
@conditions
|
100
|
+
# @conditions might be an ActiveRecord::Associations::CollectionProxy
|
101
|
+
# which it's `==` implementation will fetch all records for comparison
|
102
|
+
|
103
|
+
(@conditions.is_a?(Hash) && @conditions == {}) || @conditions.nil?
|
101
104
|
end
|
102
105
|
end
|
103
106
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CanCan
|
4
|
+
def self.valid_accessible_by_strategies
|
5
|
+
strategies = [:left_join]
|
6
|
+
strategies << :subquery unless does_not_support_subquery_strategy?
|
7
|
+
strategies
|
8
|
+
end
|
9
|
+
|
10
|
+
# Determines how CanCan should build queries when calling accessible_by,
|
11
|
+
# if the query will contain a join. The default strategy is `:subquery`.
|
12
|
+
#
|
13
|
+
# # config/initializers/cancan.rb
|
14
|
+
# CanCan.accessible_by_strategy = :subquery
|
15
|
+
#
|
16
|
+
# Valid strategies are:
|
17
|
+
# - :subquery - Creates a nested query with all joins, wrapped by a
|
18
|
+
# WHERE IN query.
|
19
|
+
# - :left_join - Calls the joins directly using `left_joins`, and
|
20
|
+
# ensures records are unique using `distinct`. Note that
|
21
|
+
# `distinct` is not reliable in some cases. See
|
22
|
+
# https://github.com/CanCanCommunity/cancancan/pull/605
|
23
|
+
def self.accessible_by_strategy
|
24
|
+
@accessible_by_strategy || default_accessible_by_strategy
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.default_accessible_by_strategy
|
28
|
+
if does_not_support_subquery_strategy?
|
29
|
+
# see https://github.com/CanCanCommunity/cancancan/pull/655 for where this was added
|
30
|
+
# the `subquery` strategy (from https://github.com/CanCanCommunity/cancancan/pull/619
|
31
|
+
# only works in Rails 5 and higher
|
32
|
+
:left_join
|
33
|
+
else
|
34
|
+
:subquery
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.accessible_by_strategy=(value)
|
39
|
+
unless valid_accessible_by_strategies.include?(value)
|
40
|
+
raise ArgumentError, "accessible_by_strategy must be one of #{valid_accessible_by_strategies.join(', ')}"
|
41
|
+
end
|
42
|
+
|
43
|
+
if value == :subquery && does_not_support_subquery_strategy?
|
44
|
+
raise ArgumentError, 'accessible_by_strategy = :subquery requires ActiveRecord 5 or newer'
|
45
|
+
end
|
46
|
+
|
47
|
+
@accessible_by_strategy = value
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.does_not_support_subquery_strategy?
|
51
|
+
!defined?(CanCan::ModelAdapters::ActiveRecordAdapter) ||
|
52
|
+
CanCan::ModelAdapters::ActiveRecordAdapter.version_lower?('5.0.0')
|
53
|
+
end
|
54
|
+
end
|
data/lib/cancan/exceptions.rb
CHANGED
@@ -58,5 +58,13 @@ module CanCan
|
|
58
58
|
def to_s
|
59
59
|
@message || @default_message
|
60
60
|
end
|
61
|
+
|
62
|
+
def inspect
|
63
|
+
details = %i[action subject conditions message].map do |attribute|
|
64
|
+
value = instance_variable_get "@#{attribute}"
|
65
|
+
"#{attribute}: #{value.inspect}" if value.present?
|
66
|
+
end.compact.join(', ')
|
67
|
+
"#<#{self.class.name} #{details}>"
|
68
|
+
end
|
61
69
|
end
|
62
70
|
end
|
@@ -34,10 +34,8 @@ module CanCan
|
|
34
34
|
# look inside the where clause to decide to outer join tables
|
35
35
|
# you're using in the where. Instead, `references()` is required
|
36
36
|
# in addition to `includes()` to force the outer join.
|
37
|
-
def
|
38
|
-
relation
|
39
|
-
relation = relation.includes(joins).references(joins) if joins.present?
|
40
|
-
relation
|
37
|
+
def build_joins_relation(relation, *_where_conditions)
|
38
|
+
relation.includes(joins).references(joins)
|
41
39
|
end
|
42
40
|
|
43
41
|
# Rails 4.2 deprecates `sanitize_sql_hash_for_conditions`
|
@@ -21,13 +21,19 @@ module CanCan
|
|
21
21
|
|
22
22
|
private
|
23
23
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
def build_joins_relation(relation, *where_conditions)
|
25
|
+
case CanCan.accessible_by_strategy
|
26
|
+
when :subquery
|
27
|
+
inner = @model_class.unscoped do
|
28
|
+
@model_class.left_joins(joins).where(*where_conditions)
|
29
|
+
end
|
30
|
+
@model_class.where(@model_class.primary_key => inner)
|
31
|
+
|
32
|
+
when :left_join
|
33
|
+
relation.left_joins(joins).distinct
|
34
|
+
end
|
28
35
|
end
|
29
36
|
|
30
|
-
# Rails 4.2 deprecates `sanitize_sql_hash_for_conditions`
|
31
37
|
def sanitize_sql(conditions)
|
32
38
|
if conditions.is_a?(Hash)
|
33
39
|
sanitize_sql_activerecord5(conditions)
|
@@ -41,11 +47,7 @@ module CanCan
|
|
41
47
|
table_metadata = ActiveRecord::TableMetadata.new(@model_class, table)
|
42
48
|
predicate_builder = ActiveRecord::PredicateBuilder.new(table_metadata)
|
43
49
|
|
44
|
-
conditions
|
45
|
-
|
46
|
-
conditions.stringify_keys!
|
47
|
-
|
48
|
-
predicate_builder.build_from_hash(conditions).map { |b| visit_nodes(b) }.join(' AND ')
|
50
|
+
predicate_builder.build_from_hash(conditions.stringify_keys).map { |b| visit_nodes(b) }.join(' AND ')
|
49
51
|
end
|
50
52
|
|
51
53
|
def visit_nodes(node)
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'conditions_extractor.rb'
|
4
|
-
require 'cancan/rules_compressor'
|
5
3
|
module CanCan
|
6
4
|
module ModelAdapters
|
7
5
|
class ActiveRecordAdapter < AbstractAdapter
|
@@ -16,6 +14,7 @@ module CanCan
|
|
16
14
|
def initialize(model_class, rules)
|
17
15
|
super
|
18
16
|
@compressed_rules = RulesCompressor.new(@rules.reverse).rules_collapsed.reverse
|
17
|
+
StiNormalizer.normalize(@compressed_rules)
|
19
18
|
ConditionsNormalizer.normalize(model_class, @compressed_rules)
|
20
19
|
end
|
21
20
|
|
@@ -60,6 +59,14 @@ module CanCan
|
|
60
59
|
end
|
61
60
|
end
|
62
61
|
|
62
|
+
def build_relation(*where_conditions)
|
63
|
+
relation = @model_class.where(*where_conditions)
|
64
|
+
return relation unless joins.present?
|
65
|
+
|
66
|
+
# subclasses must implement `build_joins_relation`
|
67
|
+
build_joins_relation(relation, *where_conditions)
|
68
|
+
end
|
69
|
+
|
63
70
|
# Returns the associations used in conditions for the :joins option of a search.
|
64
71
|
# See ModelAdditions#accessible_by
|
65
72
|
def joins
|
@@ -31,7 +31,7 @@ module CanCan
|
|
31
31
|
raise WrongAssociationName, "Association '#{key}' not defined in model '#{model_class.name}'"
|
32
32
|
end
|
33
33
|
|
34
|
-
if reflection
|
34
|
+
if normalizable_association? reflection
|
35
35
|
key = reflection.options[:through]
|
36
36
|
value = { reflection.source_reflection_name => value }
|
37
37
|
reflection = model_class.reflect_on_association(key)
|
@@ -39,6 +39,10 @@ module CanCan
|
|
39
39
|
|
40
40
|
{ key => normalize_conditions(reflection.klass.name.constantize, value) }
|
41
41
|
end
|
42
|
+
|
43
|
+
def normalizable_association?(reflection)
|
44
|
+
reflection.options[:through].present? && !reflection.options[:source_type].present?
|
45
|
+
end
|
42
46
|
end
|
43
47
|
end
|
44
48
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# this class is responsible for detecting sti classes and creating new rules for the
|
2
|
+
# relevant subclasses, using the inheritance_column as a merger
|
3
|
+
module CanCan
|
4
|
+
module ModelAdapters
|
5
|
+
class StiNormalizer
|
6
|
+
class << self
|
7
|
+
def normalize(rules)
|
8
|
+
rules_cache = []
|
9
|
+
return unless defined?(ActiveRecord::Base)
|
10
|
+
|
11
|
+
rules.delete_if do |rule|
|
12
|
+
subjects = rule.subjects.select do |subject|
|
13
|
+
update_rule(subject, rule, rules_cache)
|
14
|
+
end
|
15
|
+
subjects.length == rule.subjects.length
|
16
|
+
end
|
17
|
+
rules_cache.each { |rule| rules.push(rule) }
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def update_rule(subject, rule, rules_cache)
|
23
|
+
return false unless subject.respond_to?(:descends_from_active_record?)
|
24
|
+
return false if subject == :all || subject.descends_from_active_record?
|
25
|
+
return false unless subject < ActiveRecord::Base
|
26
|
+
|
27
|
+
rules_cache.push(build_rule_for_subclass(rule, subject))
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
# create a new rule for the subclasses that links on the inheritance_column
|
32
|
+
def build_rule_for_subclass(rule, subject)
|
33
|
+
CanCan::Rule.new(rule.base_behavior, rule.actions, subject.superclass,
|
34
|
+
rule.conditions.merge(subject.inheritance_column => subject.name), rule.block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CanCan
|
4
|
+
module Relevant
|
5
|
+
# Matches both the action, subject, and attribute, not necessarily the conditions
|
6
|
+
def relevant?(action, subject)
|
7
|
+
subject = subject.values.first if subject.class == Hash
|
8
|
+
@match_all || (matches_action?(action) && matches_subject?(subject))
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def matches_action?(action)
|
14
|
+
@expanded_actions.include?(:manage) || @expanded_actions.include?(action)
|
15
|
+
end
|
16
|
+
|
17
|
+
def matches_subject?(subject)
|
18
|
+
@subjects.include?(:all) || @subjects.include?(subject) || matches_subject_class?(subject)
|
19
|
+
end
|
20
|
+
|
21
|
+
def matches_subject_class?(subject)
|
22
|
+
@subjects.any? do |sub|
|
23
|
+
sub.is_a?(Module) && (subject.is_a?(sub) ||
|
24
|
+
subject.class.to_s == sub.to_s ||
|
25
|
+
(subject.is_a?(Module) && subject.ancestors.include?(sub)))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/cancan/rule.rb
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'conditions_matcher.rb'
|
4
|
+
require_relative 'class_matcher.rb'
|
5
|
+
require_relative 'relevant.rb'
|
6
|
+
|
4
7
|
module CanCan
|
5
8
|
# This class is used internally and should only be called through Ability.
|
6
9
|
# it holds the information about a "can" call made on Ability and provides
|
7
10
|
# helpful methods to determine permission checking and conditions hash generation.
|
8
11
|
class Rule # :nodoc:
|
9
12
|
include ConditionsMatcher
|
13
|
+
include Relevant
|
10
14
|
include ParameterValidators
|
11
|
-
attr_reader :base_behavior, :subjects, :actions, :conditions, :attributes
|
15
|
+
attr_reader :base_behavior, :subjects, :actions, :conditions, :attributes, :block
|
12
16
|
attr_writer :expanded_actions, :conditions
|
13
17
|
|
14
18
|
# The first argument when initializing is the base_behavior which is a true/false
|
@@ -24,9 +28,9 @@ module CanCan
|
|
24
28
|
raise Error, "Subject is required for #{action}" if action && subject.nil?
|
25
29
|
|
26
30
|
@base_behavior = base_behavior
|
27
|
-
@actions =
|
28
|
-
@subjects =
|
29
|
-
@attributes =
|
31
|
+
@actions = wrap(action)
|
32
|
+
@subjects = wrap(subject)
|
33
|
+
@attributes = wrap(attributes)
|
30
34
|
@conditions = extra_args || {}
|
31
35
|
@block = block
|
32
36
|
end
|
@@ -34,11 +38,13 @@ module CanCan
|
|
34
38
|
def inspect
|
35
39
|
repr = "#<#{self.class.name}"
|
36
40
|
repr += "#{@base_behavior ? 'can' : 'cannot'} #{@actions.inspect}, #{@subjects.inspect}, #{@attributes.inspect}"
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
|
42
|
+
if with_scope?
|
43
|
+
repr += ", #{@conditions.where_values_hash}"
|
44
|
+
elsif [Hash, String].include?(@conditions.class)
|
45
|
+
repr += ", #{@conditions.inspect}"
|
46
|
+
end
|
47
|
+
|
42
48
|
repr + '>'
|
43
49
|
end
|
44
50
|
|
@@ -55,12 +61,6 @@ module CanCan
|
|
55
61
|
(!with_scope? && [nil, false, [], {}, '', ' '].include?(@conditions))
|
56
62
|
end
|
57
63
|
|
58
|
-
# Matches both the action, subject, and attribute, not necessarily the conditions
|
59
|
-
def relevant?(action, subject)
|
60
|
-
subject = subject.values.first if subject.class == Hash
|
61
|
-
@match_all || (matches_action?(action) && matches_subject?(subject))
|
62
|
-
end
|
63
|
-
|
64
64
|
def only_block?
|
65
65
|
conditions_empty? && @block
|
66
66
|
end
|
@@ -111,11 +111,7 @@ module CanCan
|
|
111
111
|
end
|
112
112
|
|
113
113
|
def matches_subject_class?(subject)
|
114
|
-
@subjects
|
115
|
-
sub.is_a?(Module) && (subject.is_a?(sub) ||
|
116
|
-
subject.class.to_s == sub.to_s ||
|
117
|
-
(subject.is_a?(Module) && subject.ancestors.include?(sub)))
|
118
|
-
end
|
114
|
+
SubjectClassMatcher.matches_subject_class?(@subjects, subject)
|
119
115
|
end
|
120
116
|
|
121
117
|
def parse_attributes_from_extra_args(args)
|
@@ -130,5 +126,15 @@ module CanCan
|
|
130
126
|
raise BlockAndConditionsError, 'A hash of conditions is mutually exclusive with a block. '\
|
131
127
|
"Check \":#{action} #{subject}\" ability."
|
132
128
|
end
|
129
|
+
|
130
|
+
def wrap(object)
|
131
|
+
if object.nil?
|
132
|
+
[]
|
133
|
+
elsif object.respond_to?(:to_ary)
|
134
|
+
object.to_ary || [object]
|
135
|
+
else
|
136
|
+
[object]
|
137
|
+
end
|
138
|
+
end
|
133
139
|
end
|
134
140
|
end
|
@@ -3,10 +3,12 @@
|
|
3
3
|
module CanCan
|
4
4
|
module UnauthorizedMessageResolver
|
5
5
|
def unauthorized_message(action, subject)
|
6
|
+
subject = subject.values.last if subject.is_a?(Hash)
|
6
7
|
keys = unauthorized_message_keys(action, subject)
|
7
|
-
variables = {
|
8
|
+
variables = {}
|
9
|
+
variables[:action] = I18n.translate("actions.#{action}", default: action.to_s)
|
8
10
|
variables[:subject] = translate_subject(subject)
|
9
|
-
message = I18n.translate(keys.shift, variables.merge(scope: :unauthorized, default: keys + ['']))
|
11
|
+
message = I18n.translate(keys.shift, **variables.merge(scope: :unauthorized, default: keys + ['']))
|
10
12
|
message.blank? ? nil : message
|
11
13
|
end
|
12
14
|
|
data/lib/cancan/version.rb
CHANGED
metadata
CHANGED
@@ -1,38 +1,38 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cancancan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alessandro Rodi (Renuo AG)
|
8
8
|
- Bryan Rite
|
9
9
|
- Ryan Bates
|
10
10
|
- Richard Wilson
|
11
|
-
autorequire:
|
11
|
+
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2020-12-29 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: appraisal
|
18
18
|
requirement: !ruby/object:Gem::Requirement
|
19
19
|
requirements:
|
20
|
-
- - "~>"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '2.0'
|
23
20
|
- - ">="
|
24
21
|
- !ruby/object:Gem::Version
|
25
22
|
version: 2.0.0
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '2.0'
|
26
26
|
type: :development
|
27
27
|
prerelease: false
|
28
28
|
version_requirements: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
|
-
- - "~>"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '2.0'
|
33
30
|
- - ">="
|
34
31
|
- !ruby/object:Gem::Version
|
35
32
|
version: 2.0.0
|
33
|
+
- - "~>"
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '2.0'
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: bundler
|
38
38
|
requirement: !ruby/object:Gem::Requirement
|
@@ -71,22 +71,22 @@ dependencies:
|
|
71
71
|
name: rspec
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
|
-
- - "~>"
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
version: '3.2'
|
77
74
|
- - ">="
|
78
75
|
- !ruby/object:Gem::Version
|
79
76
|
version: 3.2.0
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '3.2'
|
80
80
|
type: :development
|
81
81
|
prerelease: false
|
82
82
|
version_requirements: !ruby/object:Gem::Requirement
|
83
83
|
requirements:
|
84
|
-
- - "~>"
|
85
|
-
- !ruby/object:Gem::Version
|
86
|
-
version: '3.2'
|
87
84
|
- - ">="
|
88
85
|
- !ruby/object:Gem::Version
|
89
86
|
version: 3.2.0
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.2'
|
90
90
|
- !ruby/object:Gem::Dependency
|
91
91
|
name: rubocop
|
92
92
|
requirement: !ruby/object:Gem::Requirement
|
@@ -115,7 +115,9 @@ files:
|
|
115
115
|
- lib/cancan/ability/actions.rb
|
116
116
|
- lib/cancan/ability/rules.rb
|
117
117
|
- lib/cancan/ability/strong_parameter_support.rb
|
118
|
+
- lib/cancan/class_matcher.rb
|
118
119
|
- lib/cancan/conditions_matcher.rb
|
120
|
+
- lib/cancan/config.rb
|
119
121
|
- lib/cancan/controller_additions.rb
|
120
122
|
- lib/cancan/controller_resource.rb
|
121
123
|
- lib/cancan/controller_resource_builder.rb
|
@@ -132,8 +134,10 @@ files:
|
|
132
134
|
- lib/cancan/model_adapters/conditions_extractor.rb
|
133
135
|
- lib/cancan/model_adapters/conditions_normalizer.rb
|
134
136
|
- lib/cancan/model_adapters/default_adapter.rb
|
137
|
+
- lib/cancan/model_adapters/sti_normalizer.rb
|
135
138
|
- lib/cancan/model_additions.rb
|
136
139
|
- lib/cancan/parameter_validators.rb
|
140
|
+
- lib/cancan/relevant.rb
|
137
141
|
- lib/cancan/rule.rb
|
138
142
|
- lib/cancan/rules_compressor.rb
|
139
143
|
- lib/cancan/unauthorized_message_resolver.rb
|
@@ -146,7 +150,7 @@ homepage: https://github.com/CanCanCommunity/cancancan
|
|
146
150
|
licenses:
|
147
151
|
- MIT
|
148
152
|
metadata: {}
|
149
|
-
post_install_message:
|
153
|
+
post_install_message:
|
150
154
|
rdoc_options: []
|
151
155
|
require_paths:
|
152
156
|
- lib
|
@@ -161,9 +165,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
165
|
- !ruby/object:Gem::Version
|
162
166
|
version: '0'
|
163
167
|
requirements: []
|
164
|
-
|
165
|
-
|
166
|
-
signing_key:
|
168
|
+
rubygems_version: 3.0.6
|
169
|
+
signing_key:
|
167
170
|
specification_version: 4
|
168
171
|
summary: Simple authorization solution for Rails.
|
169
172
|
test_files: []
|