fmrest-core 0.16.0 → 0.18.0.rc1
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 +4 -4
- data/CHANGELOG.md +26 -10
- data/README.md +52 -6
- data/lib/fmrest/connection_settings.rb +12 -7
- data/lib/fmrest/v1/auth.rb +3 -1
- data/lib/fmrest/v1/connection.rb +6 -1
- data/lib/fmrest/v1/token_session.rb +7 -1
- data/lib/fmrest/v1/utils.rb +14 -0
- data/lib/fmrest/version.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27b42f06b36c99b967649c4257ea1b4df30e70f3e30efce3c1a82e74b511a368
|
4
|
+
data.tar.gz: 46cade48892b6cedca8f18fc40ccb88c3da2e1893bb09df020fcc0847782ede4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 79335b4c02f13f90dde6052998cd2f11e29ff4da10a6622b8d789f7ec443828afea5a869c10b7f40c79f10cf4b16b88f69691eab0e7605a6372b69ec24b07f6b
|
7
|
+
data.tar.gz: 7f3a11e55de51d92680a76812a63b6e3e2fa8ecbc3ac37949af7a365c67911d7867625781c4f5947c6079d1a99f31a499a354a3999d6d3415e5a08a982cc08a1
|
data/CHANGELOG.md
CHANGED
@@ -1,13 +1,29 @@
|
|
1
1
|
## Changelog
|
2
2
|
|
3
|
+
### 0.18.0
|
4
|
+
|
5
|
+
* Better support for portals with mismatching field qualifiers
|
6
|
+
* Defining an attribute on a model that would collide with an existing method
|
7
|
+
now raises an error
|
8
|
+
|
9
|
+
### 0.17.1
|
10
|
+
|
11
|
+
* Fixed crash when `fmid_token` is set but `username` isn't
|
12
|
+
|
13
|
+
### 0.17.0
|
14
|
+
|
15
|
+
* Added support for Claris ID token login
|
16
|
+
* Added ability to use procs in settings
|
17
|
+
* Added `Rescuable` mixin
|
18
|
+
|
3
19
|
### 0.16.0
|
4
20
|
|
5
|
-
*
|
21
|
+
* Added `FmRest.logger=`
|
6
22
|
* Handle serialization of `nil`, `true` and `false` values
|
7
23
|
|
8
24
|
### 0.15.2
|
9
25
|
|
10
|
-
*
|
26
|
+
* Fixed autoloading of `FmRest::Layout`
|
11
27
|
|
12
28
|
### 0.15.0
|
13
29
|
|
@@ -23,13 +39,13 @@
|
|
23
39
|
|
24
40
|
### 0.13.1
|
25
41
|
|
26
|
-
*
|
42
|
+
* Fixed downloading of container field data from FMS19+
|
27
43
|
|
28
44
|
### 0.13.0
|
29
45
|
|
30
46
|
* Split `fmrest` gem into `fmrest-core` and `fmrest-spyke`. `fmrest` becomes a
|
31
47
|
wrapper for the two new gems.
|
32
|
-
*
|
48
|
+
* Fixed bug preventing connection databases with spaces in their names.
|
33
49
|
* Improved portal support with ability to delete portal records, and better
|
34
50
|
refreshing of portal records after saving the parent.
|
35
51
|
* `FmRest::Spyke::Base#__record_id` and `FmRest::Spyke::Base#__mod_id` now
|
@@ -44,7 +60,7 @@
|
|
44
60
|
|
45
61
|
### 0.11.1
|
46
62
|
|
47
|
-
*
|
63
|
+
* Fixed a couple crashes due to missing constants
|
48
64
|
|
49
65
|
### 0.11.0
|
50
66
|
|
@@ -59,7 +75,7 @@
|
|
59
75
|
|
60
76
|
### 0.10.1
|
61
77
|
|
62
|
-
*
|
78
|
+
* Fixed `URI.escape` obsolete warning messages in Ruby 2.7 by replacing it with
|
63
79
|
`URI.encode_www_form_component`
|
64
80
|
([PR#40](https://github.com/beezwax/fmrest-ruby/pull/40))
|
65
81
|
|
@@ -133,20 +149,20 @@
|
|
133
149
|
|
134
150
|
### 0.3.2
|
135
151
|
|
136
|
-
*
|
152
|
+
* Fixed support for ActiveSupport < 5.2
|
137
153
|
([#27](https://github.com/beezwax/fmrest-ruby/issues/27))
|
138
154
|
|
139
155
|
### 0.3.0
|
140
156
|
|
141
|
-
*
|
157
|
+
* Added Moneta token store
|
142
158
|
|
143
159
|
### 0.2.5
|
144
160
|
|
145
|
-
*
|
161
|
+
* Fixed crash in `fetch_container_data` when no proxy options were set
|
146
162
|
|
147
163
|
### 0.2.4
|
148
164
|
|
149
165
|
* Use `String#=~` instead of `String#match?` for Ruby <2.4 compatibility (Fixes
|
150
166
|
[#26](https://github.com/beezwax/fmrest-ruby/issues/26))
|
151
|
-
*
|
167
|
+
* Deprecated `FmRest.config` in favor of `FmRest.default_connection_settings`
|
152
168
|
* 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,6 +153,7 @@ 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`
|
@@ -283,10 +288,12 @@ Also, if not set, your model will try to use
|
|
283
288
|
#### Connection settings overlays
|
284
289
|
|
285
290
|
There may be cases where you want to use a different set of connection settings
|
286
|
-
depending on context
|
287
|
-
provided by the user in a web
|
288
|
-
|
289
|
-
|
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.
|
290
297
|
|
291
298
|
To solve this scenario, fmrest-ruby provides a way of defining thread-local and
|
292
299
|
reversible connection settings overlays through
|
@@ -323,7 +330,7 @@ Requests a Data API session token using the connection settings in
|
|
323
330
|
|
324
331
|
You normally don't need to use this method as fmrest-ruby will automatically
|
325
332
|
request and store session tokens for you (provided that `:autologin` is
|
326
|
-
`true`).
|
333
|
+
`true` in the connection settings, which it is by default).
|
327
334
|
|
328
335
|
### FmRest::Layout.logout
|
329
336
|
|
@@ -452,6 +459,41 @@ field values on the database that model is configured for.
|
|
452
459
|
See the [main document on setting global field values](docs/GlobalFields.md)
|
453
460
|
for details.
|
454
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
|
+
|
455
497
|
## Logging
|
456
498
|
|
457
499
|
If using `fmrest-spyke` with Rails then pretty log output will be set up for
|
@@ -501,6 +543,10 @@ class LoggyBee < FmRest::Layout
|
|
501
543
|
end
|
502
544
|
```
|
503
545
|
|
546
|
+
## Gotchas
|
547
|
+
|
548
|
+
Read about unexpected scenarios in the [gotchas doc](docs/Gotchas.md).
|
549
|
+
|
504
550
|
## API implementation completeness table
|
505
551
|
|
506
552
|
FM Data API reference: https://fmhelp.filemaker.com/docs/18/en/dataapi/
|
@@ -510,7 +556,7 @@ FM Data API reference: https://fmhelp.filemaker.com/docs/18/en/dataapi/
|
|
510
556
|
| Log in using HTTP Basic Auth | Yes | Yes |
|
511
557
|
| Log in using OAuth | No | No |
|
512
558
|
| Log in to an external data source | No | No |
|
513
|
-
| Log in using
|
559
|
+
| Log in using Claris ID account | Yes | Yes |
|
514
560
|
| Log out | Yes | Yes |
|
515
561
|
| Get product information | Manual* | No |
|
516
562
|
| Get database names | Manual* | No |
|
@@ -18,6 +18,7 @@ module FmRest
|
|
18
18
|
database
|
19
19
|
username
|
20
20
|
password
|
21
|
+
fmid_token
|
21
22
|
token
|
22
23
|
token_store
|
23
24
|
autologin
|
@@ -69,13 +70,12 @@ module FmRest
|
|
69
70
|
|
70
71
|
PROPERTIES.each do |p|
|
71
72
|
define_method(p) do
|
72
|
-
|
73
|
+
get_eval(p)
|
73
74
|
end
|
74
75
|
|
75
76
|
define_method("#{p}!") do
|
76
|
-
|
77
|
-
|
78
|
-
r
|
77
|
+
raise MissingSetting, "Missing required setting: `#{p}'" if get(p).nil?
|
78
|
+
get_eval(p)
|
79
79
|
end
|
80
80
|
|
81
81
|
define_method("#{p}?") do
|
@@ -85,7 +85,7 @@ module FmRest
|
|
85
85
|
|
86
86
|
def [](key)
|
87
87
|
raise ArgumentError, "Unknown setting `#{key}'" unless PROPERTIES.include?(key.to_sym)
|
88
|
-
|
88
|
+
get_eval(key)
|
89
89
|
end
|
90
90
|
|
91
91
|
def to_h
|
@@ -104,13 +104,18 @@ module FmRest
|
|
104
104
|
missing = REQUIRED.select { |r| get(r).nil? }.map { |m| "`#{m}'" }
|
105
105
|
raise MissingSetting, "Missing required setting(s): #{missing.join(', ')}" unless missing.empty?
|
106
106
|
|
107
|
-
unless username? || token?
|
108
|
-
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"
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
112
|
private
|
113
113
|
|
114
|
+
def get_eval(key)
|
115
|
+
c = get(key)
|
116
|
+
c.kind_of?(Proc) ? c.call : c
|
117
|
+
end
|
118
|
+
|
114
119
|
def get(key)
|
115
120
|
return @settings[key.to_sym] if @settings.has_key?(key.to_sym)
|
116
121
|
return @settings[key.to_s] if @settings.has_key?(key.to_s)
|
data/lib/fmrest/v1/auth.rb
CHANGED
@@ -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
|
data/lib/fmrest/v1/connection.rb
CHANGED
@@ -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
|
@@ -58,7 +59,11 @@ module FmRest
|
|
58
59
|
base_connection(settings, { headers: AUTH_HEADERS }) do |conn|
|
59
60
|
conn.use RaiseErrors
|
60
61
|
|
61
|
-
|
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
69
|
conn.response :logger, FmRest.logger, bodies: true, headers: true, log_level: settings.log_level
|
@@ -100,7 +100,13 @@ module FmRest
|
|
100
100
|
# Strip the host part to just the hostname (i.e. no scheme or port)
|
101
101
|
host = @settings.host!
|
102
102
|
host = URI(host).hostname if host =~ /\Ahttps?:\/\//
|
103
|
-
|
103
|
+
identity_segment = if fmid_token = @settings.fmid_token
|
104
|
+
require "digest"
|
105
|
+
Digest::SHA256.hexdigest(fmid_token)
|
106
|
+
else
|
107
|
+
@settings.username!
|
108
|
+
end
|
109
|
+
"#{host}:#{@settings.database!}:#{identity_segment}"
|
104
110
|
end
|
105
111
|
end
|
106
112
|
|
data/lib/fmrest/v1/utils.rb
CHANGED
@@ -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)
|
data/lib/fmrest/version.rb
CHANGED
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.
|
4
|
+
version: 0.18.0.rc1
|
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-
|
11
|
+
date: 2021-09-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -104,11 +104,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
104
|
version: '0'
|
105
105
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
|
-
- - "
|
107
|
+
- - ">"
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version:
|
109
|
+
version: 1.3.1
|
110
110
|
requirements: []
|
111
|
-
rubygems_version: 3.
|
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
|