spark_api 1.1.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +14 -0
- data/README.md +42 -233
- data/VERSION +1 -1
- data/lib/spark_api.rb +1 -0
- data/lib/spark_api/authentication/oauth2.rb +39 -9
- data/lib/spark_api/authentication/oauth2_impl/cli_provider.rb +96 -0
- data/lib/spark_api/authentication/oauth2_impl/faraday_middleware.rb +28 -0
- data/lib/spark_api/authentication/oauth2_impl/grant_type_base.rb +7 -2
- data/lib/spark_api/authentication/oauth2_impl/single_session_provider.rb +27 -0
- data/lib/spark_api/cli.rb +29 -10
- data/lib/spark_api/cli/api_auth.rb +1 -0
- data/lib/spark_api/cli/oauth2.rb +23 -8
- data/lib/spark_api/cli/setup.rb +31 -0
- data/lib/spark_api/configuration.rb +10 -2
- data/lib/spark_api/configuration/yaml.rb +6 -1
- data/lib/spark_api/connection.rb +1 -1
- data/lib/spark_api/errors.rb +48 -0
- data/lib/spark_api/models.rb +3 -0
- data/lib/spark_api/models/account.rb +9 -1
- data/lib/spark_api/models/base.rb +24 -19
- data/lib/spark_api/models/concerns.rb +7 -0
- data/lib/spark_api/models/concerns/destroyable.rb +32 -0
- data/lib/spark_api/models/concerns/savable.rb +66 -0
- data/lib/spark_api/models/contact.rb +6 -25
- data/lib/spark_api/models/dirty.rb +57 -0
- data/lib/spark_api/models/finders.rb +0 -4
- data/lib/spark_api/models/saved_search.rb +10 -0
- data/lib/spark_api/models/subresource.rb +5 -1
- data/lib/spark_api/models/subscription.rb +52 -0
- data/lib/spark_api/request.rb +17 -4
- data/lib/spark_api/response.rb +0 -37
- data/script/combined_flow_example.rb +3 -3
- data/script/oauth2_example.rb +3 -3
- data/spec/fixtures/base.json +3 -1
- data/spec/fixtures/contacts/new.json +2 -3
- data/spec/fixtures/contacts/new_empty.json +2 -3
- data/spec/fixtures/contacts/new_notify.json +1 -1
- data/spec/fixtures/{listings/saved_search.json → saved_searches/get.json} +1 -1
- data/spec/fixtures/saved_searches/new.json +8 -0
- data/spec/fixtures/saved_searches/post.json +12 -0
- data/spec/fixtures/saved_searches/update.json +6 -0
- data/spec/fixtures/subscriptions/get.json +19 -0
- data/spec/fixtures/subscriptions/new.json +13 -0
- data/spec/fixtures/subscriptions/post.json +10 -0
- data/spec/fixtures/subscriptions/put.json +12 -0
- data/spec/fixtures/subscriptions/subscribe.json +5 -0
- data/spec/fixtures/subscriptions/update.json +6 -0
- data/spec/mock_helper.rb +14 -6
- data/spec/oauth2_helper.rb +2 -0
- data/spec/spec_helper.rb +4 -7
- data/spec/unit/spark_api/authentication/api_auth_spec.rb +0 -1
- data/spec/unit/spark_api/authentication/oauth2_impl/faraday_middleware_spec.rb +32 -0
- data/spec/unit/spark_api/authentication/oauth2_impl/single_session_provider_spec.rb +9 -0
- data/spec/unit/spark_api/authentication/oauth2_spec.rb +29 -3
- data/spec/unit/spark_api/authentication_spec.rb +4 -10
- data/spec/unit/spark_api/configuration/yaml_spec.rb +4 -3
- data/spec/unit/spark_api/configuration_spec.rb +22 -8
- data/spec/unit/spark_api/models/account_spec.rb +5 -0
- data/spec/unit/spark_api/models/base_spec.rb +27 -0
- data/spec/unit/spark_api/models/concerns/destroyable_spec.rb +28 -0
- data/spec/unit/spark_api/models/concerns/savable_spec.rb +61 -0
- data/spec/unit/spark_api/models/contact_spec.rb +5 -5
- data/spec/unit/spark_api/models/dirty_spec.rb +46 -0
- data/spec/unit/spark_api/models/finders_spec.rb +0 -7
- data/spec/unit/spark_api/models/saved_search_spec.rb +34 -3
- data/spec/unit/spark_api/models/shared_listing_spec.rb +1 -1
- data/spec/unit/spark_api/models/subscription_spec.rb +106 -0
- data/spec/unit/spark_api/multi_client_spec.rb +14 -4
- data/spec/unit/spark_api/paginate_spec.rb +0 -1
- data/spec/unit/spark_api/request_spec.rb +10 -0
- data/spec/unit/spark_api_spec.rb +0 -3
- metadata +127 -45
- data/lib/spark_api/authentication/oauth2_impl/password_provider.rb +0 -24
@@ -35,6 +35,34 @@ module SparkApi
|
|
35
35
|
|
36
36
|
end
|
37
37
|
Faraday.register_middleware :response, :oauth2_impl => FaradayMiddleware
|
38
|
+
|
39
|
+
#==OAuth2 Faraday response middleware
|
40
|
+
# HTTP Response after filter to package oauth2 responses and bubble up basic api errors.
|
41
|
+
class SparkbarFaradayMiddleware < Faraday::Response::Middleware
|
42
|
+
|
43
|
+
def initialize(app)
|
44
|
+
super(app)
|
45
|
+
end
|
46
|
+
|
47
|
+
def on_complete(env)
|
48
|
+
body = MultiJson.decode(env[:body])
|
49
|
+
SparkApi.logger.debug("[sparkbar] Response Body: #{body.inspect}")
|
50
|
+
unless body.is_a?(Hash)
|
51
|
+
raise InvalidResponse, "The server response could not be understood"
|
52
|
+
end
|
53
|
+
case env[:status]
|
54
|
+
when 200..299
|
55
|
+
SparkApi.logger.debug("[sparkbar] Success!")
|
56
|
+
if body.include?("token")
|
57
|
+
env[:body] = body
|
58
|
+
return
|
59
|
+
end
|
60
|
+
end
|
61
|
+
raise ClientError, {:message => "Unable to process sparkbar token #{body.inspect}", :code =>0, :status => env[:status]}
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
Faraday.register_middleware :response, :sparkbar_impl => SparkbarFaradayMiddleware
|
38
66
|
|
39
67
|
end
|
40
68
|
end
|
@@ -45,6 +45,11 @@ module SparkApi
|
|
45
45
|
response.expires_in = provider.session_timeout if response.expires_in.nil?
|
46
46
|
SparkApi.logger.debug("[oauth2] New session created #{response}")
|
47
47
|
response
|
48
|
+
rescue Faraday::Error::ConnectionFailed => e
|
49
|
+
if @client.ssl_verify && e.message =~ /certificate verify failed/
|
50
|
+
SparkApi.logger.error(SparkApi::Errors.ssl_verification_error)
|
51
|
+
end
|
52
|
+
raise e
|
48
53
|
end
|
49
54
|
|
50
55
|
def needs_refreshing?
|
@@ -66,9 +71,9 @@ module SparkApi
|
|
66
71
|
opts = {
|
67
72
|
:headers => @client.headers
|
68
73
|
}
|
69
|
-
|
74
|
+
|
75
|
+
opts[:ssl] = {:verify => false } unless @client.ssl_verify
|
70
76
|
opts[:url] = endpoint
|
71
|
-
Faraday.register_middleware :response, :faraday_middleware => FaradayMiddleware
|
72
77
|
conn = Faraday::Connection.new(opts) do |conn|
|
73
78
|
conn.response :oauth2_impl
|
74
79
|
conn.adapter Faraday.default_adapter
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SparkApi
|
2
|
+
module Authentication
|
3
|
+
|
4
|
+
class SingleSessionProvider < BaseOAuth2Provider
|
5
|
+
|
6
|
+
def initialize(credentials)
|
7
|
+
@access_token = credentials.delete(:access_token)
|
8
|
+
super(credentials)
|
9
|
+
end
|
10
|
+
|
11
|
+
def load_session
|
12
|
+
@session ||= SparkApi::Authentication::OAuthSession.new({
|
13
|
+
:access_token => @access_token
|
14
|
+
})
|
15
|
+
end
|
16
|
+
|
17
|
+
def save_session session
|
18
|
+
@session = session
|
19
|
+
end
|
20
|
+
|
21
|
+
def destroy_session
|
22
|
+
@session = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/spark_api/cli.rb
CHANGED
@@ -14,9 +14,13 @@ module SparkApi
|
|
14
14
|
module CLI
|
15
15
|
class ConsoleCLI
|
16
16
|
OPTIONS_ENV = {
|
17
|
-
:endpoint
|
17
|
+
:endpoint => "API_ENDPOINT",
|
18
|
+
:no_verify => "NO_VERIFY",
|
18
19
|
# OAUTH2 Options
|
19
20
|
:access_uri => "ACCESS_URI",
|
21
|
+
:authorization_uri => "AUTHORIZATION_URI",
|
22
|
+
:redirect_uri => "REDIRECT_URI",
|
23
|
+
:code => "CODE",
|
20
24
|
:username=> "USERNAME",
|
21
25
|
:password=> "PASSWORD",
|
22
26
|
:client_id=> "CLIENT_ID",
|
@@ -53,6 +57,9 @@ module SparkApi
|
|
53
57
|
:endpoint => ENV[OPTIONS_ENV[:endpoint]],
|
54
58
|
# OAUTH2 Options
|
55
59
|
:access_uri => ENV[OPTIONS_ENV[:access_uri]],
|
60
|
+
:authorization_uri => ENV[OPTIONS_ENV[:authorization_uri]],
|
61
|
+
:redirect_uri => ENV[OPTIONS_ENV[:redirect_uri]],
|
62
|
+
:code => ENV[OPTIONS_ENV[:code]],
|
56
63
|
:username=> ENV[OPTIONS_ENV[:username]],
|
57
64
|
:password=> ENV[OPTIONS_ENV[:password]],
|
58
65
|
:client_id=> ENV[OPTIONS_ENV[:client_id]],
|
@@ -61,6 +68,7 @@ module SparkApi
|
|
61
68
|
:api_key => ENV[OPTIONS_ENV[:api_key]],
|
62
69
|
:api_secret => ENV[OPTIONS_ENV[:api_secret]],
|
63
70
|
:api_user => ENV[OPTIONS_ENV[:api_user]],
|
71
|
+
:no_verify => ENV.fetch(OPTIONS_ENV[:no_verify], false),
|
64
72
|
:console => ENV[OPTIONS_ENV[:console]]
|
65
73
|
}
|
66
74
|
cli_options = {}
|
@@ -77,15 +85,15 @@ module SparkApi
|
|
77
85
|
Options are:
|
78
86
|
BANNER
|
79
87
|
opts.separator ""
|
80
|
-
opts.on("-o","--oauth2",
|
81
|
-
"Run the API using OAuth2 credentials. The client defaults to using the Spark API authentication mode for access. ",
|
82
|
-
"See http://sparkplatform.com/docs/authentication/authentication for more information on authentication types.",
|
83
|
-
"Default: false") { |arg| cli_options[:oauth2] = arg }
|
84
88
|
opts.on("-e","--endpoint ENDPOINT",
|
85
89
|
"URI of the API.",
|
86
|
-
"Default: ENV['#{OPTIONS_ENV[:endpoint]}']") { |arg| cli_options[:endpoint] = arg }
|
90
|
+
"Default: ENV['#{OPTIONS_ENV[:endpoint]}'] or #{SparkApi::Configuration::DEFAULT_ENDPOINT}") { |arg| cli_options[:endpoint] = arg }
|
87
91
|
|
88
92
|
# OAUTH2
|
93
|
+
opts.on("-o","--oauth2",
|
94
|
+
"Run the API using OAuth2 credentials. The client defaults to using the Spark API authentication mode for access. ",
|
95
|
+
"See http://sparkplatform.com/docs/authentication/authentication for more information on authentication types.",
|
96
|
+
"Default: false") { |arg| cli_options[:oauth2] = arg }
|
89
97
|
opts.on("--client_id CLIENT_ID",
|
90
98
|
"OAuth2 client id",
|
91
99
|
"Default: ENV['#{OPTIONS_ENV[:client_id]}']") { |arg| cli_options[:client_id] = arg }
|
@@ -99,9 +107,17 @@ module SparkApi
|
|
99
107
|
"OAuth2 password",
|
100
108
|
"Default: ENV['#{OPTIONS_ENV[:password]}']") { |arg| cli_options[:password] = arg }
|
101
109
|
opts.on("--access_uri ACCESS_URI",
|
102
|
-
"OAuth2 path for granting access to the application",
|
103
|
-
"Default: ENV['#{OPTIONS_ENV[:access_uri]}']") { |arg| cli_options[:access_uri] = arg }
|
104
|
-
|
110
|
+
"OAuth2 path for granting access to the application using one of the supported grant types.",
|
111
|
+
"Default: ENV['#{OPTIONS_ENV[:access_uri]}'] or #{SparkApi::Configuration::DEFAULT_ACCESS_URI}") { |arg| cli_options[:access_uri] = arg }
|
112
|
+
opts.on("--redirect_uri REDIRECT_URI",
|
113
|
+
"OAuth2 application redirect for the client id. This needs to match whatever value is saved for the application's client_id",
|
114
|
+
"Default: ENV['#{OPTIONS_ENV[:redirect_uri]}'] or #{SparkApi::Configuration::DEFAULT_REDIRECT_URI}") { |arg| cli_options[:redirect_uri] = arg }
|
115
|
+
opts.on("--authorization_uri AUTHORIZATION_URI",
|
116
|
+
"OAuth2 authorization endpoint for a user. This is where the user should go to sign in and authorize client id.",
|
117
|
+
"Default: ENV['#{OPTIONS_ENV[:authorization_uri]}'] or #{SparkApi::Configuration::DEFAULT_AUTH_ENDPOINT}") { |arg| cli_options[:authorization_uri] = arg }
|
118
|
+
opts.on("--code CODE",
|
119
|
+
"OAuth2 authorization code used for granting application access to the API for a user") { |arg| cli_options[:code] = arg }
|
120
|
+
|
105
121
|
# API AUTH
|
106
122
|
opts.on("--api_key API_KEY",
|
107
123
|
"Authentication key for running the api using the default api authentication",
|
@@ -112,9 +128,12 @@ module SparkApi
|
|
112
128
|
opts.on("--api_user API_USER",
|
113
129
|
"ID of the Spark user to run the client as.",
|
114
130
|
"Default: ENV['#{OPTIONS_ENV[:api_user]}']") { |arg| cli_options[:api_user] = arg }
|
115
|
-
|
131
|
+
|
132
|
+
# General
|
116
133
|
opts.on("-f", "--file FILE",
|
117
134
|
"Load configuration for yaml file.") { |arg| file_options = parse_file_options(arg) }
|
135
|
+
opts.on("--no_verify",
|
136
|
+
"Disable SSL Certificate verification. This is useful for development servers.") { |arg| cli_options[:no_verify] = arg }
|
118
137
|
opts.on("-d", "--debug",
|
119
138
|
"Show detailed request logging information.") { |arg| cli_options[:debug] = arg }
|
120
139
|
opts.on("-v", "--version",
|
@@ -5,4 +5,5 @@ SparkApi.configure do |config|
|
|
5
5
|
config.api_secret = ENV["API_SECRET"]
|
6
6
|
config.api_user = ENV["API_USER"] if ENV["API_USER"]
|
7
7
|
config.endpoint = ENV["API_ENDPOINT"] if ENV["API_ENDPOINT"]
|
8
|
+
config.ssl_verify = ! (ENV["NO_VERIFY"].downcase=='true') if ENV["NO_VERIFY"]
|
8
9
|
end
|
data/lib/spark_api/cli/oauth2.rb
CHANGED
@@ -1,14 +1,29 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../cli/setup"
|
2
2
|
|
3
|
+
|
3
4
|
SparkApi.configure do |config|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
oauth = {
|
6
|
+
:authorization_uri=> ENV.fetch("AUTH_URI", SparkApi::Configuration::DEFAULT_AUTHORIZATION_URI),
|
7
|
+
:access_uri => ENV.fetch("ACCESS_URI", SparkApi::Configuration::DEFAULT_ACCESS_URI),
|
8
|
+
:redirect_uri => ENV.fetch("REDIRECT_URI", SparkApi::Configuration::DEFAULT_REDIRECT_URI),
|
9
|
+
:client_id=> ENV["CLIENT_ID"],
|
10
|
+
:client_secret=> ENV["CLIENT_SECRET"]
|
11
|
+
}
|
12
|
+
oauth[:username] = ENV["USERNAME"] if ENV.include?("USERNAME")
|
13
|
+
oauth[:password] = ENV["PASSWORD"] if ENV.include?("PASSWORD")
|
14
|
+
config.oauth2_provider = SparkApi::Authentication::OAuth2Impl::CLIProvider.new(oauth)
|
15
|
+
unless (oauth.include?(:username) && oauth.include?(:password))
|
16
|
+
config.oauth2_provider.grant_type = :authorization_code
|
17
|
+
config.oauth2_provider.code = ENV["CODE"] if ENV.include?("CODE")
|
18
|
+
end
|
12
19
|
config.authentication_mode = SparkApi::Authentication::OAuth2
|
13
20
|
config.endpoint = ENV["API_ENDPOINT"] if ENV["API_ENDPOINT"]
|
21
|
+
config.ssl_verify = ! (ENV["NO_VERIFY"].downcase=='true') if ENV["NO_VERIFY"]
|
14
22
|
end
|
23
|
+
|
24
|
+
# Enables saving and loading serialized oauth2 sessions for the system user.
|
25
|
+
def persist_sessions! my_alias = nil
|
26
|
+
warn "Warning: persistent session mode saves access tokens in clear text on the filesystem."
|
27
|
+
SparkApi.client.oauth2_provider.session_alias = my_alias unless my_alias.nil?
|
28
|
+
SparkApi.client.oauth2_provider.persistent_sessions = true
|
29
|
+
end
|
data/lib/spark_api/cli/setup.rb
CHANGED
@@ -45,3 +45,34 @@ include SparkApi::Models
|
|
45
45
|
def c
|
46
46
|
SparkApi.client
|
47
47
|
end
|
48
|
+
|
49
|
+
# Straight up HTTP functions y'all!!!
|
50
|
+
|
51
|
+
def get(path, options={})
|
52
|
+
c.get(path, options)
|
53
|
+
end
|
54
|
+
|
55
|
+
def post(path, body = nil, options={})
|
56
|
+
c.post(path, body, options)
|
57
|
+
end
|
58
|
+
|
59
|
+
def put(path, body = nil, options={})
|
60
|
+
c.put(path, body, options)
|
61
|
+
end
|
62
|
+
|
63
|
+
def delete(path, options={})
|
64
|
+
c.delete(path, options)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Handy session persistence
|
68
|
+
def save_oauth2_session! session_alias = "default"
|
69
|
+
|
70
|
+
rescue => e
|
71
|
+
puts "Unable to save the oauth2 session: #{e.message}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def load_oauth2_session session_alias = "default"
|
75
|
+
c.oauth2_provider.session = ""
|
76
|
+
rescue => e
|
77
|
+
puts "Unable to find a saved oauth2 session: #{e.message}"
|
78
|
+
end
|
@@ -5,13 +5,16 @@ module SparkApi
|
|
5
5
|
|
6
6
|
# valid configuration options
|
7
7
|
VALID_OPTION_KEYS = [:api_key, :api_secret, :api_user, :endpoint,
|
8
|
-
:user_agent, :version, :ssl, :oauth2_provider, :authentication_mode,
|
8
|
+
:user_agent, :version, :ssl, :ssl_verify, :oauth2_provider, :authentication_mode,
|
9
9
|
:auth_endpoint, :callback].freeze
|
10
10
|
OAUTH2_KEYS = [:authorization_uri, :access_uri, :client_id, :client_secret,
|
11
11
|
# Requirements for authorization_code grant type
|
12
12
|
:redirect_uri,
|
13
13
|
# Requirements for password grant type
|
14
|
-
:username, :password
|
14
|
+
:username, :password,
|
15
|
+
# Requirements for single session keys
|
16
|
+
:access_token,
|
17
|
+
:sparkbar_uri
|
15
18
|
]
|
16
19
|
|
17
20
|
require File.expand_path('../configuration/yaml', __FILE__)
|
@@ -23,10 +26,14 @@ module SparkApi
|
|
23
26
|
DEFAULT_API_SECRET = nil
|
24
27
|
DEFAULT_API_USER = nil
|
25
28
|
DEFAULT_ENDPOINT = 'https://api.sparkapi.com'
|
29
|
+
DEFAULT_REDIRECT_URI = "https://sparkplatform.com/oauth2/callback"
|
26
30
|
DEFAULT_AUTH_ENDPOINT = 'https://sparkplatform.com/openid' # Ignored for Spark API Auth
|
31
|
+
DEFAULT_AUTHORIZATION_URI = 'https://sparkplatform.com/oauth2'
|
27
32
|
DEFAULT_VERSION = 'v1'
|
33
|
+
DEFAULT_ACCESS_URI = "#{DEFAULT_ENDPOINT}/#{DEFAULT_VERSION}/oauth2/grant"
|
28
34
|
DEFAULT_USER_AGENT = "Spark API Ruby Gem #{VERSION}"
|
29
35
|
DEFAULT_SSL = true
|
36
|
+
DEFAULT_SSL_VERIFY = true
|
30
37
|
DEFAULT_OAUTH2 = nil
|
31
38
|
|
32
39
|
X_SPARK_API_USER_AGENT = "X-SparkApi-User-Agent"
|
@@ -57,6 +64,7 @@ module SparkApi
|
|
57
64
|
self.oauth2_provider = DEFAULT_OAUTH2
|
58
65
|
self.user_agent = DEFAULT_USER_AGENT
|
59
66
|
self.ssl = DEFAULT_SSL
|
67
|
+
self.ssl_verify = DEFAULT_SSL_VERIFY
|
60
68
|
self.version = DEFAULT_VERSION
|
61
69
|
self
|
62
70
|
end
|
@@ -5,7 +5,7 @@ module SparkApi
|
|
5
5
|
module Configuration
|
6
6
|
class YamlConfig
|
7
7
|
KEY_CONFIGURATIONS = VALID_OPTION_KEYS + [:oauth2] + OAUTH2_KEYS
|
8
|
-
DEFAULT_OAUTH2_PROVIDER = "SparkApi::Authentication::OAuth2Impl::
|
8
|
+
DEFAULT_OAUTH2_PROVIDER = "SparkApi::Authentication::OAuth2Impl::CLIProvider"
|
9
9
|
attr_accessor *KEY_CONFIGURATIONS
|
10
10
|
attr_reader :client_keys, :oauth2_keys, :provider
|
11
11
|
|
@@ -26,10 +26,15 @@ module SparkApi
|
|
26
26
|
def oauth2?
|
27
27
|
return oauth2 == true
|
28
28
|
end
|
29
|
+
|
30
|
+
def ssl_verify?
|
31
|
+
return ssl_verify == true
|
32
|
+
end
|
29
33
|
|
30
34
|
def name
|
31
35
|
@name
|
32
36
|
end
|
37
|
+
|
33
38
|
def api_env
|
34
39
|
if env.include? "SPARK_API_ENV"
|
35
40
|
env["SPARK_API_ENV"]
|
data/lib/spark_api/connection.rb
CHANGED
@@ -12,7 +12,7 @@ module SparkApi
|
|
12
12
|
:headers => headers
|
13
13
|
}
|
14
14
|
if(force_ssl || self.ssl)
|
15
|
-
opts[:ssl] = {:verify => false }
|
15
|
+
opts[:ssl] = {:verify => false } unless self.ssl_verify
|
16
16
|
opts[:url] = @endpoint.sub /^http:/, "https:"
|
17
17
|
else
|
18
18
|
opts[:url] = @endpoint.sub /^https:/, "http:"
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module SparkApi
|
2
|
+
|
3
|
+
# All known response codes listed in the API
|
4
|
+
module ResponseCodes
|
5
|
+
NOT_FOUND = 404
|
6
|
+
METHOD_NOT_ALLOWED = 405
|
7
|
+
INVALID_KEY = 1000
|
8
|
+
DISABLED_KEY = 1010
|
9
|
+
API_USER_REQUIRED = 1015
|
10
|
+
SESSION_TOKEN_EXPIRED = 1020
|
11
|
+
SSL_REQUIRED = 1030
|
12
|
+
INVALID_JSON = 1035
|
13
|
+
INVALID_FIELD = 1040
|
14
|
+
MISSING_PARAMETER = 1050
|
15
|
+
INVALID_PARAMETER = 1053
|
16
|
+
CONFLICTING_DATA = 1055
|
17
|
+
NOT_AVAILABLE= 1500
|
18
|
+
RATE_LIMIT_EXCEEDED = 1550
|
19
|
+
end
|
20
|
+
|
21
|
+
# Errors built from API responses
|
22
|
+
class InvalidResponse < StandardError; end
|
23
|
+
class ClientError < StandardError
|
24
|
+
attr_reader :code, :status, :details
|
25
|
+
def initialize (options = {})
|
26
|
+
# Support the standard initializer for errors
|
27
|
+
opts = options.is_a?(Hash) ? options : {:message => options.to_s}
|
28
|
+
@code = opts[:code]
|
29
|
+
@status = opts[:status]
|
30
|
+
@details = opts[:details]
|
31
|
+
super(opts[:message])
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
class NotFound < ClientError; end
|
36
|
+
class PermissionDenied < ClientError; end
|
37
|
+
class NotAllowed < ClientError; end
|
38
|
+
class BadResourceRequest < ClientError; end
|
39
|
+
|
40
|
+
# =Errors
|
41
|
+
# Error messages and other error handling
|
42
|
+
module Errors
|
43
|
+
def self.ssl_verification_error
|
44
|
+
"SSL verification problem: if connecting to a trusted but non production API endpoint, " +
|
45
|
+
"set 'ssl_verify' to false in the configuration or add '--no_verify' to the CLI command."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/spark_api/models.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
require 'spark_api/models/dirty'
|
1
2
|
require 'spark_api/models/base'
|
2
3
|
require 'spark_api/models/constraint'
|
3
4
|
require 'spark_api/models/finders'
|
4
5
|
require 'spark_api/models/subresource'
|
6
|
+
require 'spark_api/models/concerns'
|
5
7
|
|
6
8
|
require 'spark_api/models/account'
|
7
9
|
require 'spark_api/models/connect_prefs'
|
@@ -26,6 +28,7 @@ require 'spark_api/models/tour_of_home'
|
|
26
28
|
require 'spark_api/models/video'
|
27
29
|
require 'spark_api/models/virtual_tour'
|
28
30
|
require 'spark_api/models/rental_calendar'
|
31
|
+
require 'spark_api/models/subscription'
|
29
32
|
|
30
33
|
module SparkApi
|
31
34
|
module Models
|
@@ -39,7 +39,15 @@ module SparkApi
|
|
39
39
|
def primary_img(typ)
|
40
40
|
if @images.is_a?(Array)
|
41
41
|
matches = @images.select {|i| i.Type == typ}
|
42
|
-
matches.sort
|
42
|
+
matches.sort do |a,b|
|
43
|
+
if a.Name.nil? && !b.Name.nil?
|
44
|
+
1
|
45
|
+
elsif b.Name.nil? && !a.Name.nil?
|
46
|
+
-1
|
47
|
+
else
|
48
|
+
a.Name.to_s <=> b.Name.to_s
|
49
|
+
end
|
50
|
+
end.first
|
43
51
|
else
|
44
52
|
nil
|
45
53
|
end
|
@@ -5,10 +5,10 @@ module SparkApi
|
|
5
5
|
# active model type niceties.
|
6
6
|
class Base
|
7
7
|
extend Paginate
|
8
|
+
include Dirty
|
8
9
|
|
9
10
|
attr_accessor :attributes, :errors
|
10
|
-
|
11
|
-
|
11
|
+
|
12
12
|
# Name of the resource as related to the path name
|
13
13
|
def self.element_name
|
14
14
|
# TODO I'd love to pull in active model at this point to provide default naming
|
@@ -18,7 +18,7 @@ module SparkApi
|
|
18
18
|
def self.element_name=(name)
|
19
19
|
@element_name = name
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
# Resource path prefix, prepended to the url
|
23
23
|
def self.prefix
|
24
24
|
@prefix ||= "/"
|
@@ -29,7 +29,7 @@ module SparkApi
|
|
29
29
|
def self.path
|
30
30
|
"#{prefix}#{element_name}"
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def self.connection
|
34
34
|
SparkApi.client
|
35
35
|
end
|
@@ -40,7 +40,6 @@ module SparkApi
|
|
40
40
|
def initialize(attributes={})
|
41
41
|
@attributes = {}
|
42
42
|
@errors = []
|
43
|
-
@changed = []
|
44
43
|
load(attributes)
|
45
44
|
end
|
46
45
|
|
@@ -49,7 +48,7 @@ module SparkApi
|
|
49
48
|
@attributes[key.to_s] = val
|
50
49
|
end
|
51
50
|
end
|
52
|
-
|
51
|
+
|
53
52
|
def self.get(options={})
|
54
53
|
collect(connection.get(path, options))
|
55
54
|
end
|
@@ -61,28 +60,28 @@ module SparkApi
|
|
61
60
|
def self.count(options={})
|
62
61
|
connection.get(path, options.merge({:_pagination=>"count"}))
|
63
62
|
end
|
64
|
-
|
63
|
+
|
65
64
|
def method_missing(method_symbol, *arguments)
|
66
65
|
method_name = method_symbol.to_s
|
67
66
|
|
68
|
-
if method_name =~ /(
|
67
|
+
if method_name =~ /(=|\?|_will_change!)$/
|
69
68
|
case $1
|
70
69
|
when "="
|
71
70
|
write_attribute($`, arguments.first)
|
72
71
|
# TODO figure out a nice way to present setters for the standard fields
|
73
72
|
when "?"
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
73
|
+
raise NoMethodError unless attributes.include?($`)
|
74
|
+
attributes[$`] ? true : false
|
75
|
+
when "_will_change!"
|
76
|
+
raise NoMethodError unless attributes.include?($`)
|
77
|
+
attribute_will_change!($`)
|
79
78
|
end
|
80
79
|
else
|
81
80
|
return attributes[method_name] if attributes.include?(method_name)
|
82
81
|
super # GTFO
|
83
82
|
end
|
84
83
|
end
|
85
|
-
|
84
|
+
|
86
85
|
def respond_to?(method_symbol, include_private=false)
|
87
86
|
if super
|
88
87
|
return true
|
@@ -93,26 +92,32 @@ module SparkApi
|
|
93
92
|
true
|
94
93
|
elsif method_name =~ /(\?)$/
|
95
94
|
attributes.include?($`)
|
95
|
+
elsif method_name =~ /(\w*)_will_change!$/
|
96
|
+
attributes.include?($1)
|
96
97
|
else
|
97
98
|
attributes.include?(method_name)
|
98
99
|
end
|
99
100
|
|
100
101
|
end
|
101
102
|
end
|
102
|
-
|
103
|
+
|
103
104
|
def parse_id(uri)
|
104
105
|
uri[/\/.*\/(.+)$/, 1]
|
105
106
|
end
|
106
|
-
|
107
|
+
|
108
|
+
def persisted?
|
109
|
+
!(@attributes['Id'].nil? && @attributes['ResourceUri'].nil?)
|
110
|
+
end
|
111
|
+
|
107
112
|
protected
|
108
|
-
|
113
|
+
|
109
114
|
def write_attribute(attribute, value)
|
110
115
|
unless attributes[attribute] == value
|
116
|
+
attribute_will_change!(attribute)
|
111
117
|
attributes[attribute] = value
|
112
|
-
@changed << attribute unless @changed.include?(attribute)
|
113
118
|
end
|
114
119
|
end
|
115
|
-
|
120
|
+
|
116
121
|
end
|
117
122
|
end
|
118
123
|
end
|