fmrest-core 0.15.1 → 0.17.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: a07e112df06f25f9e56c59ee74ebbb34c49cfe975154dd144e37874d299d6b9b
4
- data.tar.gz: af8d865853dae23bdd0191c75c7e1002045cbf79d53520475502699d417e1ae7
3
+ metadata.gz: 6ba93e217eb5159973fc3e82d06c9cfd395f9f2d1bd4cee1bc0f193f661303f1
4
+ data.tar.gz: 151da1d88185b7a12b23bd7e8067a52ca7209fb729367682789c9c26d29808f2
5
5
  SHA512:
6
- metadata.gz: 2b5d34680c8001f7b04f7fbacda46472a61721d7e7484603100cf5a3097f0a14cc275011cbbda08b8e025ce0314e6ef09ba94165a8c572080ac9f1d1425b0afb
7
- data.tar.gz: 7802ab476ce02f18c6cc5c494aa941125104a29580fc1d47abf5049b7049aa5c3518b38035147996dd63213643e5e157fb7602729cc0eb345126cd1d8db1865c
6
+ metadata.gz: 06ded09ca8619ae8428ec534355d61f6aaca6076aa2ff7d341e6f8ce0464c50d0568b8006512eec25d3afad9591cec06adc39a9da1f2813323a116fcee7e6a0d
7
+ data.tar.gz: 96dc882fc26b359a7a91ce547de4f6e25b050f9e1a201c69b447e9a3677709ee49c1f113739f431d86cb1701a7603dd490756ac467332648a0562fc33b79f822
data/CHANGELOG.md CHANGED
@@ -1,8 +1,19 @@
1
1
  ## Changelog
2
2
 
3
- ### 0.15.1
3
+ ### 0.17.0
4
4
 
5
- * Fix autoloading of `FmRest::Layout`
5
+ * Added support for Claris ID token login
6
+ * Added ability to use procs in settings
7
+ * Added `Rescuable` mixin
8
+
9
+ ### 0.16.0
10
+
11
+ * Added `FmRest.logger=`
12
+ * Handle serialization of `nil`, `true` and `false` values
13
+
14
+ ### 0.15.2
15
+
16
+ * Fixed autoloading of `FmRest::Layout`
6
17
 
7
18
  ### 0.15.0
8
19
 
@@ -18,13 +29,13 @@
18
29
 
19
30
  ### 0.13.1
20
31
 
21
- * Fix downloading of container field data from FMS19+
32
+ * Fixed downloading of container field data from FMS19+
22
33
 
23
34
  ### 0.13.0
24
35
 
25
36
  * Split `fmrest` gem into `fmrest-core` and `fmrest-spyke`. `fmrest` becomes a
26
37
  wrapper for the two new gems.
27
- * Fix bug preventing connection databases with spaces in their names.
38
+ * Fixed bug preventing connection databases with spaces in their names.
28
39
  * Improved portal support with ability to delete portal records, and better
29
40
  refreshing of portal records after saving the parent.
30
41
  * `FmRest::Spyke::Base#__record_id` and `FmRest::Spyke::Base#__mod_id` now
@@ -39,7 +50,7 @@
39
50
 
40
51
  ### 0.11.1
41
52
 
42
- * Fix a couple crashes due to missing constants
53
+ * Fixed a couple crashes due to missing constants
43
54
 
44
55
  ### 0.11.0
45
56
 
@@ -54,7 +65,7 @@
54
65
 
55
66
  ### 0.10.1
56
67
 
57
- * Fix `URI.escape` obsolete warning messages in Ruby 2.7 by replacing it with
68
+ * Fixed `URI.escape` obsolete warning messages in Ruby 2.7 by replacing it with
58
69
  `URI.encode_www_form_component`
