forest_admin_agent 1.9.1 → 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: d85148dc0247c3d0d74c458344980576ec7aa14772a8015d237b2b63cfdd88c3
4
- data.tar.gz: ba8f07da138797ad91f931ab56db345dd37d3f8ca13d95655b28af2180594b8b
3
+ metadata.gz: 7e8e0238988884b3db56ac66a0478dc662ea5fed4377d50b2de685f414c455cb
4
+ data.tar.gz: 7986a7262febae19442a08d0916362edd97ff655d2fad7f688d43babc14e8af1
5
5
  SHA512:
6
- metadata.gz: e4c49cc7ef501eeb34283106e9f21e12b992570afb17974ba30581d7076749d2d647e5bc539fc22145d75deaf693f547a7c1e2441285967244479cd40c44ffad
7
- data.tar.gz: 4468d234313447da09cbfb88907db657bc0ba51f238c5fa18c43aa45b274d59eb0593507838c1cd78c387a1ae6ec158d83e3f524823889ad13fc22c6c85af568
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
@@ -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.1"
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.1"
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.1
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthieu
@@ -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