forest_admin_agent 1.0.0.pre.beta.31 → 1.0.0.pre.beta.32
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/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 +2 -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/query_string_parser.rb +3 -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: ba99d79966187d18f81f0e7672836a689bcbe38c5503587fe3ea720830671bb5
|
4
|
+
data.tar.gz: 03ff5cd137f8a4fcfb852ae791c0291cadd5765280f4a4d3c876970da55a9888
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2208d4c530f1bcca9a2e36bb0ce90f88ee1224ecaf795cfc9862449397d58ed5b131577d7f836498652d61080935db8744584198fcc2e961ed4e1d54c39cb94a
|
7
|
+
data.tar.gz: dda9a150ce25a95f4b1f4e88601003af2ca2b090e195bdefdd33803caf0a877f2d308431abc00f590929bc2af53962881ea66e42eed2b4ab5ed21c31e4827773
|
@@ -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
|
@@ -211,7 +211,7 @@ module ForestAdminAgent
|
|
211
211
|
|
212
212
|
return nil if actions.nil? || actions.empty?
|
213
213
|
|
214
|
-
action = actions.find { |a| a['endpoint'] == endpoint && a['
|
214
|
+
action = actions.find { |a| a['endpoint'] == endpoint && a['httpMethod'].casecmp(http_method).zero? }
|
215
215
|
|
216
216
|
raise ForestException, "The collection #{collection_name} does not have this smart action" if action.nil?
|
217
217
|
|
@@ -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
|
@@ -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
|
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.32
|
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-01 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
|