smartcar 3.2.0 → 3.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -1
- data/Gemfile.lock +1 -1
- data/README.md +5 -1
- data/lib/smartcar/auth_client.rb +29 -17
- data/lib/smartcar/base.rb +2 -12
- data/lib/smartcar/utils.rb +20 -0
- data/lib/smartcar/vehicle.rb +11 -8
- data/lib/smartcar/version.rb +1 -1
- data/lib/smartcar.rb +21 -16
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe729c83b0d759f2d787090e3f815ec9d97cd0b283585f8775ebe16e61b16e56
|
4
|
+
data.tar.gz: '029284bb31e8363b2cd0fe751705749e19365fb5692cbc3054325d648440117e'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e469fcb92c39256e4a779476217fdb7cd5cce276af14d61ac9a51054e5d5e485f70e8f7886fb1852d2fb9d8128edd9b85164303f7c36fdca9d919f50bb0f4cb
|
7
|
+
data.tar.gz: faf78f8b977e3548e9f44fa45a59ce3b26cc89de53e6d85f3a8bc5391ced3031bdb2801696cb237cc2bb8c801bf85f7d2dd5bb6f15ccf2904430c65549c8ac86
|
data/.rubocop.yml
CHANGED
@@ -12,7 +12,7 @@ Naming/AccessorMethodName:
|
|
12
12
|
Enabled: false
|
13
13
|
|
14
14
|
# Disabling this until we figure out a better way than using openstruct
|
15
|
-
# Currently we use open struct because this gives us an object representing the JSON
|
15
|
+
# Currently we use open struct because this gives us an object representing the JSON
|
16
16
|
# with accessor style methods.
|
17
17
|
Style/OpenStructUse:
|
18
18
|
Enabled: false
|
@@ -30,3 +30,9 @@ Metrics/MethodLength:
|
|
30
30
|
|
31
31
|
Metrics/ClassLength:
|
32
32
|
Max: 200
|
33
|
+
|
34
|
+
Metrics/CyclomaticComplexity:
|
35
|
+
Max: 10
|
36
|
+
|
37
|
+
Metrics/PerceivedComplexity:
|
38
|
+
Max: 10
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -31,6 +31,7 @@ not have access to the dashboard, please
|
|
31
31
|
|
32
32
|
- Create a new `AuthClient` object with your `client_id`, `client_secret`,
|
33
33
|
`redirect_uri`.
|
34
|
+
-
|
34
35
|
- Redirect the user to Smartcar Connect using `get_auth_url` with required `scope` or with one
|
35
36
|
of our frontend SDKs.
|
36
37
|
- The user will login, and then accept or deny your `scope`'s permissions.
|
@@ -76,6 +77,9 @@ Setup the environment variables for SMARTCAR_CLIENT_ID, SMARTCAR_CLIENT_SECRET a
|
|
76
77
|
export SMARTCAR_CLIENT_ID=<client id>
|
77
78
|
export SMARTCAR_CLIENT_SECRET=<client secret>
|
78
79
|
export SMARTCAR_REDIRECT_URI=<redirect URI>
|
80
|
+
# Optional ENV variables
|
81
|
+
export SMARTCAR_CONNECT_ORIGIN=(default_value: connect.smartcar.com): Used as the host for the URL that starts the Connect/OAuth2 flow
|
82
|
+
export SMARTCAR_AUTH_ORIGIN=(default_value: auth.smartcar.com): Used as the host for the token exchange requests
|
79
83
|
```
|
80
84
|
|
81
85
|
Example Usage for calling the reports API with oAuth token
|
@@ -101,7 +105,7 @@ Example Usage for calling the reports API with oAuth token
|
|
101
105
|
Example Usage for oAuth -
|
102
106
|
```ruby
|
103
107
|
# To get the redirect URL :
|
104
|
-
2.5.5 :002 > options = {
|
108
|
+
2.5.5 :002 > options = {mode: 'test'}
|
105
109
|
2.5.5 :003 > require 'smartcar'
|
106
110
|
2.5.5 :004 > client = Smartcar::AuthClient.new(options)
|
107
111
|
2.5.5 :005 > url = client.get_auth_url(["read_battery","read_charge","read_fuel","read_location","control_security","read_odometer","read_tires","read_vin","read_vehicle_info"], {flags: ["country:DE"]})
|
data/lib/smartcar/auth_client.rb
CHANGED
@@ -6,7 +6,7 @@ module Smartcar
|
|
6
6
|
class AuthClient
|
7
7
|
include Smartcar::Utils
|
8
8
|
|
9
|
-
attr_reader :redirect_uri, :client_id, :client_secret, :scope, :mode, :flags, :
|
9
|
+
attr_reader :redirect_uri, :client_id, :client_secret, :scope, :mode, :flags, :auth_origin, :connect_origin
|
10
10
|
|
11
11
|
# Constructor for a client object
|
12
12
|
#
|
@@ -14,15 +14,18 @@ module Smartcar
|
|
14
14
|
# @option options[:client_id] [String] - Client ID, if not passed fallsback to ENV['SMARTCAR_CLIENT_ID']
|
15
15
|
# @option options[:client_secret] [String] - Client Secret, if not passed fallsback to ENV['SMARTCAR_CLIENT_SECRET']
|
16
16
|
# @option options[:redirect_uri] [String] - Redirect URI, if not passed fallsback to ENV['SMARTCAR_REDIRECT_URI']
|
17
|
-
# @option options[:test_mode] [Boolean] -
|
18
|
-
#
|
17
|
+
# @option options[:test_mode] [Boolean] - [DEPRECATED], please use `mode` instead.
|
18
|
+
# Launch Smartcar Connect in [test mode](https://smartcar.com/docs/guides/testing/).
|
19
|
+
# @option options[:mode] [String] - Determine what mode Smartcar Connect should be launched in.
|
20
|
+
# Should be one of test, live or simulated.
|
19
21
|
# @return [Smartcar::AuthClient] Returns a Smartcar::AuthClient Object that has other methods
|
20
22
|
def initialize(options)
|
21
23
|
options[:redirect_uri] ||= get_config('SMARTCAR_REDIRECT_URI')
|
22
24
|
options[:client_id] ||= get_config('SMARTCAR_CLIENT_ID')
|
23
25
|
options[:client_secret] ||= get_config('SMARTCAR_CLIENT_SECRET')
|
24
|
-
options[:
|
25
|
-
options[:
|
26
|
+
options[:auth_origin] = ENV['SMARTCAR_AUTH_ORIGIN'] || AUTH_ORIGIN
|
27
|
+
options[:connect_origin] = ENV['SMARTCAR_CONNECT_ORIGIN'] || CONNECT_ORIGIN
|
28
|
+
options[:mode] = determine_mode(options[:test_mode], options[:mode]) || 'live'
|
26
29
|
super
|
27
30
|
end
|
28
31
|
|
@@ -55,7 +58,7 @@ module Smartcar
|
|
55
58
|
def get_auth_url(scope, options = {})
|
56
59
|
initialize_auth_parameters(scope, options)
|
57
60
|
add_single_select_options(options[:single_select])
|
58
|
-
|
61
|
+
connect_client.auth_code.authorize_url(@auth_parameters)
|
59
62
|
end
|
60
63
|
|
61
64
|
# Generates the tokens hash using the code returned in oauth process.
|
@@ -68,9 +71,9 @@ module Smartcar
|
|
68
71
|
def exchange_code(code, options = {})
|
69
72
|
set_token_url(options[:flags])
|
70
73
|
|
71
|
-
token_hash =
|
72
|
-
|
73
|
-
|
74
|
+
token_hash = auth_client.auth_code
|
75
|
+
.get_token(code, redirect_uri: redirect_uri)
|
76
|
+
.to_hash
|
74
77
|
|
75
78
|
json_to_ostruct(token_hash)
|
76
79
|
rescue OAuth2::Error => e
|
@@ -86,7 +89,7 @@ module Smartcar
|
|
86
89
|
def exchange_refresh_token(token, options = {})
|
87
90
|
set_token_url(options[:flags])
|
88
91
|
|
89
|
-
token_object = OAuth2::AccessToken.from_hash(
|
92
|
+
token_object = OAuth2::AccessToken.from_hash(auth_client, { refresh_token: token })
|
90
93
|
token_object = token_object.refresh!
|
91
94
|
|
92
95
|
json_to_ostruct(token_object.to_hash)
|
@@ -99,7 +102,7 @@ module Smartcar
|
|
99
102
|
#
|
100
103
|
# @return [Boolean]
|
101
104
|
def expired?(expires_at)
|
102
|
-
OAuth2::AccessToken.from_hash(
|
105
|
+
OAuth2::AccessToken.from_hash(auth_client, { expires_at: expires_at }).expired?
|
103
106
|
end
|
104
107
|
|
105
108
|
private
|
@@ -115,7 +118,7 @@ module Smartcar
|
|
115
118
|
params[:flags] = build_flags(flags) if flags
|
116
119
|
# Note - The inbuild interface to get the token does not allow any way to pass additional
|
117
120
|
# URL params. Hence building the token URL with the flags and setting it in client.
|
118
|
-
|
121
|
+
auth_client.options[:token_url] = auth_client.connection.build_url('/oauth/token', params).request_uri
|
119
122
|
end
|
120
123
|
|
121
124
|
def initialize_auth_parameters(scope, options)
|
@@ -142,13 +145,22 @@ module Smartcar
|
|
142
145
|
end
|
143
146
|
end
|
144
147
|
|
145
|
-
# gets the Oauth Client object
|
148
|
+
# gets the Oauth Client object configured with auth.connect.smartcar.com
|
149
|
+
#
|
150
|
+
# @return [OAuth2::Client] A Oauth Client object.
|
151
|
+
def auth_client
|
152
|
+
@auth_client ||= OAuth2::Client.new(client_id,
|
153
|
+
client_secret,
|
154
|
+
site: auth_origin)
|
155
|
+
end
|
156
|
+
|
157
|
+
# gets the Oauth Client object configured with connect.smartcar.com
|
146
158
|
#
|
147
159
|
# @return [OAuth2::Client] A Oauth Client object.
|
148
|
-
def
|
149
|
-
@
|
150
|
-
|
151
|
-
|
160
|
+
def connect_client
|
161
|
+
@connect_client ||= OAuth2::Client.new(client_id,
|
162
|
+
client_secret,
|
163
|
+
site: connect_origin)
|
152
164
|
end
|
153
165
|
end
|
154
166
|
end
|
data/lib/smartcar/base.rb
CHANGED
@@ -22,7 +22,7 @@ module Smartcar
|
|
22
22
|
# @param data [Hash] request body if needed.
|
23
23
|
#
|
24
24
|
# @return [Hash] The response Json parsed as a hash.
|
25
|
-
define_method verb do |path, data = nil, headers = {}|
|
25
|
+
define_method verb do |path, query_params = {}, data = nil, headers = {}|
|
26
26
|
response = service.send(verb) do |request|
|
27
27
|
request_headers = {}
|
28
28
|
request_headers['Authorization'] = auth_type == BASIC ? "Basic #{token}" : "Bearer #{token}"
|
@@ -32,6 +32,7 @@ module Smartcar
|
|
32
32
|
"Smartcar/#{VERSION} (#{RbConfig::CONFIG['host_os']}; #{RbConfig::CONFIG['arch']}) Ruby v#{RUBY_VERSION}"
|
33
33
|
request.headers = request_headers.merge(headers)
|
34
34
|
complete_path = "/v#{version}#{path}"
|
35
|
+
complete_path += "?#{URI.encode_www_form(query_params.compact)}" unless query_params.empty?
|
35
36
|
if verb == :get
|
36
37
|
request.url complete_path, data
|
37
38
|
else
|
@@ -46,17 +47,6 @@ module Smartcar
|
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
49
|
-
# This requires a proc 'PATH' to be defined in the class
|
50
|
-
# @param path [String] resource path
|
51
|
-
# @param query_params [Hash] query params
|
52
|
-
# @param auth [String] type of auth
|
53
|
-
#
|
54
|
-
# @return [Object]
|
55
|
-
def fetch(path:, query_params: {})
|
56
|
-
path += "?#{URI.encode_www_form(query_params)}" unless query_params.empty?
|
57
|
-
get(path)
|
58
|
-
end
|
59
|
-
|
60
50
|
private
|
61
51
|
|
62
52
|
# gets a smartcar API service/client
|
data/lib/smartcar/utils.rb
CHANGED
@@ -127,5 +127,25 @@ module Smartcar
|
|
127
127
|
|
128
128
|
path.split('/').reject(&:empty?).join('_').to_sym
|
129
129
|
end
|
130
|
+
|
131
|
+
# takes query parameters and returns them as a string
|
132
|
+
# EX - {'country': 'DE', 'flags': true} -> "county:DE flags:true"
|
133
|
+
def stringify_params(query_params)
|
134
|
+
query_params&.map { |key, value| "#{key}:#{value}" }&.join(' ')
|
135
|
+
end
|
136
|
+
|
137
|
+
def determine_mode(test_mode, mode)
|
138
|
+
unless mode.nil?
|
139
|
+
unless %w[test live simulated].include? mode
|
140
|
+
raise 'The "mode" parameter MUST be one of the following: \'test\', \'live\', \'simulated\''
|
141
|
+
end
|
142
|
+
|
143
|
+
return mode
|
144
|
+
end
|
145
|
+
return if test_mode.nil?
|
146
|
+
|
147
|
+
warn '[DEPRECATION] The "test_mode" parameter is deprecated, please use the "mode" parameter instead.'
|
148
|
+
test_mode.is_a?(TrueClass) ? 'test' : 'live'
|
149
|
+
end
|
130
150
|
end
|
131
151
|
end
|
data/lib/smartcar/vehicle.rb
CHANGED
@@ -11,6 +11,7 @@ module Smartcar
|
|
11
11
|
# @attr [Hash] options
|
12
12
|
# @attr unit_system [String] Unit system to represent the data in, defaults to Imperial
|
13
13
|
# @attr version [String] API version to be used.
|
14
|
+
# @attr flags [Hash] Object of flags where key is the name of the flag and value is string or boolean value.
|
14
15
|
# @attr service [Faraday::Connection] An optional connection object to be used for requests.
|
15
16
|
class Vehicle < Base
|
16
17
|
attr_reader :id
|
@@ -77,6 +78,7 @@ module Smartcar
|
|
77
78
|
@unit_system = options[:unit_system] || METRIC
|
78
79
|
@version = options[:version] || Smartcar.get_api_version
|
79
80
|
@service = options[:service]
|
81
|
+
@query_params = { flags: stringify_params(options[:flags]) }
|
80
82
|
|
81
83
|
raise InvalidParameterValue.new, "Invalid Units provided : #{@unit_system}" unless UNITS.include?(@unit_system)
|
82
84
|
raise InvalidParameterValue.new, 'Vehicle ID (id) is a required field' if id.nil?
|
@@ -177,11 +179,11 @@ module Smartcar
|
|
177
179
|
define_method method do
|
178
180
|
body, headers = case item[:type]
|
179
181
|
when :post
|
180
|
-
post(item[:path].call(id), item[:body])
|
182
|
+
post(item[:path].call(id), @query_params, item[:body])
|
181
183
|
when :delete
|
182
|
-
delete(item[:path].call(id))
|
184
|
+
delete(item[:path].call(id), @query_params)
|
183
185
|
else
|
184
|
-
|
186
|
+
get(item[:path].call(id), @query_params)
|
185
187
|
end
|
186
188
|
build_aliases(build_response(body, headers), item[:aliases])
|
187
189
|
end
|
@@ -195,7 +197,7 @@ module Smartcar
|
|
195
197
|
# @return [OpenStruct] And object representing the JSON response mentioned in https://smartcar.com/docs/api#get-application-permissions
|
196
198
|
# and a meta attribute with the relevant items from response headers.
|
197
199
|
def permissions(paging = {})
|
198
|
-
response, headers =
|
200
|
+
response, headers = get(METHODS.dig(:permissions, :path).call(id), @query_params.merge(paging))
|
199
201
|
build_response(response, headers)
|
200
202
|
end
|
201
203
|
|
@@ -206,7 +208,7 @@ module Smartcar
|
|
206
208
|
# @return [OpenStruct] An object representing the JSON response and a meta attribute
|
207
209
|
# with the relevant items from response headers.
|
208
210
|
def subscribe!(webhook_id)
|
209
|
-
response, headers = post(METHODS.dig(:subscribe!, :path).call(id, webhook_id),
|
211
|
+
response, headers = post(METHODS.dig(:subscribe!, :path).call(id, webhook_id), @query_params)
|
210
212
|
build_aliases(build_response(response, headers), METHODS.dig(:subscribe!, :aliases))
|
211
213
|
end
|
212
214
|
|
@@ -220,7 +222,8 @@ module Smartcar
|
|
220
222
|
# swapping off the token with amt for unsubscribe.
|
221
223
|
access_token = token
|
222
224
|
self.token = amt
|
223
|
-
response, headers = delete(METHODS.dig(:unsubscribe!, :path).call(id, webhook_id)
|
225
|
+
response, headers = delete(METHODS.dig(:unsubscribe!, :path).call(id, webhook_id),
|
226
|
+
@query_params)
|
224
227
|
self.token = access_token
|
225
228
|
build_response(response, headers)
|
226
229
|
end
|
@@ -233,7 +236,7 @@ module Smartcar
|
|
233
236
|
# an OpenStruct object of the requested attribute or taises if it is an error.
|
234
237
|
def batch(paths)
|
235
238
|
request_body = { requests: paths.map { |path| { path: path } } }
|
236
|
-
response, headers = post("/vehicles/#{id}/batch", request_body)
|
239
|
+
response, headers = post("/vehicles/#{id}/batch", @query_params, request_body)
|
237
240
|
process_batch_response(response, headers)
|
238
241
|
end
|
239
242
|
|
@@ -249,7 +252,7 @@ module Smartcar
|
|
249
252
|
# response body and a "meta" attribute with the relevant items from response headers.
|
250
253
|
def request(method, path, body = {}, headers = {})
|
251
254
|
path = "/vehicles/#{id}/#{path}"
|
252
|
-
raw_response, headers = send(method.downcase, path, body, headers)
|
255
|
+
raw_response, headers = send(method.downcase, path, @query_params, body, headers)
|
253
256
|
meta = build_meta(headers)
|
254
257
|
json_to_ostruct({ body: raw_response, meta: meta })
|
255
258
|
end
|
data/lib/smartcar/version.rb
CHANGED
data/lib/smartcar.rb
CHANGED
@@ -22,7 +22,8 @@ module Smartcar
|
|
22
22
|
}.freeze
|
23
23
|
|
24
24
|
# Path for smartcar oauth
|
25
|
-
|
25
|
+
CONNECT_ORIGIN = 'https://connect.smartcar.com'
|
26
|
+
AUTH_ORIGIN = 'https://auth.smartcar.com'
|
26
27
|
%w[success code test live force auto metric imperial].each do |constant|
|
27
28
|
# Constant to represent the value
|
28
29
|
const_set(constant.upcase, constant.freeze)
|
@@ -38,6 +39,7 @@ module Smartcar
|
|
38
39
|
@api_version = '2.0'
|
39
40
|
|
40
41
|
class << self
|
42
|
+
include Smartcar::Utils
|
41
43
|
# Module method Used to set api version to be used.
|
42
44
|
# This method can be used at the top to set the version and any
|
43
45
|
# following request will use the version set here unless overridden
|
@@ -67,7 +69,10 @@ module Smartcar
|
|
67
69
|
# @option options [String] :client_secret Client Secret that overrides ENV
|
68
70
|
# @option options [String] :version API version to use, defaults to what is globally set
|
69
71
|
# @option options [Hash] :flags A hash of flag name string as key and a string or boolean value.
|
70
|
-
# @option options
|
72
|
+
# @option options[Boolean] :test_mode [DEPRECATED], please use `mode` instead.
|
73
|
+
# Launch Smartcar Connect in test mode(https://smartcar.com/docs/guides/testing/).
|
74
|
+
# @option options [String] :mode Determine what mode Smartcar Connect should be launched in.
|
75
|
+
# Should be one of test, live or simulated.
|
71
76
|
# @option options [String] :test_mode_compatibility_level this is required argument while using
|
72
77
|
# test mode with a real vin. For more information refer to docs.
|
73
78
|
# @option options [Faraday::Connection] :service Optional connection object to be used for requests
|
@@ -88,9 +93,9 @@ module Smartcar
|
|
88
93
|
|
89
94
|
base_object.token = generate_basic_auth(options, base_object)
|
90
95
|
|
91
|
-
base_object.build_response(*base_object.
|
92
|
-
|
93
|
-
|
96
|
+
base_object.build_response(*base_object.get(
|
97
|
+
PATHS[:compatibility],
|
98
|
+
build_compatibility_params(vin, scope, country, options)
|
94
99
|
))
|
95
100
|
end
|
96
101
|
|
@@ -112,7 +117,7 @@ module Smartcar
|
|
112
117
|
service: options[:service]
|
113
118
|
}
|
114
119
|
)
|
115
|
-
base_object.build_response(*base_object.
|
120
|
+
base_object.build_response(*base_object.get(PATHS[:user]))
|
116
121
|
end
|
117
122
|
|
118
123
|
# Module method Returns a paged list of all vehicles connected to the application for the current authorized user.
|
@@ -134,9 +139,9 @@ module Smartcar
|
|
134
139
|
service: options[:service]
|
135
140
|
}
|
136
141
|
)
|
137
|
-
base_object.build_response(*base_object.
|
138
|
-
|
139
|
-
|
142
|
+
base_object.build_response(*base_object.get(
|
143
|
+
PATHS[:vehicles],
|
144
|
+
paging
|
140
145
|
))
|
141
146
|
end
|
142
147
|
|
@@ -169,15 +174,15 @@ module Smartcar
|
|
169
174
|
scope: scope.join(' '),
|
170
175
|
country: country
|
171
176
|
}
|
172
|
-
query_params[:flags] = options[:flags]
|
173
|
-
query_params[:mode] = options[:test_mode].is_a?(TrueClass) ? 'test' : 'live' unless options[:test_mode].nil?
|
177
|
+
query_params[:flags] = stringify_params(options[:flags])
|
174
178
|
|
175
|
-
|
176
|
-
query_params[:test_mode_compatibility_level] =
|
177
|
-
options[:test_mode_compatibility_level]
|
178
|
-
query_params[:mode] = 'test'
|
179
|
-
end
|
179
|
+
mode = determine_mode(options[:test_mode], options[:mode])
|
180
180
|
|
181
|
+
unless options[:test_mode_compatibility_level].nil?
|
182
|
+
query_params[:test_mode_compatibility_level] = options[:test_mode_compatibility_level]
|
183
|
+
mode = 'test'
|
184
|
+
end
|
185
|
+
query_params[:mode] = mode unless mode.nil?
|
181
186
|
query_params
|
182
187
|
end
|
183
188
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smartcar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ashwin Subramanian
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -235,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
235
235
|
- !ruby/object:Gem::Version
|
236
236
|
version: '0'
|
237
237
|
requirements: []
|
238
|
-
rubygems_version: 3.
|
238
|
+
rubygems_version: 3.1.6
|
239
239
|
signing_key:
|
240
240
|
specification_version: 4
|
241
241
|
summary: Ruby Gem to access smartcar APIs (https://smartcar.com/docs/)
|