insights-api-common 3.7.0 → 3.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/insights/api/common/application_controller_mixins/parameters.rb +5 -1
- data/lib/insights/api/common/filter.rb +44 -21
- data/lib/insights/api/common/open_api/generator.rb +3 -9
- data/lib/insights/api/common/paginated_response_v2.rb +100 -10
- data/lib/insights/api/common/rbac/access.rb +47 -27
- data/lib/insights/api/common/rbac/service.rb +4 -4
- data/lib/insights/api/common/version.rb +1 -1
- data/spec/support/rbac_shared_contexts.rb +9 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d2889f1fb8a92c64f95de6f5d4a97f111d35e796a2ab4fb6a6b54ade5bbef05
|
4
|
+
data.tar.gz: 951defb8fb43a566b3f16b49e76f340d95d68f839831c1d6896b72c91dd0428d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37ea90782a5dad4f376bcc9b99f051394e855b02f4689c93c8049f7a292cf373da4e4f20f8730efd4f8830e6a680b14e61849c2bf3c5198104b5efb9c167b9ef
|
7
|
+
data.tar.gz: 8d331fdbfa57116010b32374e8dfc0ef016249336db7e86dc40d5f685f2f382ff2277064aea57dc9eca451e8be1248f40039828f97762358f3d0d7f9c121f9ed
|
@@ -90,7 +90,11 @@ module Insights
|
|
90
90
|
|
91
91
|
def filtered
|
92
92
|
check_if_openapi_enabled
|
93
|
-
Insights::API::Common::Filter.new(model, safe_params_for_list[:filter], api_doc_definition).apply
|
93
|
+
Insights::API::Common::Filter.new(model, safe_params_for_list[:filter], api_doc_definition, extra_attributes_for_filtering).apply
|
94
|
+
end
|
95
|
+
|
96
|
+
def extra_attributes_for_filtering
|
97
|
+
{}
|
94
98
|
end
|
95
99
|
|
96
100
|
def pagination_limit
|
@@ -5,13 +5,30 @@ module Insights
|
|
5
5
|
INTEGER_COMPARISON_KEYWORDS = ["eq", "gt", "gte", "lt", "lte", "nil", "not_nil"].freeze
|
6
6
|
STRING_COMPARISON_KEYWORDS = ["contains", "contains_i", "eq", "eq_i", "starts_with", "starts_with_i", "ends_with", "ends_with_i", "nil", "not_nil"].freeze
|
7
7
|
|
8
|
-
attr_reader :apply, :arel_table, :api_doc_definition
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
attr_reader :apply, :arel_table, :api_doc_definition, :extra_filterable_attributes, :model
|
9
|
+
|
10
|
+
# Instantiates a new Filter object
|
11
|
+
#
|
12
|
+
# == Parameters:
|
13
|
+
# model::
|
14
|
+
# An AR model that acts as the base collection to be filtered
|
15
|
+
# raw_filter::
|
16
|
+
# The filter from the request query string
|
17
|
+
# api_doc_definition::
|
18
|
+
# The documented object definition from the OpenAPI doc
|
19
|
+
# extra_filterable_attributes::
|
20
|
+
# Attributes that can be used for filtering but are not documented in the OpenAPI doc. Something like `{"undocumented_column" => {"type" => "string"}}`
|
21
|
+
#
|
22
|
+
# == Returns:
|
23
|
+
# A new Filter object, call #apply to get the filtered set of results.
|
24
|
+
#
|
25
|
+
def initialize(model, raw_filter, api_doc_definition, extra_filterable_attributes = {})
|
26
|
+
self.query = model
|
27
|
+
@api_doc_definition = api_doc_definition
|
28
|
+
@arel_table = model.arel_table
|
29
|
+
@extra_filterable_attributes = extra_filterable_attributes
|
30
|
+
@model = model
|
31
|
+
@raw_filter = raw_filter
|
15
32
|
end
|
16
33
|
|
17
34
|
def apply
|
@@ -34,11 +51,13 @@ module Insights
|
|
34
51
|
private
|
35
52
|
|
36
53
|
attr_accessor :query
|
54
|
+
delegate(:arel_attribute, :to => :model)
|
37
55
|
|
38
56
|
class Error < ArgumentError; end
|
39
57
|
|
40
58
|
def attribute_for_key(key)
|
41
59
|
attribute = api_doc_definition.properties[key.to_s]
|
60
|
+
attribute ||= extra_filterable_attributes[key.to_s]
|
42
61
|
return attribute if attribute
|
43
62
|
errors << "found unpermitted parameter: #{key}"
|
44
63
|
nil
|
@@ -108,66 +127,70 @@ module Insights
|
|
108
127
|
end
|
109
128
|
end
|
110
129
|
|
130
|
+
def arel_lower(key)
|
131
|
+
Arel::Nodes::NamedFunction.new("LOWER", [arel_attribute(key)])
|
132
|
+
end
|
133
|
+
|
111
134
|
def comparator_contains(key, value)
|
112
135
|
return value.each { |v| comparator_contains(key, v) } if value.kind_of?(Array)
|
113
136
|
|
114
|
-
self.query = query.where(
|
137
|
+
self.query = query.where(arel_attribute(key).matches("%#{query.sanitize_sql_like(value)}%", nil, true))
|
115
138
|
end
|
116
139
|
|
117
140
|
def comparator_contains_i(key, value)
|
118
141
|
return value.each { |v| comparator_contains_i(key, v) } if value.kind_of?(Array)
|
119
142
|
|
120
|
-
self.query = query.where(arel_table
|
143
|
+
self.query = query.where(arel_table.grouping(arel_lower(key).matches("%#{query.sanitize_sql_like(value.downcase)}%", nil, true)))
|
121
144
|
end
|
122
145
|
|
123
146
|
def comparator_starts_with(key, value)
|
124
|
-
self.query = query.where(
|
147
|
+
self.query = query.where(arel_attribute(key).matches("#{query.sanitize_sql_like(value)}%", nil, true))
|
125
148
|
end
|
126
149
|
|
127
150
|
def comparator_starts_with_i(key, value)
|
128
|
-
self.query = query.where(arel_table
|
151
|
+
self.query = query.where(arel_table.grouping(arel_lower(key).matches("#{query.sanitize_sql_like(value.downcase)}%", nil, true)))
|
129
152
|
end
|
130
153
|
|
131
154
|
def comparator_ends_with(key, value)
|
132
|
-
self.query = query.where(
|
155
|
+
self.query = query.where(arel_attribute(key).matches("%#{query.sanitize_sql_like(value)}", nil, true))
|
133
156
|
end
|
134
157
|
|
135
158
|
def comparator_ends_with_i(key, value)
|
136
|
-
self.query = query.where(arel_table
|
159
|
+
self.query = query.where(arel_table.grouping(arel_lower(key).matches("%#{query.sanitize_sql_like(value.downcase)}", nil, true)))
|
137
160
|
end
|
138
161
|
|
139
162
|
def comparator_eq(key, value)
|
140
|
-
self.query = query.where(key
|
163
|
+
self.query = query.where(arel_attribute(key).eq_any(Array(value)))
|
141
164
|
end
|
142
165
|
|
143
166
|
def comparator_eq_i(key, value)
|
144
167
|
values = Array(value).map { |v| query.sanitize_sql_like(v.downcase) }
|
145
168
|
|
146
|
-
self.query = query.where(arel_table
|
169
|
+
self.query = query.where(arel_table.grouping(arel_lower(key).matches_any(values)))
|
147
170
|
end
|
148
171
|
|
149
172
|
def comparator_gt(key, value)
|
150
|
-
self.query = query.where(
|
173
|
+
self.query = query.where(arel_attribute(key).gt(value))
|
151
174
|
end
|
152
175
|
|
153
176
|
def comparator_gte(key, value)
|
154
|
-
self.query = query.where(
|
177
|
+
self.query = query.where(arel_attribute(key).gteq(value))
|
155
178
|
end
|
156
179
|
|
157
180
|
def comparator_lt(key, value)
|
158
|
-
self.query = query.where(
|
181
|
+
self.query = query.where(arel_attribute(key).lt(value))
|
159
182
|
end
|
160
183
|
|
161
184
|
def comparator_lte(key, value)
|
162
|
-
self.query = query.where(
|
185
|
+
self.query = query.where(arel_attribute(key).lteq(value))
|
163
186
|
end
|
164
187
|
|
165
188
|
def comparator_nil(key, _value = nil)
|
166
|
-
self.query = query.where(key
|
189
|
+
self.query = query.where(arel_attribute(key).eq(nil))
|
167
190
|
end
|
168
191
|
|
169
192
|
def comparator_not_nil(key, _value = nil)
|
170
|
-
self.query = query.where.not(key
|
193
|
+
self.query = query.where.not(arel_attribute(key).eq(nil))
|
171
194
|
end
|
172
195
|
end
|
173
196
|
end
|
@@ -96,11 +96,6 @@ module Insights
|
|
96
96
|
"description" => "ID of the resource",
|
97
97
|
"pattern" => "^\\d+$",
|
98
98
|
"readOnly" => true,
|
99
|
-
},
|
100
|
-
"SortByAttribute" => {
|
101
|
-
"type" => "string",
|
102
|
-
"description" => "Attribute with optional order to sort the result set by.",
|
103
|
-
"pattern" => "^[a-z\\-_]+(:asc|:desc)?$"
|
104
99
|
}
|
105
100
|
}
|
106
101
|
end
|
@@ -179,11 +174,10 @@ module Insights
|
|
179
174
|
"name" => "sort_by",
|
180
175
|
"description" => "The list of attribute and order to sort the result set by.",
|
181
176
|
"required" => false,
|
177
|
+
"style" => "deepObject",
|
178
|
+
"explode" => true,
|
182
179
|
"schema" => {
|
183
|
-
"
|
184
|
-
{ "$ref" => "##{SCHEMAS_PATH}/SortByAttribute" },
|
185
|
-
{ "type" => "array", "items" => { "$ref" => "##{SCHEMAS_PATH}/SortByAttribute" } }
|
186
|
-
]
|
180
|
+
"type" => "object"
|
187
181
|
}
|
188
182
|
}
|
189
183
|
}
|
@@ -2,35 +2,125 @@ module Insights
|
|
2
2
|
module API
|
3
3
|
module Common
|
4
4
|
class PaginatedResponseV2 < PaginatedResponse
|
5
|
+
# GraphQL name regex: /[_A-Za-z][_0-9A-Za-z]*/
|
6
|
+
ASSOCIATION_COUNT_ATTR = "__count".freeze
|
7
|
+
|
5
8
|
attr_reader :limit, :offset, :sort_by
|
6
9
|
|
10
|
+
def records
|
11
|
+
@records ||= begin
|
12
|
+
res = @base_query.order(:id).limit(limit).offset(offset)
|
13
|
+
|
14
|
+
select_for_associations, group_by_associations = sort_by_associations_query_parameters
|
15
|
+
res = res.select(*select_for_associations) if select_for_associations.present?
|
16
|
+
res = res.left_outer_joins(*sort_by_associations) if sort_by_associations.present?
|
17
|
+
res = res.group(group_by_associations) if group_by_associations.present?
|
18
|
+
|
19
|
+
order_options = sort_by_options(res.klass)
|
20
|
+
res = res.reorder(order_options) if order_options.present?
|
21
|
+
res
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Condenses parameter values for handling multi-level associations
|
26
|
+
# and returns an array of key, value pairs.
|
27
|
+
#
|
28
|
+
# Examples:
|
29
|
+
#
|
30
|
+
# Input: { "association" => { "attribute" => "value" }, "direct_attribute" => "value2" }
|
31
|
+
# Output: [["association.attribute", "value"], ["direct_attribute", "value2"]]
|
32
|
+
#
|
33
|
+
# Input: { "association" => { "attribute" => "value" }, "association2" => { "attribute2" => "value2" } }
|
34
|
+
# Output: [["association.attribute", "value"], ["association2.attribute2", "value2"]]
|
35
|
+
#
|
36
|
+
# Input: { "association" => { "attribute1" => "value1", "attribute2" => "value2" } }
|
37
|
+
# Output: [["association.attribute1", "value1"], ["association.attribute2", "value2"]]
|
38
|
+
#
|
39
|
+
def compact_parameter(param)
|
40
|
+
result = []
|
41
|
+
return result if param.blank?
|
42
|
+
|
43
|
+
param.each do |k, v|
|
44
|
+
result += if v.kind_of?(Hash) || v.kind_of?(ActionController::Parameters)
|
45
|
+
Hash(v).map { |ak, av| ["#{k}.#{ak}", av] }
|
46
|
+
else
|
47
|
+
[[k, v]]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
7
53
|
private
|
8
54
|
|
9
55
|
def sort_by_options(model)
|
10
56
|
@sort_by_options ||= begin
|
11
|
-
|
12
|
-
return sort_options if sort_by.blank?
|
13
|
-
|
14
|
-
sort_by.each do |sort_attr, sort_order|
|
57
|
+
compact_parameter(sort_by).collect do |sort_attr, sort_order|
|
15
58
|
sort_order = "asc" if sort_order.blank?
|
16
|
-
arel =
|
17
|
-
|
18
|
-
|
59
|
+
arel = if sort_attr.include?('.')
|
60
|
+
association, sort_attr = sort_attr.split('.')
|
61
|
+
association_class = association.classify.constantize
|
62
|
+
if sort_attr == ASSOCIATION_COUNT_ATTR
|
63
|
+
Arel.sql("COUNT (#{association_class.table_name}.id)")
|
64
|
+
else
|
65
|
+
association_class.arel_attribute(sort_attr)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
model.arel_attribute(sort_attr)
|
69
|
+
end
|
70
|
+
(sort_order == "desc") ? arel.desc : arel.asc
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def sort_by_associations
|
76
|
+
@sort_by_associations ||= begin
|
77
|
+
compact_parameter(sort_by).collect do |sort_attr, sort_order|
|
78
|
+
next unless sort_attr.include?('.')
|
79
|
+
|
80
|
+
sort_attr.split('.').first.to_sym
|
81
|
+
end.compact.uniq
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def sort_by_associations_query_parameters
|
86
|
+
select_for_associations = []
|
87
|
+
group_by_associations = []
|
88
|
+
count_selects = []
|
89
|
+
|
90
|
+
compact_parameter(sort_by).each do |sort_attr, _sort_order|
|
91
|
+
next unless sort_attr.include?('.')
|
92
|
+
|
93
|
+
association, attr = sort_attr.split('.')
|
94
|
+
|
95
|
+
base_id = "#{@base_query.table_name}.id"
|
96
|
+
base_all = "#{@base_query.table_name}.*"
|
97
|
+
select_for_associations << base_id << base_all if select_for_associations.empty?
|
98
|
+
group_by_associations << base_id << base_all if group_by_associations.empty?
|
99
|
+
|
100
|
+
if attr == ASSOCIATION_COUNT_ATTR
|
101
|
+
count_selects << Arel.sql("COUNT (#{association.classify.constantize.table_name}.id)")
|
102
|
+
else
|
103
|
+
arel_attr = association.classify.constantize.arel_attribute(attr)
|
104
|
+
association_attr = "#{association}_#{attr}"
|
105
|
+
select_for_associations << arel_attr.as(association_attr)
|
106
|
+
group_by_associations << association_attr
|
19
107
|
end
|
20
|
-
sort_options
|
21
108
|
end
|
109
|
+
select_for_associations.append(*count_selects) unless count_selects.empty?
|
110
|
+
|
111
|
+
[select_for_associations.compact.uniq, group_by_associations.compact.uniq]
|
22
112
|
end
|
23
113
|
|
24
114
|
def validate_sort_by
|
25
115
|
return unless sort_by.present?
|
26
116
|
raise ArgumentError, "Invalid sort_by parameter specified \"#{sort_by}\"" unless sort_by.kind_of?(ActionController::Parameters) || sort_by.kind_of?(Hash)
|
27
117
|
|
28
|
-
sort_by.each { |sort_attr, sort_order| validate_sort_by_directive(sort_attr, sort_order) }
|
118
|
+
compact_parameter(sort_by).each { |sort_attr, sort_order| validate_sort_by_directive(sort_attr, sort_order) }
|
29
119
|
end
|
30
120
|
|
31
121
|
def validate_sort_by_directive(sort_attr, sort_order)
|
32
122
|
order = sort_order.blank? ? "asc" : sort_order
|
33
|
-
raise ArgumentError, "Invalid sort_by directive specified \"#{sort_attr}=#{sort_order}\"" unless sort_attr.match?(/^[a-z
|
123
|
+
raise ArgumentError, "Invalid sort_by directive specified \"#{sort_attr}=#{sort_order}\"" unless sort_attr.match?(/^[a-z\-_\.]+$/) && order.match?(/^(asc|desc)$/)
|
34
124
|
end
|
35
125
|
end
|
36
126
|
end
|
@@ -5,32 +5,45 @@ module Insights
|
|
5
5
|
class Access
|
6
6
|
attr_reader :acl
|
7
7
|
DEFAULT_LIMIT = 500
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
ADMIN_SCOPE = "admin"
|
9
|
+
GROUP_SCOPE = "group"
|
10
|
+
USER_SCOPE = "user"
|
11
|
+
|
12
|
+
def initialize(app_name_filter = ENV["APP_NAME"])
|
13
|
+
@app_name_filter = app_name_filter
|
13
14
|
end
|
14
15
|
|
15
16
|
def process
|
16
17
|
Service.call(RBACApiClient::AccessApi) do |api|
|
17
|
-
@
|
18
|
-
@regexp.match?(item.permission)
|
19
|
-
end
|
18
|
+
@acls ||= Service.paginate(api, :get_principal_access, {:limit => DEFAULT_LIMIT}, @app_name_filter).to_a
|
20
19
|
end
|
21
20
|
self
|
22
21
|
end
|
23
22
|
|
24
|
-
def
|
25
|
-
|
23
|
+
def scopes(resource, verb, app_name = ENV['APP_NAME'])
|
24
|
+
regexp = create_regexp(app_name, resource, verb)
|
25
|
+
@acls.each_with_object([]) do |item, memo|
|
26
|
+
if regexp.match?(item.permission)
|
27
|
+
memo << all_scopes(item)
|
28
|
+
end
|
29
|
+
end.flatten.uniq.sort
|
30
|
+
end
|
31
|
+
|
32
|
+
def accessible?(resource, verb, app_name = ENV['APP_NAME'])
|
33
|
+
regexp = create_regexp(app_name, resource, verb)
|
34
|
+
@acls.any? { |item| regexp.match?(item.permission) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def admin_scope?(resource, verb, app_name = ENV['APP_NAME'])
|
38
|
+
scope?(app_name, resource, verb, ADMIN_SCOPE)
|
26
39
|
end
|
27
40
|
|
28
|
-
def
|
29
|
-
|
41
|
+
def group_scope?(resource, verb, app_name = ENV['APP_NAME'])
|
42
|
+
scope?(app_name, resource, verb, GROUP_SCOPE)
|
30
43
|
end
|
31
44
|
|
32
|
-
def
|
33
|
-
|
45
|
+
def user_scope?(resource, verb, app_name = ENV['APP_NAME'])
|
46
|
+
scope?(app_name, resource, verb, USER_SCOPE)
|
34
47
|
end
|
35
48
|
|
36
49
|
def self.enabled?
|
@@ -39,26 +52,33 @@ module Insights
|
|
39
52
|
|
40
53
|
private
|
41
54
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
55
|
+
def scope?(app_name, resource, verb, scope)
|
56
|
+
regexp = create_regexp(app_name, resource, verb)
|
57
|
+
@acls.any? do |item|
|
58
|
+
regexp.match?(item.permission) && scope_matches?(item, scope)
|
59
|
+
end
|
60
|
+
end
|
47
61
|
|
48
|
-
|
49
|
-
|
62
|
+
def scope_matches?(item, scope)
|
63
|
+
item.resource_definitions.any? do |rd|
|
64
|
+
rd.attribute_filter.key == 'scope' &&
|
65
|
+
rd.attribute_filter.operation == 'equal' &&
|
66
|
+
rd.attribute_filter.value == scope
|
50
67
|
end
|
51
68
|
end
|
52
69
|
|
53
|
-
def
|
54
|
-
|
55
|
-
|
56
|
-
rd.attribute_filter.
|
57
|
-
|
58
|
-
rd.attribute_filter.value == '{{username}}'
|
70
|
+
def all_scopes(item)
|
71
|
+
item.resource_definitions.each_with_object([]) do |rd, memo|
|
72
|
+
if rd.attribute_filter.key == 'scope' &&
|
73
|
+
rd.attribute_filter.operation == 'equal'
|
74
|
+
memo << rd.attribute_filter.value
|
59
75
|
end
|
60
76
|
end
|
61
77
|
end
|
78
|
+
|
79
|
+
def create_regexp(app_name, resource, verb)
|
80
|
+
Regexp.new("(#{Regexp.escape(app_name)}):(#{Regexp.escape(resource)}):(#{Regexp.escape(verb)})")
|
81
|
+
end
|
62
82
|
end
|
63
83
|
end
|
64
84
|
end
|
@@ -8,9 +8,9 @@ module Insights
|
|
8
8
|
class TimedOutError < StandardError; end
|
9
9
|
|
10
10
|
class Service
|
11
|
-
def self.call(klass)
|
11
|
+
def self.call(klass, extra_headers = {})
|
12
12
|
setup
|
13
|
-
yield init(klass)
|
13
|
+
yield init(klass, extra_headers)
|
14
14
|
rescue RBACApiClient::ApiError => err
|
15
15
|
raise TimedOutError.new('Connection timed out') if err.code.nil?
|
16
16
|
raise NetworkError.new(err.message) if err.code.zero?
|
@@ -55,8 +55,8 @@ module Insights
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
private_class_method def self.init(klass)
|
59
|
-
headers = Insights::API::Common::Request.current_forwardable
|
58
|
+
private_class_method def self.init(klass, extra_headers)
|
59
|
+
headers = Insights::API::Common::Request.current_forwardable.merge(extra_headers)
|
60
60
|
klass.new.tap do |api|
|
61
61
|
api.api_client.default_headers = api.api_client.default_headers.merge(headers)
|
62
62
|
end
|
@@ -24,10 +24,19 @@ RSpec.shared_context "rbac_objects" do
|
|
24
24
|
let(:resource_def3) { instance_double(RBACApiClient::ResourceDefinition, :attribute_filter => filter3) }
|
25
25
|
let(:filter4) { instance_double(RBACApiClient::ResourceDefinitionFilter, :key => 'id', :operation => 'equal', :value => '*') }
|
26
26
|
let(:resource_def4) { instance_double(RBACApiClient::ResourceDefinition, :attribute_filter => filter4) }
|
27
|
+
let(:filter5) { instance_double(RBACApiClient::ResourceDefinitionFilter, :key => 'scope', :operation => 'equal', :value => 'admin') }
|
28
|
+
let(:resource_def5) { instance_double(RBACApiClient::ResourceDefinition, :attribute_filter => filter5) }
|
29
|
+
let(:filter6) { instance_double(RBACApiClient::ResourceDefinitionFilter, :key => 'scope', :operation => 'equal', :value => 'group') }
|
30
|
+
let(:resource_def6) { instance_double(RBACApiClient::ResourceDefinition, :attribute_filter => filter6) }
|
31
|
+
let(:filter7) { instance_double(RBACApiClient::ResourceDefinitionFilter, :key => 'scope', :operation => 'equal', :value => 'user') }
|
32
|
+
let(:resource_def7) { instance_double(RBACApiClient::ResourceDefinition, :attribute_filter => filter7) }
|
27
33
|
let(:access1) { instance_double(RBACApiClient::Access, :permission => "#{app_name}:#{resource}:read", :resource_definitions => [resource_def1]) }
|
28
34
|
let(:access2) { instance_double(RBACApiClient::Access, :permission => "#{app_name}:#{resource}:write", :resource_definitions => [resource_def2]) }
|
29
35
|
let(:access3) { instance_double(RBACApiClient::Access, :permission => "#{app_name}:#{resource}:order", :resource_definitions => []) }
|
30
36
|
let(:admin_access) { instance_double(RBACApiClient::Access, :permission => "#{app_name}:#{resource}:read", :resource_definitions => [resource_def4]) }
|
37
|
+
let(:admin_scope) { instance_double(RBACApiClient::Access, :permission => "#{app_name}:#{resource}:read", :resource_definitions => [resource_def5]) }
|
38
|
+
let(:group_scope) { instance_double(RBACApiClient::Access, :permission => "#{app_name}:#{resource}:read", :resource_definitions => [resource_def6]) }
|
39
|
+
let(:user_scope) { instance_double(RBACApiClient::Access, :permission => "#{app_name}:#{resource}:read", :resource_definitions => [resource_def7]) }
|
31
40
|
let(:group_uuids) { [group1.uuid, group2.uuid, group3.uuid] }
|
32
41
|
let(:api_instance) { double }
|
33
42
|
let(:rs_class) { class_double("Insights::API::Common::RBAC::Service").as_stubbed_const(:transfer_nested_constants => true) }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: insights-api-common
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Insights Authors
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: acts_as_tenant
|