smartcar 2.4.0 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Smartcar
2
4
  # Gem current version number
3
- VERSION = "2.4.0"
5
+ VERSION = '3.0.2'
4
6
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Custom SmartcarError class to represent errors from Smartcar APIs.
4
+ class SmartcarError < StandardError
5
+ attr_reader :code, :status_code, :request_id, :type, :description, :doc_url, :resolution, :detail
6
+
7
+ def initialize(status, body, headers)
8
+ @status_code = status
9
+ if body.is_a?(String)
10
+ super(body)
11
+ @request_id = headers['sc-request-id']
12
+ return
13
+ end
14
+ body = coerce_attributes(body)
15
+
16
+ super("#{body[:type]}:#{body[:code]} - #{body[:description]}")
17
+ @request_id = body[:requestId] || headers['sc-request-id']
18
+ set_attributes(body)
19
+ end
20
+
21
+ private
22
+
23
+ def coerce_attributes(body)
24
+ body[:type] = body.delete(:error) if body[:error]
25
+ unless body[:description]
26
+ body[:description] = if body[:error_description]
27
+ body.delete(:error_description)
28
+ elsif body[:message]
29
+ body.delete(:message)
30
+ else
31
+ 'Unknown error'
32
+ end
33
+ end
34
+
35
+ body
36
+ end
37
+
38
+ def set_attributes(body)
39
+ body.each do |attribute, value|
40
+ instance_variable_set("@#{attribute}", value)
41
+ end
42
+ @doc_url = body[:docURL]
43
+ @type = @error if @error
44
+
45
+ return unless @resolution
46
+
47
+ @resolution = @resolution.is_a?(String) ? OpenStruct.new({ type: @resolution }) : OpenStruct.new(@resolution)
48
+ end
49
+ end
data/ruby-sdk.gemspec CHANGED
@@ -1,33 +1,40 @@
1
- lib = File.expand_path("lib", __dir__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require "smartcar/version"
5
+ require 'smartcar/version'
4
6
 
5
7
  Gem::Specification.new do |spec|
6
- spec.name = "smartcar"
8
+ spec.name = 'smartcar'
7
9
  spec.version = Smartcar::VERSION
8
- spec.required_ruby_version = ">= 2.5.0"
9
- spec.authors = ["Ashwin Subramanian"]
10
- spec.email = ["ashwin.subramanian@smartcar.com"]
10
+ spec.required_ruby_version = '>= 2.5.0'
11
+ spec.authors = ['Ashwin Subramanian']
12
+ spec.email = ['ashwin.subramanian@smartcar.com']
11
13
  spec.homepage = 'https://rubygems.org/gems/smartcar'
12
- spec.summary = %q{Ruby Gem to access smartcar APIs (https://smartcar.com/docs/)}
13
- spec.description = %q{This is a ruby gem to access the smartcar APIs. It includes the API classes and the OAuth system.}
14
- spec.license = "MIT"
15
- spec.metadata = {
16
- "source_code_uri" => "https://github.com/smartcar/ruby-sdk",
17
- "documentation_uri" => "https://www.rubydoc.info/gems/smartcar",
14
+ spec.summary = 'Ruby Gem to access smartcar APIs (https://smartcar.com/docs/)'
15
+ spec.description = 'This is a ruby gem to access the smartcar APIs. It includes the API classes and the OAuth system.'
16
+ spec.license = 'MIT'
17
+ spec.metadata = {
18
+ 'source_code_uri' => 'https://github.com/smartcar/ruby-sdk',
19
+ 'documentation_uri' => 'https://www.rubydoc.info/gems/smartcar'
18
20
  }
19
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
21
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
20
22
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
23
  end
22
- spec.bindir = "exe"
24
+ spec.bindir = 'exe'
23
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
- spec.require_paths = ["lib"]
26
+ spec.require_paths = ['lib']
25
27
 
26
- spec.add_development_dependency "bundler", "~> 2.0"
28
+ spec.add_development_dependency 'bundler', '~> 2.0'
29
+ spec.add_development_dependency 'byebug', '~> 11.0'
30
+ spec.add_development_dependency 'codecov', '~> 0.5.2'
27
31
  spec.add_development_dependency 'rake', '~> 12.3', '>= 12.3.3'
28
- spec.add_development_dependency "rspec", "~> 3.0"
29
- spec.add_development_dependency "byebug", "~> 11.0"
30
- spec.add_development_dependency "redcarpet", "~> 3.5.0"
31
- spec.add_development_dependency "selenium-webdriver", "~> 3.142"
32
- spec.add_dependency "oauth2", "~> 1.4"
32
+ spec.add_development_dependency 'readapt', '~> 1.3'
33
+ spec.add_development_dependency 'redcarpet', '~> 3.5.0'
34
+ spec.add_development_dependency 'rspec', '~> 3.0'
35
+ spec.add_development_dependency 'rubocop', '~> 1.12'
36
+ spec.add_development_dependency 'selenium-webdriver', '~> 3.142'
37
+ spec.add_development_dependency 'webmock', '~> 3.13'
38
+ spec.add_dependency 'oauth2', '~> 1.4'
39
+ spec.add_dependency 'recursive-open-struct', '~> 1.1.3'
33
40
  end
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: 2.4.0
4
+ version: 3.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ashwin Subramanian
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-05-13 00:00:00.000000000 Z
11
+ date: 2021-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '11.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '11.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: codecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.5.2
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.5.2
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: rake
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -45,47 +73,61 @@ dependencies:
45
73
  - !ruby/object:Gem::Version
46
74
  version: 12.3.3
47
75
  - !ruby/object:Gem::Dependency
48
- name: rspec
76
+ name: readapt
49
77
  requirement: !ruby/object:Gem::Requirement
50
78
  requirements:
51
79
  - - "~>"
52
80
  - !ruby/object:Gem::Version
53
- version: '3.0'
81
+ version: '1.3'
54
82
  type: :development
55
83
  prerelease: false
56
84
  version_requirements: !ruby/object:Gem::Requirement
57
85
  requirements:
58
86
  - - "~>"
59
87
  - !ruby/object:Gem::Version
60
- version: '3.0'
88
+ version: '1.3'
61
89
  - !ruby/object:Gem::Dependency
62
- name: byebug
90
+ name: redcarpet
63
91
  requirement: !ruby/object:Gem::Requirement
64
92
  requirements:
65
93
  - - "~>"
66
94
  - !ruby/object:Gem::Version
67
- version: '11.0'
95
+ version: 3.5.0
68
96
  type: :development
69
97
  prerelease: false
70
98
  version_requirements: !ruby/object:Gem::Requirement
71
99
  requirements:
72
100
  - - "~>"
73
101
  - !ruby/object:Gem::Version
74
- version: '11.0'
102
+ version: 3.5.0
75
103
  - !ruby/object:Gem::Dependency
76
- name: redcarpet
104
+ name: rspec
77
105
  requirement: !ruby/object:Gem::Requirement
78
106
  requirements:
79
107
  - - "~>"
80
108
  - !ruby/object:Gem::Version
81
- version: 3.5.0
109
+ version: '3.0'
82
110
  type: :development
83
111
  prerelease: false
84
112
  version_requirements: !ruby/object:Gem::Requirement
85
113
  requirements:
86
114
  - - "~>"
87
115
  - !ruby/object:Gem::Version
88
- version: 3.5.0
116
+ version: '3.0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rubocop
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '1.12'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '1.12'
89
131
  - !ruby/object:Gem::Dependency
90
132
  name: selenium-webdriver
91
133
  requirement: !ruby/object:Gem::Requirement
@@ -100,6 +142,20 @@ dependencies:
100
142
  - - "~>"
101
143
  - !ruby/object:Gem::Version
102
144
  version: '3.142'
145
+ - !ruby/object:Gem::Dependency
146
+ name: webmock
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '3.13'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '3.13'
103
159
  - !ruby/object:Gem::Dependency
104
160
  name: oauth2
105
161
  requirement: !ruby/object:Gem::Requirement
@@ -114,6 +170,20 @@ dependencies:
114
170
  - - "~>"
115
171
  - !ruby/object:Gem::Version
116
172
  version: '1.4'
173
+ - !ruby/object:Gem::Dependency
174
+ name: recursive-open-struct
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: 1.1.3
180
+ type: :runtime
181
+ prerelease: false
182
+ version_requirements: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - "~>"
185
+ - !ruby/object:Gem::Version
186
+ version: 1.1.3
117
187
  description: This is a ruby gem to access the smartcar APIs. It includes the API classes
118
188
  and the OAuth system.
119
189
  email:
@@ -124,6 +194,7 @@ extra_rdoc_files: []
124
194
  files:
125
195
  - ".gitignore"
126
196
  - ".rspec"
197
+ - ".rubocop.yml"
127
198
  - ".travis.yml"
128
199
  - ".yardopts"
129
200
  - CODE_OF_CONDUCT.md
@@ -135,23 +206,12 @@ files:
135
206
  - bin/console
136
207
  - bin/setup
137
208
  - lib/smartcar.rb
209
+ - lib/smartcar/auth_client.rb
138
210
  - lib/smartcar/base.rb
139
- - lib/smartcar/battery.rb
140
- - lib/smartcar/battery_capacity.rb
141
- - lib/smartcar/charge.rb
142
- - lib/smartcar/engine_oil.rb
143
- - lib/smartcar/fuel.rb
144
- - lib/smartcar/location.rb
145
- - lib/smartcar/oauth.rb
146
- - lib/smartcar/odometer.rb
147
- - lib/smartcar/permissions.rb
148
- - lib/smartcar/tire_pressure.rb
149
- - lib/smartcar/user.rb
150
211
  - lib/smartcar/utils.rb
151
212
  - lib/smartcar/vehicle.rb
152
- - lib/smartcar/vehicle_attributes.rb
153
213
  - lib/smartcar/version.rb
154
- - lib/smartcar/vin.rb
214
+ - lib/smartcar_error.rb
155
215
  - ruby-sdk.gemspec
156
216
  homepage: https://rubygems.org/gems/smartcar
157
217
  licenses:
@@ -1,13 +0,0 @@
1
- module Smartcar
2
- # class to represent Battery info
3
- #@attr [Number] percentRemaining Decimal value representing the remaining charge percent.
4
- #@attr [Number] range Remaining range of the vehicle.
5
- class Battery < Base
6
- # Path Proc for hitting battery end point
7
- PATH = Proc.new{|id| "/vehicles/#{id}/battery"}
8
- attr_reader :percentRemaining, :range
9
-
10
- # just to have Ruby-esque method names
11
- alias_method :percentage_remaining, :percentRemaining
12
- end
13
- end
@@ -1,9 +0,0 @@
1
- module Smartcar
2
- # class to represent Battery Capacity info
3
- #@attr [Number] capacity Decimal value representing the battery's total capacity in kWh.
4
- class BatteryCapacity < Base
5
- # Path Proc for hitting battery capacity end point
6
- PATH = Proc.new{|id| "/vehicles/#{id}/battery/capacity"}
7
- attr_reader :capacity
8
- end
9
- end
@@ -1,13 +0,0 @@
1
- module Smartcar
2
- # class to represent Charge info
3
- #@attr [Boolean] isPluggedIn Specifies if the vehicle is plugged in.
4
- #@attr [String] state Charging state of the vehicle.
5
- class Charge < Base
6
- # Path Proc for hitting charge end point
7
- PATH = Proc.new{|id| "/vehicles/#{id}/charge"}
8
- attr_reader :isPluggedIn, :state
9
-
10
- # just to have Ruby-esque method names
11
- alias_method :is_plugged_in?, :isPluggedIn
12
- end
13
- end
@@ -1,12 +0,0 @@
1
- module Smartcar
2
- # class to represent Engine oil info
3
- #@attr [Number] lifeRemaining Remaining life of the engine oil
4
- class EngineOil < Base
5
- # Path Proc for hitting engine oil end point
6
- PATH = Proc.new{|id| "/vehicles/#{id}/engine/oil"}
7
- attr_reader :lifeRemaining
8
-
9
- # just to have Ruby-esque method names
10
- alias_method :life_remaining, :lifeRemaining
11
- end
12
- end
data/lib/smartcar/fuel.rb DELETED
@@ -1,15 +0,0 @@
1
- module Smartcar
2
- # class to represent Fuel info
3
- #@attr [Number] amountRemaining Amount of fuel remaining.
4
- #@attr [Number] percentageRemaining Decimal value representing the remaining fuel percent.
5
- #@attr [Number] range Remaining range of the vehicle.
6
- class Fuel < Base
7
- # Path Proc for hitting fuel end point
8
- PATH = Proc.new{|id| "/vehicles/#{id}/fuel"}
9
- attr_reader :amountRemaining, :percentRemaining, :range
10
-
11
- # just to have Ruby-esque method names
12
- alias_method :amount_remaining, :amountRemaining
13
- alias_method :percent_remaining, :percentRemaining
14
- end
15
- end
@@ -1,10 +0,0 @@
1
- module Smartcar
2
- # class to represent Location info
3
- #@attr [Number] latitude Latitude of last recorded location.
4
- #@attr [Number] longitude Longitude of last recorded location.
5
- class Location < Base
6
- # Path Proc for hitting location end point
7
- PATH = Proc.new{|id| "/vehicles/#{id}/location"}
8
- attr_reader :latitude, :longitude
9
- end
10
- end
@@ -1,119 +0,0 @@
1
- module Smartcar
2
- # Oauth class to take care of the Oauth 2.0 with Smartcar APIs
3
- #
4
- class Oauth < Base
5
- extend Smartcar::Utils
6
- # By default users are not shown the permission dialog if they have already
7
- # approved the set of scopes for this application. The application can elect
8
- # to always display the permissions dialog to the user by setting
9
- # approval_prompt to `force`.
10
- #
11
- # @param options [Hash]
12
- # @option options[:client_id] [String] - Client ID, if not passed fallsback to ENV['CLIENT_ID']
13
- # @option options[:client_secret] [String] - Client Secret, if not passed fallsback to ENV['CLIENT_SECRET']
14
- # @option options[:redirect_uri] [String] - Redirect URI, if not passed fallsback to ENV['REDIRECT_URI']
15
- # @option options[:scope] [Array of Strings] - array of scopes that specify what the user can access
16
- # EXAMPLE : ['read_odometer', 'read_vehicle_info', 'required:read_location']
17
- # For further details refer to https://smartcar.com/docs/guides/scope/
18
- # @option options[:test_mode] [Boolean] - Setting this to 'true' runs it in test mode.
19
- #
20
- # @return [Smartcar::Oauth] Returns a Smartcar::Oauth Object that has other methods
21
- def initialize(options)
22
- @redirect_uri = options[:redirect_uri] || get_config('REDIRECT_URI')
23
- @client_id = options[:client_id] || get_config('CLIENT_ID')
24
- @client_secret = options[:client_secret] || get_config('CLIENT_SECRET')
25
- @scope = options[:scope]
26
- @test_mode = !!options[:test_mode]
27
- end
28
-
29
- # Generate the OAuth authorization URL.
30
- # @param options [Hash]
31
- # @option options[:state] [String] - OAuth state parameter passed to the
32
- # redirect uri. This parameter may be used for identifying the user who
33
- # initiated the request.
34
- # @option options[:force_prompt] [Boolean] - Setting `force_prompt` to
35
- # `true` will show the permissions approval screen on every authentication
36
- # attempt, even if the user has previously consented to the exact scope of
37
- # permissions.
38
- # @option options[:make] [String] - `make' is an optional parameter that allows
39
- # users to bypass the car brand selection screen.
40
- # For a complete list of supported makes, please see our
41
- # [API Reference](https://smartcar.com/docs/api#authorization) documentation.
42
- # @option options[:single_select] [Boolean, Hash] - An optional value that sets the
43
- # behavior of the grant dialog displayed to the user. If set to `true`,
44
- # `single_select` limits the user to selecting only one vehicle. If `single_select`
45
- # is an hash with the property `vin`, Smartcar will only authorize the vehicle
46
- # with the specified VIN. See the
47
- # [Single Select guide](https://smartcar.com/docs/guides/single-select/)
48
- # for more information.
49
- # @option options[:flags] [Array of Strings] - an optional array of early access features to enable.
50
- #
51
- # @return [String] Authorization URL string
52
- def authorization_url(options = {})
53
- options[:scope] = @scope
54
- auth_parameters = {
55
- redirect_uri: @redirect_uri,
56
- approval_prompt: options[:force_prompt] ? FORCE : AUTO,
57
- mode: @test_mode ? TEST : LIVE,
58
- response_type: CODE,
59
- }
60
-
61
- auth_parameters[:flags] = options[:flags].join(' ') unless options[:flags].nil?
62
- auth_parameters[:scope] = @scope.join(' ') unless @scope.nil?
63
-
64
- %I(state make).each do |parameter|
65
- auth_parameters[parameter] = options[parameter] unless options[parameter].nil?
66
- end
67
-
68
- if(options[:single_select].is_a?(Hash))
69
- auth_parameters[:single_select_vin] = options[:single_select][:vin]
70
- auth_parameters[:single_select] = true
71
- else
72
- auth_parameters[:single_select] = !!options[:single_select]
73
- end
74
- client.auth_code.authorize_url(auth_parameters)
75
- end
76
-
77
- # Generates the tokens hash using the code returned in oauth process.
78
- # @param auth_code [String] This is the code that is returned after user
79
- # visits and authorizes on the authorization URL.
80
- #
81
- # @return [Hash] Hash of token, refresh token, expiry info and token type
82
- def get_token(auth_code)
83
- client.auth_code
84
- .get_token(
85
- auth_code,
86
- redirect_uri: @redirect_uri
87
- ).to_hash
88
- end
89
-
90
- # Refreshing the access token
91
- # @param refresh_token [String] refresh_token received during token exchange
92
- #
93
- # @return [Hash] Hash of token, refresh token, expiry info and token type
94
- def exchange_refresh_token(refresh_token)
95
- token_object = OAuth2::AccessToken.from_hash(client, {refresh_token: refresh_token})
96
- token_object = token_object.refresh!
97
- token_object.to_hash
98
- end
99
-
100
- # Checks if token is expired using Oauth2 classes
101
- # @param expires_at [Number] expires_at as time since epoch
102
- #
103
- # @return [Boolean]
104
- def expired?(expires_at)
105
- OAuth2::AccessToken.from_hash(client, {expires_at: expires_at}).expired?
106
- end
107
-
108
- private
109
- # gets the Oauth Client object
110
- #
111
- # @return [OAuth2::Client] A Oauth Client object.
112
- def client
113
- @client ||= OAuth2::Client.new( @client_id,
114
- @client_secret,
115
- :site => OAUTH_PATH
116
- )
117
- end
118
- end
119
- end