cancancan 3.0.2 → 3.3.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/cancancan.gemspec +1 -0
- data/lib/cancan.rb +2 -0
- data/lib/cancan/ability.rb +5 -1
- data/lib/cancan/ability/rules.rb +5 -2
- data/lib/cancan/class_matcher.rb +26 -0
- data/lib/cancan/conditions_matcher.rb +5 -2
- data/lib/cancan/config.rb +74 -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/sti_normalizer.rb +39 -0
- data/lib/cancan/model_additions.rb +4 -2
- data/lib/cancan/relevant.rb +29 -0
- data/lib/cancan/rule.rb +19 -15
- data/lib/cancan/unauthorized_message_resolver.rb +4 -2
- data/lib/cancan/version.rb +1 -1
- metadata +11 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4498ac94e1994faa4da80dc957d8c9564433d991048774f9ac2f051e60de580
|
4
|
+
data.tar.gz: 74209123c4c49adcd1d2d81df1de61c5f8cc2f243fdcdb4d01d3e41731e4c266
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb7774650d12a7073d09bb713f7eedfd7d376689f6d6bb842620b325a814720172f4fec900705bcc0dd3bd90818a88d2ab7e3904ea3a5d004533e13b4bed1c4c
|
7
|
+
data.tar.gz: a7a6fff07fbd7d52816dd960d00ae0baea7d50c5ed41d0abf32ac3a0c2b6bc3c557a4309944717b57aad785ad7dc394870c079b6a820b62798a373a9d9f8c2b0
|
data/cancancan.gemspec
CHANGED
@@ -10,6 +10,7 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.authors = ['Alessandro Rodi (Renuo AG)', 'Bryan Rite', 'Ryan Bates', 'Richard Wilson']
|
11
11
|
s.email = 'alessandro.rodi@renuo.ch'
|
12
12
|
s.homepage = 'https://github.com/CanCanCommunity/cancancan'
|
13
|
+
s.metadata = { 'funding_uri' => 'https://github.com/sponsors/coorasse' }
|
13
14
|
s.summary = 'Simple authorization solution for Rails.'
|
14
15
|
s.description = 'Simple authorization solution for Rails. All permissions are stored in a single location.'
|
15
16
|
s.platform = Gem::Platform::RUBY
|
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
|
data/lib/cancan/ability/rules.rb
CHANGED
@@ -19,12 +19,13 @@ module CanCan
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def add_rule_to_index(rule, position)
|
22
|
-
@rules_index ||=
|
22
|
+
@rules_index ||= {}
|
23
23
|
|
24
24
|
subjects = rule.subjects.compact
|
25
25
|
subjects << :all if subjects.empty?
|
26
26
|
|
27
27
|
subjects.each do |subject|
|
28
|
+
@rules_index[subject] ||= []
|
28
29
|
@rules_index[subject] << position
|
29
30
|
end
|
30
31
|
end
|
@@ -48,7 +49,9 @@ module CanCan
|
|
48
49
|
rules
|
49
50
|
else
|
50
51
|
positions = @rules_index.values_at(subject, *alternative_subjects(subject))
|
51
|
-
positions.
|
52
|
+
positions.compact!
|
53
|
+
positions.flatten!
|
54
|
+
positions.sort!
|
52
55
|
positions.map { |i| @rules[i] }
|
53
56
|
end
|
54
57
|
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
|
@@ -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,74 @@
|
|
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
|
+
return @accessible_by_strategy if @accessible_by_strategy
|
25
|
+
|
26
|
+
@accessible_by_strategy = default_accessible_by_strategy
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.default_accessible_by_strategy
|
30
|
+
if does_not_support_subquery_strategy?
|
31
|
+
# see https://github.com/CanCanCommunity/cancancan/pull/655 for where this was added
|
32
|
+
# the `subquery` strategy (from https://github.com/CanCanCommunity/cancancan/pull/619
|
33
|
+
# only works in Rails 5 and higher
|
34
|
+
:left_join
|
35
|
+
else
|
36
|
+
:subquery
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.accessible_by_strategy=(value)
|
41
|
+
validate_accessible_by_strategy!(value)
|
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.with_accessible_by_strategy(value)
|
51
|
+
return yield if value == accessible_by_strategy
|
52
|
+
|
53
|
+
validate_accessible_by_strategy!(value)
|
54
|
+
|
55
|
+
begin
|
56
|
+
strategy_was = accessible_by_strategy
|
57
|
+
@accessible_by_strategy = value
|
58
|
+
yield
|
59
|
+
ensure
|
60
|
+
@accessible_by_strategy = strategy_was
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.validate_accessible_by_strategy!(value)
|
65
|
+
return if valid_accessible_by_strategies.include?(value)
|
66
|
+
|
67
|
+
raise ArgumentError, "accessible_by_strategy must be one of #{valid_accessible_by_strategies.join(', ')}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.does_not_support_subquery_strategy?
|
71
|
+
!defined?(CanCan::ModelAdapters::ActiveRecordAdapter) ||
|
72
|
+
CanCan::ModelAdapters::ActiveRecordAdapter.version_lower?('5.0.0')
|
73
|
+
end
|
74
|
+
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
|
@@ -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
|
@@ -20,8 +20,10 @@ module CanCan
|
|
20
20
|
# @articles = Article.accessible_by(current_ability, :update)
|
21
21
|
#
|
22
22
|
# Here only the articles which the user can update are returned.
|
23
|
-
def accessible_by(ability, action = :index)
|
24
|
-
|
23
|
+
def accessible_by(ability, action = :index, strategy: CanCan.accessible_by_strategy)
|
24
|
+
CanCan.with_accessible_by_strategy(strategy) do
|
25
|
+
ability.model_adapter(self, action).database_records
|
26
|
+
end
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
@@ -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
|
@@ -57,12 +61,6 @@ module CanCan
|
|
57
61
|
(!with_scope? && [nil, false, [], {}, '', ' '].include?(@conditions))
|
58
62
|
end
|
59
63
|
|
60
|
-
# Matches both the action, subject, and attribute, not necessarily the conditions
|
61
|
-
def relevant?(action, subject)
|
62
|
-
subject = subject.values.first if subject.class == Hash
|
63
|
-
@match_all || (matches_action?(action) && matches_subject?(subject))
|
64
|
-
end
|
65
|
-
|
66
64
|
def only_block?
|
67
65
|
conditions_empty? && @block
|
68
66
|
end
|
@@ -113,11 +111,7 @@ module CanCan
|
|
113
111
|
end
|
114
112
|
|
115
113
|
def matches_subject_class?(subject)
|
116
|
-
@subjects
|
117
|
-
sub.is_a?(Module) && (subject.is_a?(sub) ||
|
118
|
-
subject.class.to_s == sub.to_s ||
|
119
|
-
(subject.is_a?(Module) && subject.ancestors.include?(sub)))
|
120
|
-
end
|
114
|
+
SubjectClassMatcher.matches_subject_class?(@subjects, subject)
|
121
115
|
end
|
122
116
|
|
123
117
|
def parse_attributes_from_extra_args(args)
|
@@ -132,5 +126,15 @@ module CanCan
|
|
132
126
|
raise BlockAndConditionsError, 'A hash of conditions is mutually exclusive with a block. '\
|
133
127
|
"Check \":#{action} #{subject}\" ability."
|
134
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
|
135
139
|
end
|
136
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,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cancancan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.3.0
|
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: 2021-06-21 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: appraisal
|
@@ -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
|
@@ -145,8 +149,9 @@ files:
|
|
145
149
|
homepage: https://github.com/CanCanCommunity/cancancan
|
146
150
|
licenses:
|
147
151
|
- MIT
|
148
|
-
metadata:
|
149
|
-
|
152
|
+
metadata:
|
153
|
+
funding_uri: https://github.com/sponsors/coorasse
|
154
|
+
post_install_message:
|
150
155
|
rdoc_options: []
|
151
156
|
require_paths:
|
152
157
|
- lib
|
@@ -162,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
162
167
|
version: '0'
|
163
168
|
requirements: []
|
164
169
|
rubygems_version: 3.0.6
|
165
|
-
signing_key:
|
170
|
+
signing_key:
|
166
171
|
specification_version: 4
|
167
172
|
summary: Simple authorization solution for Rails.
|
168
173
|
test_files: []
|