forest_admin_agent 1.0.0.pre.beta.31 → 1.0.0.pre.beta.32
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 +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
|