fmrest 0.1.0 → 0.2.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 +4 -4
- data/.gitignore +1 -0
- data/.yardopts +1 -0
- data/README.md +101 -7
- data/fmrest.gemspec +3 -0
- data/lib/fmrest.rb +2 -0
- data/lib/fmrest/errors.rb +27 -0
- data/lib/fmrest/spyke.rb +9 -0
- data/lib/fmrest/spyke/base.rb +2 -0
- data/lib/fmrest/spyke/container_field.rb +59 -0
- data/lib/fmrest/spyke/json_parser.rb +83 -24
- data/lib/fmrest/spyke/model.rb +7 -0
- data/lib/fmrest/spyke/model/associations.rb +2 -0
- data/lib/fmrest/spyke/model/attributes.rb +14 -55
- data/lib/fmrest/spyke/model/connection.rb +2 -0
- data/lib/fmrest/spyke/model/container_fields.rb +25 -0
- data/lib/fmrest/spyke/model/orm.rb +72 -5
- data/lib/fmrest/spyke/model/serialization.rb +80 -0
- data/lib/fmrest/spyke/model/uri.rb +2 -0
- data/lib/fmrest/spyke/portal.rb +2 -0
- data/lib/fmrest/spyke/relation.rb +30 -14
- data/lib/fmrest/token_store.rb +6 -0
- data/lib/fmrest/token_store/active_record.rb +74 -0
- data/lib/fmrest/token_store/base.rb +25 -0
- data/lib/fmrest/token_store/memory.rb +26 -0
- data/lib/fmrest/token_store/redis.rb +45 -0
- data/lib/fmrest/v1.rb +10 -49
- data/lib/fmrest/v1/connection.rb +57 -0
- data/lib/fmrest/v1/container_fields.rb +73 -0
- data/lib/fmrest/v1/paths.rb +36 -0
- data/lib/fmrest/v1/raise_errors.rb +55 -0
- data/lib/fmrest/v1/token_session.rb +32 -12
- data/lib/fmrest/v1/token_store/active_record.rb +6 -66
- data/lib/fmrest/v1/token_store/memory.rb +6 -19
- data/lib/fmrest/v1/utils.rb +94 -0
- data/lib/fmrest/version.rb +3 -1
- metadata +60 -5
- data/lib/fmrest/v1/token_store.rb +0 -6
- data/lib/fmrest/v1/token_store/base.rb +0 -14
@@ -1,9 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module FmRest
|
2
4
|
module V1
|
3
5
|
# FM Data API authentication middleware using the credentials strategy
|
4
6
|
#
|
5
7
|
class TokenSession < Faraday::Middleware
|
6
8
|
HEADER_KEY = "Authorization".freeze
|
9
|
+
TOKEN_STORE_INTERFACE = [:load, :store, :delete].freeze
|
7
10
|
|
8
11
|
def initialize(app, options = FmRest.config)
|
9
12
|
super(app)
|
@@ -20,7 +23,7 @@ module FmRest
|
|
20
23
|
@app.call(env).on_complete do |response_env|
|
21
24
|
if response_env[:status] == 401 # Unauthorized
|
22
25
|
env[:body] = request_body
|
23
|
-
token_store.
|
26
|
+
token_store.delete(token_store_key)
|
24
27
|
set_auth_header(env)
|
25
28
|
return @app.call(env)
|
26
29
|
end
|
@@ -38,11 +41,11 @@ module FmRest
|
|
38
41
|
# otherwise raises an exception.
|
39
42
|
#
|
40
43
|
def token
|
41
|
-
token = token_store.
|
44
|
+
token = token_store.load(token_store_key)
|
42
45
|
return token if token
|
43
46
|
|
44
47
|
if token = request_token
|
45
|
-
token_store.store(token)
|
48
|
+
token_store.store(token_store_key, token)
|
46
49
|
return token
|
47
50
|
end
|
48
51
|
|
@@ -61,19 +64,36 @@ module FmRest
|
|
61
64
|
false
|
62
65
|
end
|
63
66
|
|
64
|
-
|
65
|
-
|
67
|
+
# The key to use to store a token, uses the format host:database
|
68
|
+
#
|
69
|
+
def token_store_key
|
70
|
+
@token_store_key ||=
|
71
|
+
begin
|
72
|
+
# Strip the host part to just the hostname (i.e. no scheme or port)
|
73
|
+
host = @options.fetch(:host)
|
74
|
+
host = URI(host).hostname if host.match?(/\Ahttps?:\/\//)
|
75
|
+
"#{host}:#{@options.fetch(:database)}"
|
76
|
+
end
|
66
77
|
end
|
67
78
|
|
68
|
-
def
|
69
|
-
|
79
|
+
def token_store
|
80
|
+
@token_store ||=
|
70
81
|
begin
|
71
|
-
|
72
|
-
|
73
|
-
|
82
|
+
if TOKEN_STORE_INTERFACE.all? { |method| token_store_option.respond_to?(method) }
|
83
|
+
token_store_option
|
84
|
+
elsif token_store_option.kind_of?(Class)
|
85
|
+
token_store_option.new
|
86
|
+
else
|
87
|
+
require "fmrest/token_store/memory"
|
88
|
+
TokenStore::Memory.new
|
89
|
+
end
|
74
90
|
end
|
75
91
|
end
|
76
92
|
|
93
|
+
def token_store_option
|
94
|
+
@options[:token_store] || FmRest.token_store
|
95
|
+
end
|
96
|
+
|
77
97
|
def auth_connection
|
78
98
|
@auth_connection ||= V1.base_connection(@options) do |conn|
|
79
99
|
conn.basic_auth @options.fetch(:username), @options.fetch(:password)
|
@@ -82,8 +102,8 @@ module FmRest
|
|
82
102
|
conn.response :logger, nil, bodies: true, headers: true
|
83
103
|
end
|
84
104
|
|
85
|
-
conn.response
|
86
|
-
conn.adapter
|
105
|
+
conn.response :json
|
106
|
+
conn.adapter Faraday.default_adapter
|
87
107
|
end
|
88
108
|
end
|
89
109
|
end
|
@@ -1,73 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
warn "FmRest::V1::TokenStore::ActiveRecord is deprecated, use FmRest::TokenStore::ActiveRecord instead"
|
4
|
+
|
5
|
+
require "fmrest/token_store/active_record"
|
2
6
|
|
3
7
|
module FmRest
|
4
8
|
module V1
|
5
9
|
module TokenStore
|
6
|
-
|
7
|
-
#
|
8
|
-
# https://github.com/minad/moneta/blob/master/lib/moneta/adapters/activerecord.rb
|
9
|
-
#
|
10
|
-
class ActiveRecord < Base
|
11
|
-
DEFAULT_TABLE_NAME = "fmrest_session_tokens".freeze
|
12
|
-
|
13
|
-
@connection_lock = ::Mutex.new
|
14
|
-
class << self
|
15
|
-
attr_reader :connection_lock
|
16
|
-
end
|
17
|
-
|
18
|
-
attr_reader :connection_pool, :model
|
19
|
-
|
20
|
-
delegate :with_connection, to: :connection_pool
|
21
|
-
|
22
|
-
def initialize(host, database, options = {})
|
23
|
-
super
|
24
|
-
|
25
|
-
@connection_pool = ::ActiveRecord::Base.connection_pool
|
26
|
-
|
27
|
-
create_table
|
28
|
-
|
29
|
-
@model = Class.new(::ActiveRecord::Base)
|
30
|
-
@model.table_name = table_name
|
31
|
-
end
|
32
|
-
|
33
|
-
def clear
|
34
|
-
model.where(scope: scope).delete_all
|
35
|
-
end
|
36
|
-
|
37
|
-
def fetch
|
38
|
-
model.where(scope: scope).pluck(:token).first
|
39
|
-
end
|
40
|
-
|
41
|
-
def store(token)
|
42
|
-
record = model.find_or_initialize_by(scope: scope)
|
43
|
-
record.token = token
|
44
|
-
record.save!
|
45
|
-
token
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
def create_table
|
51
|
-
with_connection do |conn|
|
52
|
-
return if conn.table_exists?(table_name)
|
53
|
-
|
54
|
-
# Prevent multiple connections from attempting to create the table simultaneously.
|
55
|
-
self.class.connection_lock.synchronize do
|
56
|
-
conn.create_table(table_name, id: false) do |t|
|
57
|
-
t.string :scope, null: false
|
58
|
-
t.string :token, null: false
|
59
|
-
t.datetime :updated_at
|
60
|
-
end
|
61
|
-
conn.add_index(table_name, :scope, unique: true)
|
62
|
-
conn.add_index(table_name, [:scope, :token])
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def table_name
|
68
|
-
options[:table_name] || DEFAULT_TABLE_NAME
|
69
|
-
end
|
70
|
-
end
|
10
|
+
ActiveRecord = ::FmRest::TokenStore::ActiveRecord
|
71
11
|
end
|
72
12
|
end
|
73
13
|
end
|
@@ -1,26 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
warn "FmRest::V1::TokenStore::Memory is deprecated, use FmRest::TokenStore::Memory instead"
|
4
|
+
|
5
|
+
require "fmrest/token_store/memory"
|
2
6
|
|
3
7
|
module FmRest
|
4
8
|
module V1
|
5
9
|
module TokenStore
|
6
|
-
|
7
|
-
def initialize(host, database, options = {})
|
8
|
-
super
|
9
|
-
@tokens = {}
|
10
|
-
end
|
11
|
-
|
12
|
-
def clear
|
13
|
-
@tokens.delete(scope)
|
14
|
-
end
|
15
|
-
|
16
|
-
def fetch
|
17
|
-
@tokens[scope]
|
18
|
-
end
|
19
|
-
|
20
|
-
def store(token)
|
21
|
-
@tokens[scope] = token
|
22
|
-
end
|
23
|
-
end
|
10
|
+
Memory = ::FmRest::TokenStore::Memory
|
24
11
|
end
|
25
12
|
end
|
26
13
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FmRest
|
4
|
+
module V1
|
5
|
+
module Utils
|
6
|
+
VALID_SCRIPT_KEYS = [:prerequest, :presort, :after].freeze
|
7
|
+
|
8
|
+
# Converts custom script options to a hash with the Data API's expected
|
9
|
+
# JSON script format.
|
10
|
+
#
|
11
|
+
# If script_options is a string or symbol it will be passed as the name
|
12
|
+
# of the script to execute (after the action, e.g. save).
|
13
|
+
#
|
14
|
+
# If script_options is an array the first element will be the name of the
|
15
|
+
# script to execute (after the action) and the second element (if any)
|
16
|
+
# will be its param value.
|
17
|
+
#
|
18
|
+
# If script_options is a hash it will expect to contain one or more of
|
19
|
+
# the following keys: :prerequest, :presort, :after
|
20
|
+
#
|
21
|
+
# Any of those keys should contain either a string/symbol or array, which
|
22
|
+
# will be treated as described above, except for their own script
|
23
|
+
# execution order (prerequest, presort or after action).
|
24
|
+
#
|
25
|
+
# Examples:
|
26
|
+
#
|
27
|
+
# convert_script_params("My Script")
|
28
|
+
# # => { "script": "My Script" }
|
29
|
+
#
|
30
|
+
# convert_script_params(["My Script", "the param"])
|
31
|
+
# # => { "script": "My Script", "script.param": "the param" }
|
32
|
+
#
|
33
|
+
# convert_script_params(after: "After Script", prerequest: "Prerequest Script")
|
34
|
+
# # => { "script": "After Script", "script.prerequest": "Prerequest Script" }
|
35
|
+
#
|
36
|
+
# convert_script_params(presort: ["Presort Script", "foo"], prerequest: "Prerequest Script")
|
37
|
+
# # => {
|
38
|
+
# # "script.presort": "After Script",
|
39
|
+
# # "script.presort.param": "foo",
|
40
|
+
# # "script.prerequest": "Prerequest Script"
|
41
|
+
# # }
|
42
|
+
#
|
43
|
+
def convert_script_params(script_options)
|
44
|
+
params = {}
|
45
|
+
|
46
|
+
case script_options
|
47
|
+
when String, Symbol
|
48
|
+
params[:script] = script_options.to_s
|
49
|
+
|
50
|
+
when Array
|
51
|
+
params.merge!(convert_script_arguments(script_options))
|
52
|
+
|
53
|
+
when Hash
|
54
|
+
script_options.each_key do |key|
|
55
|
+
next if VALID_SCRIPT_KEYS.include?(key)
|
56
|
+
raise ArgumentError, "Invalid script option #{key.inspect}"
|
57
|
+
end
|
58
|
+
|
59
|
+
if script_options.has_key?(:prerequest)
|
60
|
+
params.merge!(convert_script_arguments(script_options[:prerequest], :prerequest))
|
61
|
+
end
|
62
|
+
|
63
|
+
if script_options.has_key?(:presort)
|
64
|
+
params.merge!(convert_script_arguments(script_options[:presort], :presort))
|
65
|
+
end
|
66
|
+
|
67
|
+
if script_options.has_key?(:after)
|
68
|
+
params.merge!(convert_script_arguments(script_options[:after]))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
params
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def convert_script_arguments(script_arguments, suffix = nil)
|
78
|
+
base = suffix ? "script.#{suffix}".to_sym : :script
|
79
|
+
|
80
|
+
{}.tap do |params|
|
81
|
+
case script_arguments
|
82
|
+
when String, Symbol
|
83
|
+
params[base] = script_arguments.to_s
|
84
|
+
when Array
|
85
|
+
params[base] = script_arguments.first.to_s
|
86
|
+
params["#{base}.param".to_sym] = script_arguments[1] if script_arguments[1]
|
87
|
+
else
|
88
|
+
raise ArgumentError, "Script arguments are expected as a String, Symbol or Array"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/fmrest/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fmrest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.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: 2019-
|
11
|
+
date: 2019-06-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -148,6 +148,48 @@ dependencies:
|
|
148
148
|
- - ">="
|
149
149
|
- !ruby/object:Gem::Version
|
150
150
|
version: '0'
|
151
|
+
- !ruby/object:Gem::Dependency
|
152
|
+
name: activerecord
|
153
|
+
requirement: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - ">="
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
type: :development
|
159
|
+
prerelease: false
|
160
|
+
version_requirements: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
- !ruby/object:Gem::Dependency
|
166
|
+
name: sqlite3
|
167
|
+
requirement: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - "~>"
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: 1.3.6
|
172
|
+
type: :development
|
173
|
+
prerelease: false
|
174
|
+
version_requirements: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - "~>"
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: 1.3.6
|
179
|
+
- !ruby/object:Gem::Dependency
|
180
|
+
name: mock_redis
|
181
|
+
requirement: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ">="
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
type: :development
|
187
|
+
prerelease: false
|
188
|
+
version_requirements: !ruby/object:Gem::Requirement
|
189
|
+
requirements:
|
190
|
+
- - ">="
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '0'
|
151
193
|
description: FileMaker Data API client using Faraday, with optional ActiveRecord-like
|
152
194
|
ORM based on Spyke
|
153
195
|
email:
|
@@ -159,6 +201,7 @@ files:
|
|
159
201
|
- ".gitignore"
|
160
202
|
- ".rspec"
|
161
203
|
- ".travis.yml"
|
204
|
+
- ".yardopts"
|
162
205
|
- CODE_OF_CONDUCT.md
|
163
206
|
- Gemfile
|
164
207
|
- LICENSE.txt
|
@@ -166,23 +209,35 @@ files:
|
|
166
209
|
- Rakefile
|
167
210
|
- fmrest.gemspec
|
168
211
|
- lib/fmrest.rb
|
212
|
+
- lib/fmrest/errors.rb
|
169
213
|
- lib/fmrest/spyke.rb
|
170
214
|
- lib/fmrest/spyke/base.rb
|
215
|
+
- lib/fmrest/spyke/container_field.rb
|
171
216
|
- lib/fmrest/spyke/json_parser.rb
|
172
217
|
- lib/fmrest/spyke/model.rb
|
173
218
|
- lib/fmrest/spyke/model/associations.rb
|
174
219
|
- lib/fmrest/spyke/model/attributes.rb
|
175
220
|
- lib/fmrest/spyke/model/connection.rb
|
221
|
+
- lib/fmrest/spyke/model/container_fields.rb
|
176
222
|
- lib/fmrest/spyke/model/orm.rb
|
223
|
+
- lib/fmrest/spyke/model/serialization.rb
|
177
224
|
- lib/fmrest/spyke/model/uri.rb
|
178
225
|
- lib/fmrest/spyke/portal.rb
|
179
226
|
- lib/fmrest/spyke/relation.rb
|
227
|
+
- lib/fmrest/token_store.rb
|
228
|
+
- lib/fmrest/token_store/active_record.rb
|
229
|
+
- lib/fmrest/token_store/base.rb
|
230
|
+
- lib/fmrest/token_store/memory.rb
|
231
|
+
- lib/fmrest/token_store/redis.rb
|
180
232
|
- lib/fmrest/v1.rb
|
233
|
+
- lib/fmrest/v1/connection.rb
|
234
|
+
- lib/fmrest/v1/container_fields.rb
|
235
|
+
- lib/fmrest/v1/paths.rb
|
236
|
+
- lib/fmrest/v1/raise_errors.rb
|
181
237
|
- lib/fmrest/v1/token_session.rb
|
182
|
-
- lib/fmrest/v1/token_store.rb
|
183
238
|
- lib/fmrest/v1/token_store/active_record.rb
|
184
|
-
- lib/fmrest/v1/token_store/base.rb
|
185
239
|
- lib/fmrest/v1/token_store/memory.rb
|
240
|
+
- lib/fmrest/v1/utils.rb
|
186
241
|
- lib/fmrest/version.rb
|
187
242
|
homepage: https://github.com/beezwax/fmrest-ruby
|
188
243
|
licenses:
|
@@ -204,7 +259,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
259
|
version: '0'
|
205
260
|
requirements: []
|
206
261
|
rubyforge_project:
|
207
|
-
rubygems_version: 2.7.
|
262
|
+
rubygems_version: 2.7.8
|
208
263
|
signing_key:
|
209
264
|
specification_version: 4
|
210
265
|
summary: FileMaker Data API client using Faraday
|