forest_admin_agent 1.0.0.pre.beta.31 → 1.0.0.pre.beta.33
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/forest_admin_agent/http/Exceptions/conflict_error.rb +1 -2
- data/lib/forest_admin_agent/http/Exceptions/forbidden_error.rb +1 -2
- data/lib/forest_admin_agent/http/Exceptions/http_exception.rb +2 -3
- data/lib/forest_admin_agent/http/Exceptions/require_approval.rb +1 -2
- data/lib/forest_admin_agent/http/Exceptions/unprocessable_error.rb +13 -0
- data/lib/forest_admin_agent/routes/action/action.rb +22 -1
- data/lib/forest_admin_agent/services/permissions.rb +5 -2
- data/lib/forest_admin_agent/services/smart_action_checker.rb +5 -5
- data/lib/forest_admin_agent/utils/condition_tree_parser.rb +11 -11
- data/lib/forest_admin_agent/utils/context_variables.rb +4 -1
- data/lib/forest_admin_agent/utils/query_string_parser.rb +15 -1
- data/lib/forest_admin_agent/utils/schema/schema_emitter.rb +1 -1
- data/lib/forest_admin_agent/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a943d6f4ac59186bf4a2b032ffdd301d41239636408457c0d4f809633cc3ad49
|
4
|
+
data.tar.gz: a292ad6d5ffc8d1c65734729f0c31212a7a5157ffd5c93be2552cc19c3fbb092
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 407664d61c301ddaa40c049f52b7e58c5373ad73990f031e64f986349ca32dd45550787a3252d85f881486c61557507bfd09ec861f0f41d51bcb646250f80b56
|
7
|
+
data.tar.gz: 4b62bea51c7f25aaf6d2902e686b1280e8dcc019864c8c6848795846b2c9ee9aee92e0b0e53cb897b1485dbda2ed29161ea43ec0eccf4a45ec110e19c8440e38
|
@@ -2,11 +2,10 @@ module ForestAdminAgent
|
|
2
2
|
module Http
|
3
3
|
module Exceptions
|
4
4
|
class HttpException < StandardError
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :status, :message, :name
|
6
6
|
|
7
|
-
def initialize(
|
7
|
+
def initialize(status, message, name = nil)
|
8
8
|
super(message)
|
9
|
-
@code = code
|
10
9
|
@status = status
|
11
10
|
@message = message
|
12
11
|
@name = name
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'jsonapi-serializers'
|
2
2
|
require 'active_support/inflector'
|
3
|
+
require 'jwt'
|
3
4
|
|
4
5
|
module ForestAdminAgent
|
5
6
|
module Routes
|
@@ -41,10 +42,11 @@ module ForestAdminAgent
|
|
41
42
|
|
42
43
|
def handle_request(args = {})
|
43
44
|
build(args)
|
45
|
+
args = middleware_custom_action_approval_request_data(args)
|
44
46
|
filter_for_caller = get_record_selection(args)
|
45
47
|
get_record_selection(args, include_user_scope: false)
|
46
48
|
|
47
|
-
|
49
|
+
@permissions.can_smart_action?(args, @collection, filter_for_caller)
|
48
50
|
|
49
51
|
raw_data = args.dig(:params, :data, :attributes, :values)
|
50
52
|
|
@@ -94,6 +96,25 @@ module ForestAdminAgent
|
|
94
96
|
|
95
97
|
private
|
96
98
|
|
99
|
+
def middleware_custom_action_approval_request_data(args)
|
100
|
+
raise Http::Exceptions::UnprocessableError if args.dig(:params, :data, :attributes, :requester_id)
|
101
|
+
|
102
|
+
if (signed_request = args.dig(:params, :data, :attributes, :signed_approval_request))
|
103
|
+
args[:params][:data][:attributes][:signed_approval_request] = decode_signed_approval_request(signed_request)
|
104
|
+
end
|
105
|
+
|
106
|
+
args
|
107
|
+
end
|
108
|
+
|
109
|
+
def decode_signed_approval_request(signed_request)
|
110
|
+
ForestAdminDatasourceToolkit::Utils::HashHelper.convert_keys(JWT.decode(
|
111
|
+
signed_request,
|
112
|
+
Facades::Container.cache(:env_secret),
|
113
|
+
true,
|
114
|
+
{ algorithm: 'HS256' }
|
115
|
+
)[0])
|
116
|
+
end
|
117
|
+
|
97
118
|
def get_record_selection(args, include_user_scope: true)
|
98
119
|
attributes = args.dig(:params, :data, :attributes)
|
99
120
|
|
@@ -86,7 +86,7 @@ module ForestAdminAgent
|
|
86
86
|
smart_action_approval = SmartActionChecker.new(
|
87
87
|
request[:params],
|
88
88
|
collection,
|
89
|
-
collections_data[collection.name.to_sym][:actions][action[
|
89
|
+
collections_data[collection.name.to_sym][:actions][action['name'].to_sym],
|
90
90
|
caller,
|
91
91
|
user_data[:roleId],
|
92
92
|
filter
|
@@ -103,6 +103,9 @@ module ForestAdminAgent
|
|
103
103
|
|
104
104
|
return nil if scope.nil?
|
105
105
|
|
106
|
+
team = get_team(caller.rendering_id)
|
107
|
+
user = get_user_data(caller.id)
|
108
|
+
|
106
109
|
context_variables = ContextVariables.new(team, user)
|
107
110
|
|
108
111
|
ContextVariablesInjector.inject_context_in_filter(scope, context_variables)
|
@@ -211,7 +214,7 @@ module ForestAdminAgent
|
|
211
214
|
|
212
215
|
return nil if actions.nil? || actions.empty?
|
213
216
|
|
214
|
-
action = actions.find { |a| a['endpoint'] == endpoint && a['
|
217
|
+
action = actions.find { |a| a['endpoint'] == endpoint && a['httpMethod'].casecmp(http_method).zero? }
|
215
218
|
|
216
219
|
raise ForestException, "The collection #{collection_name} does not have this smart action" if action.nil?
|
217
220
|
|
@@ -38,7 +38,8 @@ module ForestAdminAgent
|
|
38
38
|
def can_approve?
|
39
39
|
if smart_action[:userApprovalEnabled].include?(role_id) &&
|
40
40
|
(smart_action[:userApprovalConditions].empty? || match_conditions(:userApprovalConditions)) &&
|
41
|
-
(attributes[:requester_id] != caller.id ||
|
41
|
+
(attributes[:signed_approval_request][:data][:attributes][:requester_id] != caller.id ||
|
42
|
+
smart_action[:selfApprovalEnabled].include?(role_id))
|
42
43
|
return true
|
43
44
|
end
|
44
45
|
|
@@ -70,8 +71,7 @@ module ForestAdminAgent
|
|
70
71
|
else
|
71
72
|
Nodes::ConditionTreeLeaf.new(pk, 'IN', attributes[:ids])
|
72
73
|
end
|
73
|
-
|
74
|
-
condition = smart_action[condition_name][0]['filter']
|
74
|
+
condition = smart_action[condition_name][0][:filter]
|
75
75
|
conditional_filter = filter.override(
|
76
76
|
condition_tree: ConditionTreeFactory.intersect(
|
77
77
|
[
|
@@ -81,9 +81,9 @@ module ForestAdminAgent
|
|
81
81
|
]
|
82
82
|
)
|
83
83
|
)
|
84
|
-
rows = collection.aggregate(caller, conditional_filter, Aggregation.new(operation: 'Count'))
|
85
84
|
|
86
|
-
|
85
|
+
rows = collection.aggregate(caller, conditional_filter, Aggregation.new(operation: 'Count'))
|
86
|
+
(rows.empty? ? 0 : rows[0]['value']) == attributes[:ids].count
|
87
87
|
rescue StandardError
|
88
88
|
raise ConflictError.new(
|
89
89
|
'The conditions to trigger this action cannot be verified. Please contact an administrator.',
|
@@ -11,16 +11,16 @@ module ForestAdminAgent
|
|
11
11
|
|
12
12
|
def self.from_plain_object(collection, filters)
|
13
13
|
if leaf?(filters)
|
14
|
-
operator = filters[
|
14
|
+
operator = filters[:operator].titleize.tr(' ', '_')
|
15
15
|
value = parse_value(collection, filters)
|
16
16
|
|
17
|
-
return ConditionTreeLeaf.new(filters[
|
17
|
+
return ConditionTreeLeaf.new(filters[:field], operator, value)
|
18
18
|
end
|
19
19
|
|
20
20
|
if branch?(filters)
|
21
|
-
aggregator = filters[
|
21
|
+
aggregator = filters[:aggregator].capitalize
|
22
22
|
conditions = []
|
23
|
-
filters[
|
23
|
+
filters[:conditions].each do |sub_tree|
|
24
24
|
conditions << from_plain_object(collection, sub_tree)
|
25
25
|
end
|
26
26
|
|
@@ -31,11 +31,11 @@ module ForestAdminAgent
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def self.parse_value(collection, leaf)
|
34
|
-
schema = Collection.get_field_schema(collection, leaf[
|
35
|
-
operator = leaf[
|
34
|
+
schema = Collection.get_field_schema(collection, leaf[:field])
|
35
|
+
operator = leaf[:operator].titleize.tr(' ', '_')
|
36
36
|
|
37
|
-
if operator == Operators::IN && leaf[
|
38
|
-
values = leaf[
|
37
|
+
if operator == Operators::IN && leaf[:field].is_a?(String)
|
38
|
+
values = leaf[:value].split(',').map(&:strip)
|
39
39
|
|
40
40
|
return values.map { |item| !%w[false 0 no].include?(item) } if schema.column_type == 'Boolean'
|
41
41
|
|
@@ -44,15 +44,15 @@ module ForestAdminAgent
|
|
44
44
|
return values
|
45
45
|
end
|
46
46
|
|
47
|
-
leaf[
|
47
|
+
leaf[:value]
|
48
48
|
end
|
49
49
|
|
50
50
|
def self.leaf?(filters)
|
51
|
-
filters.key?(
|
51
|
+
filters.key?(:field) && filters.key?(:operator)
|
52
52
|
end
|
53
53
|
|
54
54
|
def self.branch?(filters)
|
55
|
-
filters.key?(
|
55
|
+
filters.key?(:aggregator) && filters.key?(:conditions)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -29,7 +29,10 @@ module ForestAdminAgent
|
|
29
29
|
end
|
30
30
|
|
31
31
|
if context_variable_key.start_with?(USER_VALUE_TAG_PREFIX)
|
32
|
-
|
32
|
+
user[:tags].each do |tag|
|
33
|
+
match_key = context_variable_key[USER_VALUE_TAG_PREFIX.length..]
|
34
|
+
return tag[match_key] if tag.key?(match_key)
|
35
|
+
end
|
33
36
|
end
|
34
37
|
|
35
38
|
user[context_variable_key[USER_VALUE_PREFIX.length..].to_sym]
|
@@ -22,7 +22,9 @@ module ForestAdminAgent
|
|
22
22
|
|
23
23
|
return if filters.nil?
|
24
24
|
|
25
|
-
filters = JSON.parse(filters) if filters.is_a? String
|
25
|
+
filters = JSON.parse(filters, symbolize_names: true) if filters.is_a? String
|
26
|
+
# TODO: add else for convert all keys to sym
|
27
|
+
|
26
28
|
ConditionTreeParser.from_plain_object(collection, filters)
|
27
29
|
# TODO: ConditionTreeValidator::validate($conditionTree, $collection);
|
28
30
|
end
|
@@ -102,6 +104,18 @@ module ForestAdminAgent
|
|
102
104
|
|
103
105
|
extended != '0'
|
104
106
|
end
|
107
|
+
|
108
|
+
def self.parse_sort(collection, args)
|
109
|
+
sort_string = args.dig(:params, :sort)
|
110
|
+
|
111
|
+
return SortUtils::SortFactory.by_primary_keys(collection) unless sort_string
|
112
|
+
|
113
|
+
sort = Sort.new([
|
114
|
+
{ field: sort_string.gsub(/^-/, '').tr('.', ':'), ascending: !sort_string.start_with?('-') }
|
115
|
+
])
|
116
|
+
|
117
|
+
ForestAdminDatasourceToolkit::Validations::SortValidator.validate(collection, sort)
|
118
|
+
end
|
105
119
|
end
|
106
120
|
end
|
107
121
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forest_admin_agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.beta.
|
4
|
+
version: 1.0.0.pre.beta.33
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthieu
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-
|
12
|
+
date: 2024-03-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -237,6 +237,7 @@ files:
|
|
237
237
|
- lib/forest_admin_agent/http/Exceptions/http_exception.rb
|
238
238
|
- lib/forest_admin_agent/http/Exceptions/not_found_error.rb
|
239
239
|
- lib/forest_admin_agent/http/Exceptions/require_approval.rb
|
240
|
+
- lib/forest_admin_agent/http/Exceptions/unprocessable_error.rb
|
240
241
|
- lib/forest_admin_agent/http/forest_admin_api_requester.rb
|
241
242
|
- lib/forest_admin_agent/http/router.rb
|
242
243
|
- lib/forest_admin_agent/routes/abstract_authenticated_route.rb
|