forest_admin_agent 1.37.0 → 1.37.1

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: dc6e61b3689e5c138ee42e22593c8c63b831c0ecdb1bd83c98eaf7906474b05e
4
- data.tar.gz: fa9601ceb32774b5238c78ad6afe7264e6814ea4b8a90bbc87fff720d8b58c79
3
+ metadata.gz: 5f51fef26a1f52081d72076f28f72f437b54a83098e102a42a6296762c9132b7
4
+ data.tar.gz: 21687f62160a1c9cec54ecd22ec825916b01b8e7dba199effa38155bf562d1f7
5
5
  SHA512:
6
- metadata.gz: 842fb4291fe4d103bdb227012e1eefcc2aee41ddf57d3524cf40c78d3497d0697f76007f418e06cc4b8c051f7bf337bbe634583f95affd00f928d556be3e1486
7
- data.tar.gz: 846cc2161f6e731dd6141279d99f3927953929881ae4a1b3770746d3bc94070a44507d4fddbb7d98c3b9a2810eb095dbfb51c64546ffbc6e5754c9a23a0aecea
6
+ metadata.gz: 2cfb0856639abffe732513e6cc01d94f91f7f26e251e211f56405b6b695410a77a66b767315ec5a775ce2f534629121bc44e9315389e5764e338c4da49e911eb
7
+ data.tar.gz: ca3e278582b7166879c261efffbd47e85ae991e1b18867b10ec4d8f05c0eed3505420a455cc3b393730eb8d0a9f16d1b61c422d50e9f198d4d4d75316ed913ce
@@ -13,6 +13,8 @@ module ForestAdminAgent
13
13
  attr_reader :customizer, :container, :has_env_secret
14
14
  attr_accessor :schema_only_mode
15
15
 
16
+ ENV_SECRET_FORMAT = /\A[0-9a-f]{64}\z/
17
+
16
18
  def initialize
17
19
  super
18
20
  @reloading = false
@@ -20,7 +22,7 @@ module ForestAdminAgent
20
22
 
21
23
  def setup(options)
22
24
  @options = options
23
- @has_env_secret = options.to_h.key?(:env_secret)
25
+ @has_env_secret = !options.to_h[:env_secret].nil?
24
26
  @customizer = ForestAdminDatasourceCustomizer::DatasourceCustomizer.new
25
27
  build_container
26
28
  build_cache
@@ -115,6 +117,7 @@ module ForestAdminAgent
115
117
  end
116
118
 
117
119
  return unless @has_env_secret
120
+ return unless secrets_format_valid?
118
121
 
119
122
  schema = generate_schema_file
120
123
 
@@ -127,7 +130,19 @@ module ForestAdminAgent
127
130
  end
128
131
  end
129
132
 
130
- post_schema(schema, force)
133
+ begin
134
+ post_schema(schema, force)
135
+ rescue StandardError => e
136
+ # A well-formed secret can still be rejected by the server (wrong project, revoked
137
+ # secret, network down, ...). Same rule as an invalid format: block boot in
138
+ # production, but never in dev - warn and move on instead. Scoped to this call
139
+ # only, so a local bug (a broken customization, an unwritable schema_path, ...)
140
+ # still surfaces immediately instead of being logged as a generic warning.
141
+ raise e if Facades::Container.cache(:is_production)
142
+
143
+ @logger.log('Warn', "[ForestAdmin] #{e.message}")
144
+ @logger.log('Warn', '[ForestAdmin] Schema sync failed, continuing without it.')
145
+ end
131
146
  end
132
147
 
133
148
  # Generates or loads the schema and writes it to file (in development mode).
@@ -175,6 +190,40 @@ module ForestAdminAgent
175
190
 
176
191
  private
177
192
 
193
+ # Checked from send_schema rather than setup, so that schema-only mode (which never
194
+ # syncs to the server) never fails on a secret it doesn't actually need.
195
+ def secrets_format_valid?
196
+ errors = secret_format_errors
197
+ return true if errors.empty?
198
+
199
+ if Facades::Container.cache(:is_production)
200
+ raise ForestAdminAgent::Http::Exceptions::ValidationError, errors.join(' ')
201
+ end
202
+
203
+ # Don't block boot on a config mistake in dev: warn loudly and skip the schema
204
+ # sync instead, so the developer can still work on the rest of the app.
205
+ errors.each { |error| @logger.log('Warn', "[ForestAdmin] #{error}") }
206
+ @logger.log('Warn', '[ForestAdmin] Skipping schema sync until this is fixed.')
207
+ false
208
+ end
209
+
210
+ def secret_format_errors
211
+ errors = []
212
+ env_secret = @options.to_h[:env_secret]
213
+
214
+ unless env_secret.is_a?(String) && env_secret.match?(ENV_SECRET_FORMAT)
215
+ errors << 'config.env_secret is invalid: it must be the 64-character hexadecimal secret from your ' \
216
+ 'Forest Admin project settings.'
217
+ end
218
+
219
+ auth_secret = @options.to_h[:auth_secret]
220
+ unless auth_secret.is_a?(String)
221
+ errors << 'config.auth_secret is invalid: it must be a string. Any long random value works.'
222
+ end
223
+
224
+ errors
225
+ end
226
+
178
227
  def container_replace(key, value)
