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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4743393dc5a51698d6ec25932119d4aae31242217e544edec5f4e20a9b6ef59f
4
- data.tar.gz: 6a392b579969712a8ecf97c40b937b61525c716d871283704247f05d4ad2758c
3
+ metadata.gz: a943d6f4ac59186bf4a2b032ffdd301d41239636408457c0d4f809633cc3ad49
4
+ data.tar.gz: a292ad6d5ffc8d1c65734729f0c31212a7a5157ffd5c93be2552cc19c3fbb092
5
5
  SHA512:
6
- metadata.gz: aadfe844b717ad56d665970d67c06d56116b3801aa3014e6ceabb4461f911a33622836f336e19d8300a179f8389df9c86adf9a3fcbf3891082be4b0bca2575db
7
- data.tar.gz: b07c6856de135844267526f7d091becdba8a7f72be56cbdd669b0a9297dd2e70eddec4f3238387295e1bbceadced2bdf292a08ab28b29c92a5f16113049593a2
6
+ metadata.gz: 407664d61c301ddaa40c049f52b7e58c5373ad73990f031e64f986349ca32dd45550787a3252d85f881486c61557507bfd09ec861f0f41d51bcb646250f80b56
7
+ data.tar.gz: 4b62bea51c7f25aaf6d2902e686b1280e8dcc019864c8c6848795846b2c9ee9aee92e0b0e53cb897b1485dbda2ed29161ea43ec0eccf4a45ec110e19c8440e38
@@ -5,8 +5,7 @@ module ForestAdminAgent
5
5
  attr_reader :name
6
6
 
7
7
  def initialize(message, name = 'ConflictError')
8
- @name = name
9
- super(429, 'Conflict', message)
8
+ super(429, message, name)
10
9
  end
11
10
  end
12
11
  end
@@ -5,8 +5,7 @@ module ForestAdminAgent
5
5
  attr_reader :name
6
6
 
7
7
  def initialize(message, name = 'ForbiddenError')
8
- @name = name
9
- super(403, 'Forbidden', message)
8
+ super(403, message, name)
10
9
  end
11
10
  end
12
11
  end
@@ -2,11 +2,10 @@ module ForestAdminAgent
2
2
  module Http
3
3
  module Exceptions
4
4
  class HttpException < StandardError
5
- attr_reader :code, :status, :message, :name
5
+ attr_reader :status, :message, :name
6
6
 
7
- def initialize(code, status, message, name = nil)
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
@@ -5,9 +5,8 @@ module ForestAdminAgent
5
5
  attr_reader :name, :data
6
6
 
7
7
  def initialize(message, name = 'RequireApproval', data = [])
8
- @name = name
8
+ super(403, message, name)
9
9
  @data = data
10
- super(403, 'Forbidden', message)
11
10
  end
12
11
  end
13
12
  end
@@ -0,0 +1,13 @@
1
+ module ForestAdminAgent
2
+ module Http
3
+ module Exceptions
4
+ class UnprocessableError < HttpException
5
+ attr_reader :name
6
+
7
+ def initialize(message = '', name = 'UnprocessableError')
8
+ super(422, message, name)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -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
- # TODO: permission
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[:name]],
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['http_method'].casecmp(http_method).zero? }
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 || smart_action[:selfApprovalEnabled].include?(role_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
- (rows[0]['value'] || 0) == attributes[:ids].count
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['operator'].titleize.tr(' ', '_')
14
+ operator = filters[:operator].titleize.tr(' ', '_')
15
15
  value = parse_value(collection, filters)
16
16
 
17
- return ConditionTreeLeaf.new(filters['field'], operator, value)
17
+ return ConditionTreeLeaf.new(filters[:field], operator, value)
18
18
  end
19
19
 
20
20
  if branch?(filters)
21
- aggregator = filters['aggregator'].capitalize
21
+ aggregator = filters[:aggregator].capitalize
22
22
  conditions = []
23
- filters['conditions'].each do |sub_tree|
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['field'])
35
- operator = leaf['operator'].titleize.tr(' ', '_')
34
+ schema = Collection.get_field_schema(collection, leaf[:field])
35
+ operator = leaf[:operator].titleize.tr(' ', '_')
36
36
 
37
- if operator == Operators::IN && leaf['field'].is_a?(String)
38
- values = leaf['value'].split(',').map(&:strip)
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['value']
47
+ leaf[:value]
48
48
  end
49
49
 
50
50
  def self.leaf?(filters)
51
- filters.key?('field') && filters.key?('operator')
51
+ filters.key?(:field) && filters.key?(:operator)
52
52
  end
53
53
 
54
54
  def self.branch?(filters)
55
- filters.key?('aggregator') && filters.key?('conditions')
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
- return user[:tags][context_variable_key[USER_VALUE_TAG_PREFIX.length..]]
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
@@ -7,7 +7,7 @@ module ForestAdminAgent
7
7
  class SchemaEmitter
8
8
  LIANA_NAME = "forest-rails"
9
9
 
10
- LIANA_VERSION = "1.0.0-beta.31"
10
+ LIANA_VERSION = "1.0.0-beta.33"
11
11
 
12
12
  def self.get_serialized_schema(datasource)
13
13
  schema_path = Facades::Container.cache(:schema_path)
@@ -1,3 +1,3 @@
1
1
  module ForestAdminAgent
2
- VERSION = "1.0.0-beta.31"
2
+ VERSION = "1.0.0-beta.33"
3
3
  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.31
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-02-22 00:00:00.000000000 Z
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