forest_admin_agent 1.9.0 → 1.10.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: db02d65763186ba3ebdb9a253ca60c7a292c00f4b52d54e841be1ab4cd05702b
4
- data.tar.gz: 87bd836d1d1f461d7aed416d8bb43397067f1575331974df1ac59ec32bbb415d
3
+ metadata.gz: 7e8e0238988884b3db56ac66a0478dc662ea5fed4377d50b2de685f414c455cb
4
+ data.tar.gz: 7986a7262febae19442a08d0916362edd97ff655d2fad7f688d43babc14e8af1
5
5
  SHA512:
6
- metadata.gz: 241d1f8f861ed041334c14713018b0c0609d4193e4821c1d517975b1e780b57fc5e606fae505799f73393b700117e17cc53b8218b1a6595d71d238fc9d887cda
7
- data.tar.gz: 434548e00921d627fa800d10834980476afaf3bd3a3ef5e2e80bca7bd64263622284bae86c28449b3708ac507847ff8326c6029163164930564da7fd601eb385
6
+ metadata.gz: d1f931091e7e9e836208337f190bc0442e7543e55afd232ffc2c98331823f1f235fa71eeae574b13a907009756783fd3d17592fe7540f091a827cee9a2e44ad2
7
+ data.tar.gz: 69f51337fc2eb92f6eba5f0c0d1decd260f61bb2703975336cec22c857452bb87ecbc5bc1a914444e5ec38a9052430df35f579124c3ac7a55cef61fd21a0152a
@@ -20,6 +20,7 @@ module ForestAdminAgent
20
20
  Resources::Show.new.routes,
21
21
  Resources::Store.new.routes,
22
22
  Resources::Update.new.routes,
23
+ Resources::UpdateField.new.routes,
23
24
  Resources::Related::CsvRelated.new.routes,
24
25
  Resources::Related::ListRelated.new.routes,
25
26
  Resources::Related::CountRelated.new.routes,
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jsonapi-serializers'
4
+
5
+ module ForestAdminAgent
6
+ module Routes
7
+ module Resources
8
+ class UpdateField < AbstractAuthenticatedRoute
9
+ include ForestAdminAgent::Builder
10
+ include ForestAdminDatasourceToolkit::Components::Query
11
+ include ForestAdminDatasourceToolkit::Validations
12
+ include ForestAdminDatasourceToolkit::Schema
13
+
14
+ def setup_routes
15
+ add_route(
16
+ 'forest_update_field',
17
+ 'put',
18
+ '/:collection_name/:id/relationships/:field_name/:index',
19
+ ->(args) { handle_request(args) }
20
+ )
21
+
22
+ self
23
+ end
24
+
25
+ def handle_request(args = {})
26
+ build(args)
27
+
28
+ record_id = Utils::Id.unpack_id(@collection, args[:params]['id'], with_key: true)
29
+ field_name = args[:params]['field_name']
30
+ array_index = parse_index(args[:params]['index'])
31
+
32
+ @permissions.can?(:edit, @collection)
33
+
34
+ field_schema = @collection.schema[:fields][field_name]
35
+ validate_array_field!(field_schema, field_name)
36
+
37
+ record = fetch_record(record_id)
38
+
39
+ array = record[field_name]
40
+ validate_array_value!(array, field_name, array_index)
41
+
42
+ new_value = parse_value_from_body(args[:params], field_schema)
43
+
44
+ updated_array = array.dup
45
+ updated_array[array_index] = new_value
46
+
47
+ scope = @permissions.get_scope(@collection)
48
+ condition_tree = ConditionTree::ConditionTreeFactory.match_records(@collection, [record_id])
49
+ filter = ForestAdminDatasourceToolkit::Components::Query::Filter.new(
50
+ condition_tree: ConditionTree::ConditionTreeFactory.intersect([condition_tree, scope])
51
+ )
52
+ @collection.update(@caller, filter, { field_name => updated_array })
53
+
54
+ records = @collection.list(@caller, filter, ProjectionFactory.all(@collection))
55
+
56
+ {
57
+ name: args[:params]['collection_name'],
58
+ content: JSONAPI::Serializer.serialize(
59
+ records[0],
60
+ is_collection: false,
61
+ class_name: @collection.name,
62
+ serializer: Serializer::ForestSerializer
63
+ )
64
+ }
65
+ end
66
+
67
+ private
68
+
69
+ def parse_index(index_param)
70
+ index = Integer(index_param)
71
+ raise Http::Exceptions::ValidationError, 'Index must be non-negative' if index.negative?
72
+
73
+ index
74
+ rescue ArgumentError
75
+ raise Http::Exceptions::ValidationError, "Invalid index: #{index_param}"
76
+ end
77
+
78
+ def validate_array_field!(field_schema, field_name)
79
+ FieldValidator.validate(@collection, field_name)
80
+ return if field_schema.column_type.to_s.start_with?('[')
81
+
82
+ raise Http::Exceptions::ValidationError,
83
+ "Field '#{field_name}' is not an array (type: #{field_schema.column_type})"
84
+ rescue ForestAdminDatasourceToolkit::Exceptions::ValidationError => e
85
+ raise Http::Exceptions::NotFoundError, e.message if e.message.include?('not found')
86
+
87
+ raise Http::Exceptions::ValidationError, e.message
88
+ end
89
+
90
+ def fetch_record(record_id)
91
+ scope = @permissions.get_scope(@collection)
92
+ condition_tree = ConditionTree::ConditionTreeFactory.match_records(@collection, [record_id])
93
+ filter = ForestAdminDatasourceToolkit::Components::Query::Filter.new(
94
+ condition_tree: ConditionTree::ConditionTreeFactory.intersect([condition_tree, scope])
95
+ )
96
+ records = @collection.list(@caller, filter, ProjectionFactory.all(@collection))
97
+
98
+ raise Http::Exceptions::NotFoundError, 'Record not found' unless records&.any?
99
+
100
+ records[0]
101
+ end
102
+
103
+ def validate_array_value!(array, field_name, array_index)
104
+ unless array.is_a?(Array)
105
+ raise Http::Exceptions::UnprocessableError,
106
+ "Field '#{field_name}' value is not an array (got: #{array.class})"
107
+ end
108
+
109
+ return unless array_index >= array.length
110
+
111
+ raise Http::Exceptions::ValidationError,
112
+ "Index #{array_index} out of bounds for array of length #{array.length}"
113
+ end
114
+
115
+ def parse_value_from_body(params, field_schema)
116
+ body = params[:data] || {}
117
+ value = body.dig(:attributes, 'value') || body.dig(:attributes, :value)
118
+
119
+ coerce_value(value, field_schema.column_type)
120
+ end
121
+
122
+ def coerce_value(value, column_type)
123
+ return value unless column_type.to_s.start_with?('[') && column_type.to_s.end_with?(']')
124
+
125
+ element_type = column_type.to_s[1..-2]
126
+
127
+ if element_type == 'Number' && value.is_a?(String)
128
+ begin
129
+ return Float(value)
130
+ rescue ArgumentError
131
+ raise Http::Exceptions::ValidationError, "Cannot coerce '#{value}' to Number - wrong type"
132
+ end
133
+ end
134
+
135
+ value
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -87,7 +87,26 @@ module ForestAdminAgent
87
87
  def fetch_rules