179
228
  @container._container.delete(key.to_s)
180
229
  @container.register(key, value)
@@ -211,6 +260,7 @@ module ForestAdminAgent
211
260
 
212
261
  begin
213
262
  response = client.post('/forest/apimaps/hashcheck', { schemaFileHash: hash }.to_json)
263
+ client.raise_for_response!(response)
214
264
  body = JSON.parse(response.body)
215
265
  body['sendSchema']
216
266
  rescue JSON::ParserError => e
@@ -281,7 +331,8 @@ module ForestAdminAgent
281
331
  def send_schema_to_server(api_map)
282
332
  ForestAdminAgent::Facades::Container.logger.log('Info', 'schema was updated, sending new version')
283
333
  client = ForestAdminAgent::Http::ForestAdminApiRequester.new
284
- client.post('/forest/apimaps', api_map.to_json)
334
+ response = client.post('/forest/apimaps', api_map.to_json)
335
+ client.raise_for_response!(response)
285
336
  rescue Faraday::Error => e
286
337
  status = e.response[:status] if e.response
287
338
  if status
@@ -41,33 +41,48 @@ module ForestAdminAgent
41
41
  )
42
42
  end
43
43
 
44
- if error.response[:status].zero? || error.response[:status] == 502
44
+ raise_for_status(error.response[:status], cause: error)
45
+ end
46
+
47
+ # Faraday does not raise on HTTP error statuses here (no raise_error middleware
48
+ # configured), so a response has to be checked explicitly to turn e.g. an
49
+ # invalid envSecret (404) into the same typed errors as handle_response_error.
50
+ def raise_for_response!(response)
51
+ return if response.success?
52
+
53
+ raise_for_status(response.status, message: response.reason_phrase)
54
+ end
55
+
56
+ private
57
+
58
+ def raise_for_status(status, cause: nil, message: cause&.message)
59
+ if status.zero? || status == 502
45
60
  raise BadGatewayError.new(
46
61
  'Failed to reach ForestAdmin server. Are you online?',
47
- details: { status: error.response[:status] },
48
- cause: error
62
+ details: { status: status },
63
+ cause: cause
49
64
  )
50
65
  end
51
66
 
52
- if error.response[:status] == 404
67
+ if status == 404
53
68
  raise NotFoundError.new(
54
69
  'ForestAdmin server failed to find the project related to the envSecret you configured. Can you check that you copied it properly in the Forest initialization?',
55
- details: { status: error.response[:status] }
70
+ details: { status: status }
56
71
  )
57
72
  end
58
73
 
59
- if error.response[:status] == 503
74
+ if status == 503
60
75
  raise ServiceUnavailableError.new(
61
76
  'Forest is in maintenance for a few minutes. We are upgrading your experience in the forest. We just need a few more minutes to get it right.',
62
- details: { status: error.response[:status] },
63
- cause: error
77
+ details: { status: status },
78
+ cause: cause
64
79
  )
65
80
  end
66
81
 
67
82
  raise InternalServerError.new(
68
83
  'An unexpected error occurred while contacting the ForestAdmin server. Please contact support@forestadmin.com for further investigations.',
69
- details: { status: error.response[:status], message: error.message },
70
- cause: error
84
+ details: { status: status, message: message },
85
+ cause: cause
71
86
  )
72
87
  end
73
88
  end
@@ -6,7 +6,7 @@ module ForestAdminAgent
6
6
  module Schema
7
7
  class SchemaEmitter
8
8
  LIANA_NAME = "agent-ruby"
9
- LIANA_VERSION = "1.37.0"
9
+ LIANA_VERSION = "1.37.1"
10
10
 
11
11
  def self.generate(datasource)
12
12
  datasource.collections
@@ -1,3 +1,3 @@
1
1
  module ForestAdminAgent
2
- VERSION = "1.37.0"
2
+ VERSION = "1.37.1"
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.37.0
4
+ version: 1.37.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthieu