fmrest-core 0.17.1 → 0.18.0

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: 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