88
88
  response = forest_api.get('/liana/v1/ip-whitelist-rules')
89
89
 
90
- body = JSON.parse(response.body)
90
+ unless response.status == 200
91
+ ForestAdminAgent::Facades::Container.logger.log('Error', {
92
+ error: "HTTP #{response.status}",
93
+ status: response.status,
94
+ response: response.body
95
+ })
96
+ raise ForestAdminAgent::Error, ForestAdminAgent::Utils::ErrorMessages::UNEXPECTED
97
+ end
98
+
99
+ begin
100
+ body = JSON.parse(response.body)
101
+ rescue JSON::ParserError => e
102
+ ForestAdminAgent::Facades::Container.logger.log('Error', {
103
+ error: e.message,
104
+ status: response.status,
105
+ response: response.body
106
+ })
107
+ raise ForestAdminAgent::Error, ForestAdminAgent::Utils::ErrorMessages::UNEXPECTED
108
+ end
109
+
91
110
  ip_whitelist_data = body['data']['attributes']
92
111
 
93
112
  @use_ip_whitelist = ip_whitelist_data['use_ip_whitelist']
@@ -27,7 +27,7 @@ module ForestAdminAgent
27
27
  field = collection.schema[:fields][pk_name]
28
28
  value = primary_key_values[index]
29
29
  casted_value = field.column_type == 'Number' ? value.to_i : value
30
- ForestAdminDatasourceToolkit::Validations::FieldValidator.validate_value(value, field, casted_value)
30
+ ForestAdminDatasourceToolkit::Validations::FieldValidator.validate_value(pk_name, field, casted_value)
31
31
 
32
32
  [pk_name, casted_value]
33
33
  end.to_h
@@ -6,7 +6,7 @@ module ForestAdminAgent
6
6
  module Schema
7
7
  class SchemaEmitter
8
8
  LIANA_NAME = "agent-ruby"
9
- LIANA_VERSION = "1.9.0"
9
+ LIANA_VERSION = "1.10.0"
10
10
 
11
11
  def self.generate(datasource)
12
12
  datasource.collections
@@ -1,3 +1,3 @@
1
1
  module ForestAdminAgent
2
- VERSION = "1.9.0"
2
+ VERSION = "1.10.0"
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.9.0
4
+ version: 1.10.0
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: 2025-10-20 00:00:00.000000000 Z
12
+ date: 2025-10-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -264,6 +264,7 @@ files:
264
264
  - lib/forest_admin_agent/routes/resources/show.rb
265
265
  - lib/forest_admin_agent/routes/resources/store.rb
266
266
  - lib/forest_admin_agent/routes/resources/update.rb
267
+ - lib/forest_admin_agent/routes/resources/update_field.rb
267
268
  - lib/forest_admin_agent/routes/security/authentication.rb
268
269
  - lib/forest_admin_agent/routes/security/scope_invalidation.rb
269
270
  - lib/forest_admin_agent/routes/system/health_check.rb