fmrest-core 0.17.1 → 0.18.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: 4fe47fc97c28e7098accafef4a2974e959f8f910619fdec2177abb8048a9cf53
4
- data.tar.gz: 4439686866ddd5023f98b8d1651992fbb068e36b0872d47d66923303c2eeaee7
3
+ metadata.gz: fdfc316e5474cc3abbf196051aa48846f6b04452e0864a320445079a09a3f449
4
+ data.tar.gz: d23a6c290f33ab9c43f149de58af85825859aae9f0bc781200395bc883f66009
5
5
  SHA512:
6
- metadata.gz: f0d1c9af0e393ac39c7a4625afcf1301d9756116e511baf80f313cff15ffaa75bf1e4fbbbad60d548a8fe4101bfad59704aa0d40e08a334881cfec68ad823d7f
7
- data.tar.gz: c1e372106b999c00d93d83e8ae14ef5bf06b094c6c53eabca44ee7d56d1f1f67114614d0adc323c5b4b817494be14a5f25518e57a392f21c73aafa1130fe59f0
6
+ metadata.gz: 48ddb1505f075011675b5bfbeb437d42e70dff62912a6c44b0ac454c205332e8e61da6a628c0ae0cda095214d54dded125f8f98fa0af711d2e8e34b1d24332e1
7
+ data.tar.gz: 16623334ee707adb60e479d6db8bff23f22aa23cac397e32b839d4dceaa7aed4a2e94558684d08b1eaaa1fb008093b9628014a73b8b7dbe93f3d2cd1bc3498fc
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  ## Changelog
2
2
 
3
+ ### 0.18.0
4
+
5
+ * Better support for portals with mismatching field qualifiers
6
+ * Better ergonomics for script execution, improved documentation
7
+ * Defining an attribute on a model that would collide with an existing method
8
+ now raises an error
9
+ * Cleared Faraday deprecation messages on authentication methods
10
+ * Handle FileMaker Cloud case where HTTP 401 Unauthorized with content-type
11
+ text/html is returned after token expiry
12
+ * Add retry option to Rescuable mixin
13
+ * Added fmrest-ruby/VERSION to User-Agent headers
14
+
3
15
  ### 0.17.1
4
16
 
5
17
  * Fixed crash when `fmid_token` is set but `username` isn't
data/README.md CHANGED
@@ -543,6 +543,10 @@ class LoggyBee < FmRest::Layout
543
543
  end