59
70
  ([PR#40](https://github.com/beezwax/fmrest-ruby/pull/40))
60
71
 
@@ -128,20 +139,20 @@
128
139
 
129
140
  ### 0.3.2
130
141
 
131
- * Fix support for ActiveSupport < 5.2
142
+ * Fixed support for ActiveSupport < 5.2
132
143
  ([#27](https://github.com/beezwax/fmrest-ruby/issues/27))
133
144
 
134
145
  ### 0.3.0
135
146
 
136
- * Add Moneta token store
147
+ * Added Moneta token store
137
148
 
138
149
  ### 0.2.5
139
150
 
140
- * Fix crash in `fetch_container_data` when no proxy options were set
151
+ * Fixed crash in `fetch_container_data` when no proxy options were set
141
152
 
142
153
  ### 0.2.4
143
154
 
144
155
  * Use `String#=~` instead of `String#match?` for Ruby <2.4 compatibility (Fixes
145
156
  [#26](https://github.com/beezwax/fmrest-ruby/issues/26))
146
- * Deprecate `FmRest.config` in favor of `FmRest.default_connection_settings`
157
+ * Deprecated `FmRest.config` in favor of `FmRest.default_connection_settings`
147
158
  * Honor Faraday SSL and proxy settings when fetching container files
data/README.md CHANGED
@@ -125,6 +125,10 @@ The minimum required connection settings are `:host`, `:database`, `:username`
125
125
  and `:password`, but fmrest-ruby has many other options you can pass when
126
126
  setting up a connection (see [full list](#full-list-of-available-options) below).
127
127
 
128
+ If you're using FileMaker Cloud you may need to pass `:fmid_token` instead
129
+ of the regular `:username` and `:password`. See the [main document on
130
+ connecting to FileMaker Cloud](docs/FileMakerCloud.md) for more info.
131
+
128
132
  `:ssl` and `:proxy` are forwarded to the underlying
129
133
  [Faraday](https://github.com/lostisland/faraday) connection. You can use this
130
134
  to, for instance, disable SSL verification:
@@ -149,9 +153,11 @@ Option | Description | Format
149
153
  `:username` | A Data API-ready account | String | None
150
154
  `:password` | Your password | String | None
151
155
  `:account_name` | Alias of `:username` | String | None
156
+ `:fmid_token` | Claris ID token (only needed for FileMaker Cloud) | String | None
152
157
  `:ssl` | SSL options to be forwarded to Faraday | Faraday SSL options | None
153
158
  `:proxy` | Proxy options to be forwarded to Faraday | Faraday proxy options | None
154
159
  `:log` | Log JSON responses to STDOUT | Boolean | `false`
160
+ `:log_level` | Which log level to log into | Values accepted by `Logger#level=` | `:debug`
155
161
  `:coerce_dates` | See section on [date fields](#date-fields-and-timezones) | Boolean \| `:hybrid` \| `:full` | `false`
156
162
  `:date_format` | Date parsing format | String (FM date format) | `"MM/dd/yyyy"`
157
163
  `:timestamp_format` | Timestmap parsing format | String (FM date format) | `"MM/dd/yyyy HH:mm:ss"`
@@ -282,10 +288,12 @@ Also, if not set, your model will try to use
282
288
  #### Connection settings overlays
283
289
 
284
290
  There may be cases where you want to use a different set of connection settings
285
- depending on context. For example, if you want to use username and password
286
- provided by the user in a web application. Since `.fmrest_config`
287
- is set at the class level, changing the username/password for the model in one
288
- context would also change it in all other contexts, leading to security issues.
291
+ depending on context, or simply change the connection settings over time. For
292
+ example, if you want to use username and password provided by the user in a web
293
+ application, or if you're connecting using an expiring Claris ID token. Since
294
+ `.fmrest_config` is set at the class level, changing the username/password for
295
+ the model in one context would also change it in all other contexts, leading to
296
+ security issues.
289
297
 
290
298
  To solve this scenario, fmrest-ruby provides a way of defining thread-local and
291
299
  reversible connection settings overlays through
@@ -322,7 +330,7 @@ Requests a Data API session token using the connection settings in
322
330
 
323
331
  You normally don't need to use this method as fmrest-ruby will automatically
324
332
  request and store session tokens for you (provided that `:autologin` is
325
- `true`).
333
+ `true` in the connection settings, which it is by default).
326
334
 
327
335
  ### FmRest::Layout.logout
328
336
 
@@ -451,13 +459,48 @@ field values on the database that model is configured for.
451
459
  See the [main document on setting global field values](docs/GlobalFields.md)
452
460
  for details.
453
461
 
462
+ ### Rescuable mixin
463
+
464
+ Sometimes you may want to handle Data API errors at the model level. For
465
+ instance, if you're logging in to a file hosted by FileMaker Cloud using a
466
+ Claris ID token, and you want to be able to renew said token when it fails to
467
+ log you in. For such cases fmrest-ruby provides an off-by-default mixin called
468
+ `Rescuable` that provides convenience macros for that. If you've used Ruby on
469
+ Rails you may be familiar with its syntax from controllers. E.g.
470
+
471
+ ```ruby
472
+ class BeeBase < FmRest::Layout
473
+ include FmRest::Spyke::Model::Rescuable
474
+
475
+ rescue_from FmRest::APIError::SystemError, with: :notify_admin_of_system_error
476
+
477
+ # Shorthand for rescue_with FmRest::APIError::AccountError, ...
478
+ rescue_account_error { ClarisIDTokenManager.expire_token }
479
+
480
+ def self.notify_admin_of_system_error(e)
481
+ # Shoot an email to the FM admin...
482
+ end
483
+ end
484
+ ```
485
+
486
+ Since `Rescuable` uses `ActiveSupport::Rescuable` internally, you may want to
487
+ check [Rails'
488
+ documentation](https://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html)
489
+ too for details on how it works.
490
+
491
+ One caveat of using `rescue_from` is that it always catches exceptions at the
492
+ class level, so if you pass a method name to `with:` that method has to be a
493
+ class method. Also note that this will only catch exceptions raised during an
494
+ API call to the Data API server (in other words, only on actions that perform
495
+ an HTTP request).
496
+
454
497
  ## Logging
455
498
 
456
499
  If using `fmrest-spyke` with Rails then pretty log output will be set up for
457
500
  you automatically by Spyke (see [their
458
501
  README](https://github.com/balvig/spyke#log-output)).
459
502
 
460
- You can also enable simple Faraday STDOUT logging of raw requests (useful for
503
+ You can also enable simple Faraday logging of raw requests (useful for
461
504
  debugging) by passing `log: true` in the options hash for either
462
505
  `FmRest.default_connection_settings=` or your models' `fmrest_config=`, e.g.:
463
506
 
@@ -478,7 +521,17 @@ class LoggyBee < FmRest::Layout
478
521
  end
479
522
  ```
480
523
 
481
- If you need to set up more complex logging for your models can use the
524
+ You can also pass `log_level` to connection settings to change the severity of
525
+ log output (defaults to `:debug`).
526
+
527
+ By default fmrest-ruby logs to STDOUT or to Rails' logger object if available.
528
+ You can change this by providing your own logger object to `FmRest.logger=`:
529
+
530
+ ```ruby
531
+ FmRest.logger = Logger.new("fmrest.log")
532
+ ```
533
+
534
+ If you need to set up more complex logging for your models you can use the
482
535
  `faraday` block inside your class to inject your own logger middleware into the
483
536
  Faraday connection, e.g.:
484
537
 
@@ -499,7 +552,7 @@ FM Data API reference: https://fmhelp.filemaker.com/docs/18/en/dataapi/
499
552
  | Log in using HTTP Basic Auth | Yes | Yes |
500
553
  | Log in using OAuth | No | No |
501
554
  | Log in to an external data source | No | No |
502
- | Log in using a FileMaker ID account | No | No |
555
+ | Log in using Claris ID account | Yes | Yes |
503
556
  | Log out | Yes | Yes |
504
557
  | Get product information | Manual* | No |
505
558
  | Get database names | Manual* | No |
data/lib/fmrest.rb CHANGED
@@ -15,9 +15,13 @@ module FmRest
15
15
 
16
16
  class << self
17
17
  attr_accessor :token_store
18
+ attr_writer :logger
18
19
 
19
20
  def default_connection_settings=(settings)
20
- @default_connection_settings = ConnectionSettings.wrap(settings, skip_validation: true)
21
+ # Skip validation since we may use the defaults for half-complete
22
+ # settings
23
+ @default_connection_settings =
24
+ ConnectionSettings.wrap(settings, skip_validation: true)
21
25
  end
22
26
 
23
27
  def default_connection_settings
@@ -34,6 +38,15 @@ module FmRest
34
38
  default_connection_settings
35
39
  end
36
40
 
41
+ def logger
42
+ @logger ||= if defined?(Rails)
43
+ Rails.logger
44
+ else
45
+ require "logger"
46
+ Logger.new($stdout)
47
+ end
48
+ end
49
+
37
50
  # Shortcut for FmRest::V1.escape_find_operators
38
51
  #
39
52
  # @param (see FmRest::V1.escape_find_operators
@@ -41,5 +54,10 @@ module FmRest
41
54
  def e(s)
42
55
  V1.escape_find_operators(s)
43
56
  end
57
+
58
+ def Layout(*_)
59
+ require "fmrest/spyke"
60
+ self.Layout(*_)
61
+ end
44
62
  end
45
63
  end
@@ -18,12 +18,14 @@ module FmRest
18
18
  database
19
19
  username
20
20
  password
21
+ fmid_token
21
22
  token
22
23
  token_store
23
24
  autologin
24
25
  ssl
25
26
  proxy
26
27
  log
28
+ log_level
27
29
  coerce_dates
28
30
  date_format
29
31
  timestamp_format
@@ -45,6 +47,7 @@ module FmRest
45
47
  DEFAULTS = {
46
48
  autologin: true,
47
49
  log: false,
50
+ log_level: :debug,
48
51
  date_format: DEFAULT_DATE_FORMAT,
49
52
  time_format: DEFAULT_TIME_FORMAT,
50
53
  timestamp_format: DEFAULT_TIMESTAMP_FORMAT,
@@ -67,13 +70,12 @@ module FmRest
67
70
 
68
71
  PROPERTIES.each do |p|
69
72
  define_method(p) do
70
- get(p)
73
+ get_eval(p)
71
74
  end
72
75
 
73
76
  define_method("#{p}!") do
74
- r = get(p)
75
- raise MissingSetting, "Missing required setting: `#{p}'" if r.nil?
76
- r
77
+ raise MissingSetting, "Missing required setting: `#{p}'" if get(p).nil?
78
+ get_eval(p)
77
79
  end
78
80
 
79
81
  define_method("#{p}?") do
@@ -83,7 +85,7 @@ module FmRest
83
85
 
84
86
  def [](key)
85
87
  raise ArgumentError, "Unknown setting `#{key}'" unless PROPERTIES.include?(key.to_sym)
86
- get(key)
88
+ get_eval(key)
87
89
  end
88
90
 
89
91
  def to_h
@@ -102,13 +104,18 @@ module FmRest
102
104
  missing = REQUIRED.select { |r| get(r).nil? }.map { |m| "`#{m}'" }
103
105
  raise MissingSetting, "Missing required setting(s): #{missing.join(', ')}" unless missing.empty?
104
106
 
105
- unless username? || token?
106
- raise MissingSetting, "A minimum of `username' or `token' are required to be able to establish a connection"
107
+ unless username? || fmid_token? || token?
108
+ raise MissingSetting, "A minimum of `username', `fmid_token' or `token' are required to be able to establish a connection"
107
109
  end
108
110
  end
109
111
 
110
112
  private
111
113
 
114
+ def get_eval(key)
115
+ c = get(key)
116
+ c.kind_of?(Proc) ? c.call : c
117
+ end
118
+
112
119
  def get(key)
113
120
  return @settings[key.to_sym] if @settings.has_key?(key.to_sym)
114
121
  return @settings[key.to_s] if @settings.has_key?(key.to_s)
@@ -3,6 +3,8 @@
3
3
  module FmRest
4
4
  module V1
5
5
  module Auth
6
+ ACCESS_TOKEN_HEADER = "X-FM-Data-Access-Token"
7
+
6
8
  # Requests a token through basic auth
7
9
  #
8
10
  # @param connection [Faraday] the auth connection to use for
@@ -23,7 +25,7 @@ module FmRest
23
25
  # @raise [FmRest::APIError::AccountError] if authentication failed
24
26
  def request_auth_token!(connection = FmRest.V1.auth_connection)
25
27
  resp = connection.post(V1.session_path)
26
- resp.body["response"]["token"]
28
+ resp.headers[ACCESS_TOKEN_HEADER] || resp.body["response"]["token"]
27
29
  end
28
30
  end
29
31
  end
@@ -9,6 +9,7 @@ module FmRest
9
9
  DATABASES_PATH = "#{BASE_PATH}/databases"
10
10
 
11
11
  AUTH_HEADERS = { "Content-Type" => "application/json" }.freeze
12
+ CLARIS_ID_HTTP_AUTH_TYPE = "FMID"
12
13
 
13
14
  # Builds a complete DAPI Faraday connection with middleware already
14
15
  # configured to handle authentication, JSON parsing, logging and DAPI
@@ -41,7 +42,7 @@ module FmRest
41
42
  end
42
43
 
43
44
  if settings.log
44
- conn.response :logger, nil, bodies: true, headers: true
45
+ conn.response :logger, FmRest.logger, bodies: true, headers: true, log_level: settings.log_level
45
46
  end
46
47
 
47
48
  conn.adapter Faraday.default_adapter
@@ -58,10 +59,14 @@ module FmRest
58
59
  base_connection(settings, { headers: AUTH_HEADERS }) do |conn|
59
60
  conn.use RaiseErrors
60
61
 
61
- conn.basic_auth settings.username!, settings.password!
62
+ if settings.fmid_token?
63
+ conn.authorization CLARIS_ID_HTTP_AUTH_TYPE, settings.fmid_token
64
+ else
65
+ conn.basic_auth settings.username!, settings.password!
66
+ end
62
67
 
63
68
  if settings.log
64
- conn.response :logger, nil, bodies: true, headers: true
69
+ conn.response :logger, FmRest.logger, bodies: true, headers: true, log_level: settings.log_level
65
70
  end
66
71
 
67
72
  conn.response :json
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FmRest
4
- VERSION = "0.15.1"
4
+ VERSION = "0.17.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.15.1
4
+ version: 0.17.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-04-05 00:00:00.000000000 Z
11
+ date: 2021-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -108,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  requirements: []
111
- rubygems_version: 3.0.6
111
+ rubygems_version: 3.2.3
112
112
  signing_key:
113
113
  specification_version: 4
114
114
  summary: FileMaker Data API client using Faraday, core library