544
544
  ```
545
545
 
546
+ ## Gotchas
547
+
548
+ Read about unexpected scenarios in the [gotchas doc](docs/Gotchas.md).
549
+
546
550
  ## API implementation completeness table
547
551
 
548
552
  FM Data API reference: https://fmhelp.filemaker.com/docs/18/en/dataapi/
@@ -8,7 +8,8 @@ module FmRest
8
8
  BASE_PATH = "/fmi/data/v1"
9
9
  DATABASES_PATH = "#{BASE_PATH}/databases"
10
10
 
11
- AUTH_HEADERS = { "Content-Type" => "application/json" }.freeze
11
+ DEFAULT_HEADERS = { "User-Agent" => "fmrest-ruby/#{::FmRest::VERSION} Faraday/#{::Faraday::VERSION}" }.freeze
12
+ AUTH_CONNECTION_HEADERS = DEFAULT_HEADERS.merge("Content-Type" => "application/json").freeze
12
13
  CLARIS_ID_HTTP_AUTH_TYPE = "FMID"
13
14
 
14
15
  # Builds a complete DAPI Faraday connection with middleware already
@@ -21,7 +22,7 @@ module FmRest
21
22
  def build_connection(settings = FmRest.default_connection_settings, &block)
22
23
  settings = ConnectionSettings.wrap(settings)
23
24
 
24
- base_connection(settings) do |conn|
25
+ base_connection(settings, headers: DEFAULT_HEADERS) do |conn|
25
26
  conn.use RaiseErrors
26
27
  conn.use TokenSession, settings
27
28
 
@@ -38,7 +39,7 @@ module FmRest
38
39
  yield conn, settings
39
40
  else
40
41
  conn.use TypeCoercer, settings
41
- conn.response :json
42
+ conn.response :json, content_type: /\bjson$/
42
43
  end
43
44
 
44
45
  if settings.log
@@ -56,20 +57,20 @@ module FmRest
56
57
  def auth_connection(settings = FmRest.default_connection_settings)
57
58
  settings = ConnectionSettings.wrap(settings)
58
59
 
59
- base_connection(settings, { headers: AUTH_HEADERS }) do |conn|
60
+ base_connection(settings, headers: AUTH_CONNECTION_HEADERS) do |conn|
60
61
  conn.use RaiseErrors
61
62
 
62
63
  if settings.fmid_token?
63
- conn.authorization CLARIS_ID_HTTP_AUTH_TYPE, settings.fmid_token
64
+ conn.request :authorization, CLARIS_ID_HTTP_AUTH_TYPE, settings.fmid_token
64
65
  else
65
- conn.basic_auth settings.username!, settings.password!
66
+ conn.request :basic_auth, settings.username!, settings.password!
66
67
  end
67
68
 
68
69
  if settings.log
69
70
  conn.response :logger, FmRest.logger, bodies: true, headers: true, log_level: settings.log_level
70
71
  end
71
72
 
72
- conn.response :json
73
+ conn.response :json, content_type: /\bjson$/
73
74
  conn.adapter Faraday.default_adapter
74
75
  end
75
76
  end
@@ -5,10 +5,9 @@ module FmRest
5
5
  # FM Data API response middleware for raising exceptions on API response
6
6
  # errors
7
7
  #
8
- # https://fmhelp.filemaker.com/help/17/fmp/en/index.html#page/FMP_Help/error-codes.html
9
- #
10
8
  class RaiseErrors < Faraday::Response::Middleware
11
- # https://fmhelp.filemaker.com/help/17/fmp/en/index.html#page/FMP_Help/error-codes.html
9
+ # Error codes reference:
10
+ # https://help.claris.com/en/pro-help/content/error-codes.html
12
11
  ERROR_RANGES = {
13
12
  -1 => APIError::UnknownError,
14
13
  100 => APIError::ResourceMissingError,
@@ -28,6 +27,17 @@ module FmRest
28
27
  }.freeze
29
28
 
30
29
  def on_complete(env)
30
+ # Sometimes, especially when using FileMaker Cloud, a failed
31
+ # authorization request will return a 401 (Unauthorized) with text/html
32
+ # content-type instead of the regular JSON, so we need to catch it
33
+ # manually here, emulating a regular account error
34
+ if !(/\bjson$/ === env.response_headers["content-type"]) && env.status == 401
35
+ raise FmRest::APIError::AccountError.new(212, "Authentication failed (HTTP 401: Unauthorized)")
36
+ end
37
+
38
+ # From this point on we want JSON
39
+ return unless env.body.is_a?(Hash)
40
+
31
41
  # Sniff for either straight JSON parsing or Spyke's format
32
42
  if env.body[:metadata] && env.body[:metadata][:messages]
33
43
  check_errors(env.body[:metadata][:messages])
@@ -132,7 +132,10 @@ module FmRest
132
132
  end
133
133
 
134
134
  def auth_connection
135
- @auth_connection ||= V1.auth_connection(@settings)
135
+ # NOTE: this is purposely not memoized so that settings can be
136
+ # refreshed (since proc-based settings will not be automatically
137
+ # re-eval'd, for example for fmid_token-based auth)
138
+ V1.auth_connection(@settings)
136
139
  end
137
140
  end
138
141
  end
@@ -21,7 +21,7 @@ module FmRest
21
21
 
22
22
  def on_complete(env)
23
23
  return unless enabled?
24
- return unless env.body.kind_of?(Hash)
24
+ return unless env.body.is_a?(Hash)
25
25
 
26
26
  data = env.body.dig("response", "data") || env.body.dig(:response, :data)
27
27
 
@@ -8,6 +8,8 @@ module FmRest
8
8
  # See https://help.claris.com/en/pro-help/content/finding-text.html
9
9
  FM_FIND_OPERATORS_RE = /([@\*#\?!=<>"])/
10
10
 
11
+ FULLY_QUALIFIED_FIELD_NAME_MATCHER = /\A[^:]+::[^:]+\Z/.freeze
12
+
11
13
  # Converts custom script options to a hash with the Data API's expected
12
14
  # JSON script format.
13
15
  #
@@ -104,6 +106,18 @@ module FmRest
104
106
  s.gsub(FM_FIND_OPERATORS_RE, "\\\\\\1")
105
107
  end
106
108
 
109
+ # Returns whether the given FileMaker field name is a fully-qualified
110
+ # name. In other words, whether it contains the string "::".
111
+ #
112
+ # Note that this is a simple naive check which doesn't account for
113
+ # invalid field names.
114
+ #
115
+ # @param field_name [String] The field name to test
116
+ # @return [Boolean] Whether the field is a FQN
117
+ def is_fully_qualified?(field_name)
118
+ FULLY_QUALIFIED_FIELD_NAME_MATCHER === field_name.to_s
119
+ end
120
+
107
121
  private
108
122
 
109
123
  def convert_script_arguments(script_arguments, suffix = nil)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FmRest
4
- VERSION = "0.17.1"
4
+ VERSION = "0.18.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fmrest-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.1
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pedro Carbajal
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-29 00:00:00.000000000 Z
11
+ date: 2021-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday