spark_api 1.0.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.
- data/History.txt +139 -0
- data/LICENSE +14 -0
- data/README.md +153 -0
- data/Rakefile +18 -0
- data/VERSION +1 -0
- data/bin/spark_api +8 -0
- data/bin/spark_api~ +8 -0
- data/lib/spark_api.rb +46 -0
- data/lib/spark_api/authentication.rb +55 -0
- data/lib/spark_api/authentication/api_auth.rb +104 -0
- data/lib/spark_api/authentication/api_auth.rb~ +104 -0
- data/lib/spark_api/authentication/base_auth.rb +47 -0
- data/lib/spark_api/authentication/base_auth.rb~ +47 -0
- data/lib/spark_api/authentication/oauth2.rb +198 -0
- data/lib/spark_api/authentication/oauth2.rb~ +199 -0
- data/lib/spark_api/authentication/oauth2_impl/grant_type_base.rb +87 -0
- data/lib/spark_api/authentication/oauth2_impl/grant_type_base.rb~ +87 -0
- data/lib/spark_api/authentication/oauth2_impl/grant_type_code.rb +48 -0
- data/lib/spark_api/authentication/oauth2_impl/grant_type_code.rb~ +49 -0
- data/lib/spark_api/authentication/oauth2_impl/grant_type_password.rb +44 -0
- data/lib/spark_api/authentication/oauth2_impl/grant_type_password.rb~ +45 -0
- data/lib/spark_api/authentication/oauth2_impl/grant_type_refresh.rb +35 -0
- data/lib/spark_api/authentication/oauth2_impl/grant_type_refresh.rb~ +36 -0
- data/lib/spark_api/authentication/oauth2_impl/middleware.rb +38 -0
- data/lib/spark_api/authentication/oauth2_impl/middleware.rb~ +39 -0
- data/lib/spark_api/authentication/oauth2_impl/password_provider.rb +24 -0
- data/lib/spark_api/authentication/oauth2_impl/password_provider.rb~ +25 -0
- data/lib/spark_api/cli.rb +158 -0
- data/lib/spark_api/cli.rb~ +158 -0
- data/lib/spark_api/cli/api_auth.rb +8 -0
- data/lib/spark_api/cli/api_auth.rb~ +8 -0
- data/lib/spark_api/cli/oauth2.rb +14 -0
- data/lib/spark_api/cli/oauth2.rb~ +14 -0
- data/lib/spark_api/cli/setup.rb +47 -0
- data/lib/spark_api/cli/setup.rb~ +47 -0
- data/lib/spark_api/client.rb +27 -0
- data/lib/spark_api/configuration.rb +54 -0
- data/lib/spark_api/configuration.rb~ +54 -0
- data/lib/spark_api/configuration/yaml.rb +101 -0
- data/lib/spark_api/configuration/yaml.rb~ +101 -0
- data/lib/spark_api/connection.rb +42 -0
- data/lib/spark_api/faraday.rb +64 -0
- data/lib/spark_api/faraday.rb~ +64 -0
- data/lib/spark_api/models.rb +33 -0
- data/lib/spark_api/models.rb~ +33 -0
- data/lib/spark_api/models/account.rb +115 -0
- data/lib/spark_api/models/account.rb~ +115 -0
- data/lib/spark_api/models/base.rb +118 -0
- data/lib/spark_api/models/base.rb~ +118 -0
- data/lib/spark_api/models/connect_prefs.rb +10 -0
- data/lib/spark_api/models/connect_prefs.rb~ +10 -0
- data/lib/spark_api/models/constraint.rb +16 -0
- data/lib/spark_api/models/constraint.rb~ +16 -0
- data/lib/spark_api/models/contact.rb +49 -0
- data/lib/spark_api/models/contact.rb~ +49 -0
- data/lib/spark_api/models/custom_fields.rb +12 -0
- data/lib/spark_api/models/custom_fields.rb~ +12 -0
- data/lib/spark_api/models/document.rb +11 -0
- data/lib/spark_api/models/document.rb~ +11 -0
- data/lib/spark_api/models/finders.rb +45 -0
- data/lib/spark_api/models/finders.rb~ +45 -0
- data/lib/spark_api/models/idx_link.rb +47 -0
- data/lib/spark_api/models/idx_link.rb~ +47 -0
- data/lib/spark_api/models/listing.rb +197 -0
- data/lib/spark_api/models/listing.rb~ +197 -0
- data/lib/spark_api/models/listing_cart.rb +72 -0
- data/lib/spark_api/models/listing_cart.rb~ +72 -0
- data/lib/spark_api/models/market_statistics.rb +33 -0
- data/lib/spark_api/models/market_statistics.rb~ +33 -0
- data/lib/spark_api/models/message.rb +21 -0
- data/lib/spark_api/models/message.rb~ +21 -0
- data/lib/spark_api/models/note.rb +41 -0
- data/lib/spark_api/models/note.rb~ +41 -0
- data/lib/spark_api/models/notification.rb +42 -0
- data/lib/spark_api/models/notification.rb~ +42 -0
- data/lib/spark_api/models/open_house.rb +24 -0
- data/lib/spark_api/models/open_house.rb~ +24 -0
- data/lib/spark_api/models/photo.rb +70 -0
- data/lib/spark_api/models/photo.rb~ +70 -0
- data/lib/spark_api/models/property_types.rb +7 -0
- data/lib/spark_api/models/property_types.rb~ +7 -0
- data/lib/spark_api/models/saved_search.rb +16 -0
- data/lib/spark_api/models/saved_search.rb~ +16 -0
- data/lib/spark_api/models/shared_listing.rb +35 -0
- data/lib/spark_api/models/shared_listing.rb~ +35 -0
- data/lib/spark_api/models/standard_fields.rb +50 -0
- data/lib/spark_api/models/standard_fields.rb~ +50 -0
- data/lib/spark_api/models/subresource.rb +19 -0
- data/lib/spark_api/models/subresource.rb~ +19 -0
- data/lib/spark_api/models/system_info.rb +14 -0
- data/lib/spark_api/models/system_info.rb~ +14 -0
- data/lib/spark_api/models/tour_of_home.rb +24 -0
- data/lib/spark_api/models/tour_of_home.rb~ +24 -0
- data/lib/spark_api/models/video.rb +16 -0
- data/lib/spark_api/models/video.rb~ +16 -0
- data/lib/spark_api/models/virtual_tour.rb +18 -0
- data/lib/spark_api/models/virtual_tour.rb~ +18 -0
- data/lib/spark_api/multi_client.rb +59 -0
- data/lib/spark_api/multi_client.rb~ +59 -0
- data/lib/spark_api/paginate.rb +109 -0
- data/lib/spark_api/paginate.rb~ +109 -0
- data/lib/spark_api/primary_array.rb +29 -0
- data/lib/spark_api/primary_array.rb~ +29 -0
- data/lib/spark_api/request.rb +96 -0
- data/lib/spark_api/request.rb~ +96 -0
- data/lib/spark_api/response.rb +70 -0
- data/lib/spark_api/response.rb~ +70 -0
- data/lib/spark_api/version.rb +4 -0
- data/lib/spark_api/version.rb~ +4 -0
- data/script/console +6 -0
- data/script/console~ +6 -0
- data/script/example.rb +27 -0
- data/script/example.rb~ +27 -0
- data/spec/fixtures/accounts/all.json +160 -0
- data/spec/fixtures/accounts/my.json +74 -0
- data/spec/fixtures/accounts/my_portal.json +20 -0
- data/spec/fixtures/accounts/my_put.json +5 -0
- data/spec/fixtures/accounts/my_save.json +5 -0
- data/spec/fixtures/accounts/office.json +142 -0
- data/spec/fixtures/accounts/password_save.json +6 -0
- data/spec/fixtures/authentication_failure.json +7 -0
- data/spec/fixtures/base.json +13 -0
- data/spec/fixtures/contacts/contacts.json +28 -0
- data/spec/fixtures/contacts/my.json +19 -0
- data/spec/fixtures/contacts/new.json +11 -0
- data/spec/fixtures/contacts/new_empty.json +8 -0
- data/spec/fixtures/contacts/new_notify.json +11 -0
- data/spec/fixtures/contacts/post.json +10 -0
- data/spec/fixtures/contacts/tags.json +11 -0
- data/spec/fixtures/count.json +10 -0
- data/spec/fixtures/empty.json +3 -0
- data/spec/fixtures/errors/expired.json +7 -0
- data/spec/fixtures/errors/failure.json +5 -0
- data/spec/fixtures/errors/failure_with_constraint.json +17 -0
- data/spec/fixtures/errors/failure_with_msg.json +7 -0
- data/spec/fixtures/generic_delete.json +1 -0
- data/spec/fixtures/generic_failure.json +5 -0
- data/spec/fixtures/listing_carts/add_listing.json +13 -0
- data/spec/fixtures/listing_carts/add_listing_post.json +5 -0
- data/spec/fixtures/listing_carts/empty.json +5 -0
- data/spec/fixtures/listing_carts/listing_cart.json +19 -0
- data/spec/fixtures/listing_carts/new.json +12 -0
- data/spec/fixtures/listing_carts/post.json +10 -0
- data/spec/fixtures/listing_carts/remove_listing.json +13 -0
- data/spec/fixtures/listings/constraints.json +18 -0
- data/spec/fixtures/listings/constraints_with_pagination.json +24 -0
- data/spec/fixtures/listings/document_index.json +19 -0
- data/spec/fixtures/listings/multiple.json +69 -0
- data/spec/fixtures/listings/no_subresources.json +38 -0
- data/spec/fixtures/listings/open_houses.json +21 -0
- data/spec/fixtures/listings/photos/index.json +469 -0
- data/spec/fixtures/listings/photos/new.json +12 -0
- data/spec/fixtures/listings/photos/post.json +20 -0
- data/spec/fixtures/listings/put.json +5 -0
- data/spec/fixtures/listings/put_expiration_date.json +5 -0
- data/spec/fixtures/listings/saved_search.json +17 -0
- data/spec/fixtures/listings/shared_listing_get.json +14 -0
- data/spec/fixtures/listings/shared_listing_new.json +9 -0
- data/spec/fixtures/listings/shared_listing_post.json +10 -0
- data/spec/fixtures/listings/tour_of_homes.json +23 -0
- data/spec/fixtures/listings/videos_index.json +18 -0
- data/spec/fixtures/listings/virtual_tours_index.json +42 -0
- data/spec/fixtures/listings/with_documents.json +52 -0
- data/spec/fixtures/listings/with_permissions.json +44 -0
- data/spec/fixtures/listings/with_photos.json +110 -0
- data/spec/fixtures/listings/with_supplement.json +39 -0
- data/spec/fixtures/listings/with_videos.json +54 -0
- data/spec/fixtures/listings/with_vtour.json +48 -0
- data/spec/fixtures/logo_fbs.png +0 -0
- data/spec/fixtures/messages/new.json +14 -0
- data/spec/fixtures/messages/new_empty.json +7 -0
- data/spec/fixtures/messages/new_with_recipients.json +15 -0
- data/spec/fixtures/messages/post.json +5 -0
- data/spec/fixtures/notes/add.json +11 -0
- data/spec/fixtures/notes/agent_shared.json +11 -0
- data/spec/fixtures/notes/agent_shared_empty.json +7 -0
- data/spec/fixtures/notes/new.json +5 -0
- data/spec/fixtures/notifications/mark_read.json +1 -0
- data/spec/fixtures/notifications/new.json +8 -0
- data/spec/fixtures/notifications/new_empty.json +7 -0
- data/spec/fixtures/notifications/notifications.json +43 -0
- data/spec/fixtures/notifications/post.json +10 -0
- data/spec/fixtures/notifications/unread.json +10 -0
- data/spec/fixtures/oauth2/access.json +3 -0
- data/spec/fixtures/oauth2/access_with_old_refresh.json +5 -0
- data/spec/fixtures/oauth2/access_with_refresh.json +5 -0
- data/spec/fixtures/oauth2/authorization_code_body.json +7 -0
- data/spec/fixtures/oauth2/error.json +3 -0
- data/spec/fixtures/oauth2/password_body.json +7 -0
- data/spec/fixtures/oauth2/refresh_body.json +7 -0
- data/spec/fixtures/oauth2_error.json +3 -0
- data/spec/fixtures/property_types/property_types.json +31 -0
- data/spec/fixtures/session.json +10 -0
- data/spec/fixtures/standardfields/city.json +1031 -0
- data/spec/fixtures/standardfields/nearby.json +53 -0
- data/spec/fixtures/standardfields/standardfields.json +188 -0
- data/spec/fixtures/standardfields/stateorprovince.json +36 -0
- data/spec/fixtures/success.json +5 -0
- data/spec/json_helper.rb +76 -0
- data/spec/mock_helper.rb +124 -0
- data/spec/oauth2_helper.rb +68 -0
- data/spec/spec_helper.rb +48 -0
- data/spec/unit/flexmls_api_spec.rb~ +23 -0
- data/spec/unit/spark_api/authentication/api_auth_spec.rb +169 -0
- data/spec/unit/spark_api/authentication/api_auth_spec.rb~ +169 -0
- data/spec/unit/spark_api/authentication/base_auth_spec.rb +10 -0
- data/spec/unit/spark_api/authentication/base_auth_spec.rb~ +10 -0
- data/spec/unit/spark_api/authentication/oauth2_impl/grant_type_base_spec.rb +10 -0
- data/spec/unit/spark_api/authentication/oauth2_impl/grant_type_base_spec.rb~ +10 -0
- data/spec/unit/spark_api/authentication/oauth2_spec.rb +205 -0
- data/spec/unit/spark_api/authentication/oauth2_spec.rb~ +205 -0
- data/spec/unit/spark_api/authentication_spec.rb +38 -0
- data/spec/unit/spark_api/authentication_spec.rb~ +38 -0
- data/spec/unit/spark_api/configuration/yaml_spec.rb +72 -0
- data/spec/unit/spark_api/configuration/yaml_spec.rb~ +72 -0
- data/spec/unit/spark_api/configuration_spec.rb +122 -0
- data/spec/unit/spark_api/configuration_spec.rb~ +122 -0
- data/spec/unit/spark_api/faraday_spec.rb +90 -0
- data/spec/unit/spark_api/faraday_spec.rb~ +90 -0
- data/spec/unit/spark_api/models/account_spec.rb +176 -0
- data/spec/unit/spark_api/models/base_spec.rb +106 -0
- data/spec/unit/spark_api/models/connect_prefs_spec.rb +9 -0
- data/spec/unit/spark_api/models/constraint_spec.rb +19 -0
- data/spec/unit/spark_api/models/contact_spec.rb +108 -0
- data/spec/unit/spark_api/models/contact_spec.rb~ +108 -0
- data/spec/unit/spark_api/models/document_spec.rb +32 -0
- data/spec/unit/spark_api/models/listing_cart_spec.rb +127 -0
- data/spec/unit/spark_api/models/listing_cart_spec.rb~ +127 -0
- data/spec/unit/spark_api/models/listing_spec.rb +320 -0
- data/spec/unit/spark_api/models/listing_spec.rb~ +320 -0
- data/spec/unit/spark_api/models/message_spec.rb +47 -0
- data/spec/unit/spark_api/models/message_spec.rb~ +47 -0
- data/spec/unit/spark_api/models/note_spec.rb +63 -0
- data/spec/unit/spark_api/models/note_spec.rb~ +63 -0
- data/spec/unit/spark_api/models/notification_spec.rb +62 -0
- data/spec/unit/spark_api/models/notification_spec.rb~ +62 -0
- data/spec/unit/spark_api/models/open_house_spec.rb +39 -0
- data/spec/unit/spark_api/models/photo_spec.rb +92 -0
- data/spec/unit/spark_api/models/property_types_spec.rb +33 -0
- data/spec/unit/spark_api/models/saved_search_spec.rb +40 -0
- data/spec/unit/spark_api/models/shared_listing_spec.rb +45 -0
- data/spec/unit/spark_api/models/shared_listing_spec.rb~ +45 -0
- data/spec/unit/spark_api/models/standard_fields_spec.rb +60 -0
- data/spec/unit/spark_api/models/system_info_spec.rb +83 -0
- data/spec/unit/spark_api/models/tour_of_home_spec.rb +44 -0
- data/spec/unit/spark_api/models/video_spec.rb +36 -0
- data/spec/unit/spark_api/models/virtual_tour_spec.rb +44 -0
- data/spec/unit/spark_api/multi_client_spec.rb +56 -0
- data/spec/unit/spark_api/multi_client_spec.rb~ +56 -0
- data/spec/unit/spark_api/paginate_spec.rb +224 -0
- data/spec/unit/spark_api/paginate_spec.rb~ +224 -0
- data/spec/unit/spark_api/primary_array_spec.rb +41 -0
- data/spec/unit/spark_api/primary_array_spec.rb~ +41 -0
- data/spec/unit/spark_api/request_spec.rb +344 -0
- data/spec/unit/spark_api/request_spec.rb~ +344 -0
- data/spec/unit/spark_api_spec.rb +23 -0
- metadata +725 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module SparkApi
|
|
2
|
+
module Authentication
|
|
3
|
+
module OAuth2Impl
|
|
4
|
+
# OAuth2 authentication flow using username and password parameters for the user in the
|
|
5
|
+
# request. This implementation is geared towards authentication styles for native
|
|
6
|
+
# applications that need to use OAuth2
|
|
7
|
+
class GrantTypePassword < GrantTypeBase
|
|
8
|
+
def initialize(client, provider, session)
|
|
9
|
+
super(client, provider, session)
|
|
10
|
+
end
|
|
11
|
+
def authenticate
|
|
12
|
+
new_session = nil
|
|
13
|
+
if needs_refreshing?
|
|
14
|
+
new_session = refresh
|
|
15
|
+
end
|
|
16
|
+
return new_session unless new_session.nil?
|
|
17
|
+
create_session(token_params)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def refresh()
|
|
21
|
+
GrantTypeRefresh.new(client,provider,session).authenticate
|
|
22
|
+
rescue ClientError => e
|
|
23
|
+
SparkApi.logger.info("[oauth2] Refreshing token failed, the library will try and authenticate from scratch: #{e.message}")
|
|
24
|
+
nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
def token_params
|
|
29
|
+
params = {
|
|
30
|
+
"client_id" => @provider.client_id,
|
|
31
|
+
"client_secret" => @provider.client_secret,
|
|
32
|
+
"grant_type" => "password",
|
|
33
|
+
"username" => @provider.username,
|
|
34
|
+
"password" => @provider.password,
|
|
35
|
+
}.to_json
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
|
|
2
|
+
module FlexmlsApi
|
|
3
|
+
module Authentication
|
|
4
|
+
module OAuth2Impl
|
|
5
|
+
# OAuth2 authentication flow using username and password parameters for the user in the
|
|
6
|
+
# request. This implementation is geared towards authentication styles for native
|
|
7
|
+
# applications that need to use OAuth2
|
|
8
|
+
class GrantTypePassword < GrantTypeBase
|
|
9
|
+
def initialize(client, provider, session)
|
|
10
|
+
super(client, provider, session)
|
|
11
|
+
end
|
|
12
|
+
def authenticate
|
|
13
|
+
new_session = nil
|
|
14
|
+
if needs_refreshing?
|
|
15
|
+
new_session = refresh
|
|
16
|
+
end
|
|
17
|
+
return new_session unless new_session.nil?
|
|
18
|
+
create_session(token_params)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def refresh()
|
|
22
|
+
GrantTypeRefresh.new(client,provider,session).authenticate
|
|
23
|
+
rescue ClientError => e
|
|
24
|
+
FlexmlsApi.logger.info("[oauth2] Refreshing token failed, the library will try and authenticate from scratch: #{e.message}")
|
|
25
|
+
nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
def token_params
|
|
30
|
+
params = {
|
|
31
|
+
"client_id" => @provider.client_id,
|
|
32
|
+
"client_secret" => @provider.client_secret,
|
|
33
|
+
"grant_type" => "password",
|
|
34
|
+
"username" => @provider.username,
|
|
35
|
+
"password" => @provider.password,
|
|
36
|
+
}.to_json
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module SparkApi
|
|
2
|
+
module Authentication
|
|
3
|
+
# OAuth2 authentication flow to refresh an access token
|
|
4
|
+
module OAuth2Impl
|
|
5
|
+
class GrantTypeRefresh < GrantTypeBase
|
|
6
|
+
attr_accessor :params
|
|
7
|
+
def initialize(client, provider, session)
|
|
8
|
+
super(client, provider, session)
|
|
9
|
+
@params = {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def authenticate
|
|
13
|
+
new_session = nil
|
|
14
|
+
unless @session.refresh_token.nil?
|
|
15
|
+
SparkApi.logger.debug("[oauth2] Refreshing authentication to #{provider.access_uri} using [#{session.refresh_token}]")
|
|
16
|
+
new_session = create_session(token_params)
|
|
17
|
+
end
|
|
18
|
+
new_session
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
def token_params
|
|
23
|
+
@params.merge({
|
|
24
|
+
"client_id" => @provider.client_id,
|
|
25
|
+
"client_secret" => @provider.client_secret,
|
|
26
|
+
"grant_type" => "refresh_token",
|
|
27
|
+
"refresh_token"=> session.refresh_token,
|
|
28
|
+
}).to_json
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
module FlexmlsApi
|
|
3
|
+
module Authentication
|
|
4
|
+
# OAuth2 authentication flow to refresh an access token
|
|
5
|
+
module OAuth2Impl
|
|
6
|
+
class GrantTypeRefresh < GrantTypeBase
|
|
7
|
+
attr_accessor :params
|
|
8
|
+
def initialize(client, provider, session)
|
|
9
|
+
super(client, provider, session)
|
|
10
|
+
@params = {}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def authenticate
|
|
14
|
+
new_session = nil
|
|
15
|
+
unless @session.refresh_token.nil?
|
|
16
|
+
FlexmlsApi.logger.debug("[oauth2] Refreshing authentication to #{provider.access_uri} using [#{session.refresh_token}]")
|
|
17
|
+
new_session = create_session(token_params)
|
|
18
|
+
end
|
|
19
|
+
new_session
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
def token_params
|
|
24
|
+
@params.merge({
|
|
25
|
+
"client_id" => @provider.client_id,
|
|
26
|
+
"client_secret" => @provider.client_secret,
|
|
27
|
+
"grant_type" => "refresh_token",
|
|
28
|
+
"refresh_token"=> session.refresh_token,
|
|
29
|
+
}).to_json
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module SparkApi
|
|
2
|
+
|
|
3
|
+
module Authentication
|
|
4
|
+
|
|
5
|
+
module OAuth2Impl
|
|
6
|
+
|
|
7
|
+
#==OAuth2 Faraday response middleware
|
|
8
|
+
# HTTP Response after filter to package oauth2 responses and bubble up basic api errors.
|
|
9
|
+
class Middleware < Faraday::Response::ParseJson
|
|
10
|
+
def on_complete(finished_env)
|
|
11
|
+
body = parse(finished_env[:body])
|
|
12
|
+
SparkApi.logger.debug("[oauth2] Response Body: #{body.inspect}")
|
|
13
|
+
unless body.is_a?(Hash)
|
|
14
|
+
raise InvalidResponse, "The server response could not be understood"
|
|
15
|
+
end
|
|
16
|
+
case finished_env[:status]
|
|
17
|
+
when 200..299
|
|
18
|
+
SparkApi.logger.debug("[oauth2] Success!")
|
|
19
|
+
session = OAuthSession.new(body)
|
|
20
|
+
else
|
|
21
|
+
# Handle the WWW-Authenticate Response Header Field if present. This can be returned by
|
|
22
|
+
# OAuth2 implementations and wouldn't hurt to log.
|
|
23
|
+
auth_header_error = finished_env[:request_headers]["WWW-Authenticate"]
|
|
24
|
+
SparkApi.logger.warn("Authentication error #{auth_header_error}") unless auth_header_error.nil?
|
|
25
|
+
raise ClientError, {:message => body["error"], :code =>0, :status => finished_env[:status]}
|
|
26
|
+
end
|
|
27
|
+
SparkApi.logger.debug("[oauth2] Session=#{session.inspect}")
|
|
28
|
+
finished_env[:body] = session
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def initialize(app)
|
|
32
|
+
super(app)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
|
|
2
|
+
module FlexmlsApi
|
|
3
|
+
|
|
4
|
+
module Authentication
|
|
5
|
+
|
|
6
|
+
module OAuth2Impl
|
|
7
|
+
|
|
8
|
+
#==OAuth2 Faraday response middleware
|
|
9
|
+
# HTTP Response after filter to package oauth2 responses and bubble up basic api errors.
|
|
10
|
+
class Middleware < Faraday::Response::ParseJson
|
|
11
|
+
def on_complete(finished_env)
|
|
12
|
+
body = parse(finished_env[:body])
|
|
13
|
+
FlexmlsApi.logger.debug("[oauth2] Response Body: #{body.inspect}")
|
|
14
|
+
unless body.is_a?(Hash)
|
|
15
|
+
raise InvalidResponse, "The server response could not be understood"
|
|
16
|
+
end
|
|
17
|
+
case finished_env[:status]
|
|
18
|
+
when 200..299
|
|
19
|
+
FlexmlsApi.logger.debug("[oauth2] Success!")
|
|
20
|
+
session = OAuthSession.new(body)
|
|
21
|
+
else
|
|
22
|
+
# Handle the WWW-Authenticate Response Header Field if present. This can be returned by
|
|
23
|
+
# OAuth2 implementations and wouldn't hurt to log.
|
|
24
|
+
auth_header_error = finished_env[:request_headers]["WWW-Authenticate"]
|
|
25
|
+
FlexmlsApi.logger.warn("Authentication error #{auth_header_error}") unless auth_header_error.nil?
|
|
26
|
+
raise ClientError, {:message => body["error"], :code =>0, :status => finished_env[:status]}
|
|
27
|
+
end
|
|
28
|
+
FlexmlsApi.logger.debug("[oauth2] Session=#{session.inspect}")
|
|
29
|
+
finished_env[:body] = session
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def initialize(app)
|
|
33
|
+
super(app)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module SparkApi
|
|
2
|
+
module Authentication
|
|
3
|
+
module OAuth2Impl
|
|
4
|
+
class PasswordProvider < SparkApi::Authentication::BaseOAuth2Provider
|
|
5
|
+
def initialize(credentials)
|
|
6
|
+
super(credentials)
|
|
7
|
+
@grant_type = :password
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def load_session()
|
|
11
|
+
@session
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def save_session(session)
|
|
15
|
+
@session = session
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def destroy_session
|
|
19
|
+
@session = nil
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
module FlexmlsApi
|
|
3
|
+
module Authentication
|
|
4
|
+
module OAuth2Impl
|
|
5
|
+
class PasswordProvider < FlexmlsApi::Authentication::BaseOAuth2Provider
|
|
6
|
+
def initialize(credentials)
|
|
7
|
+
super(credentials)
|
|
8
|
+
@grant_type = :password
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def load_session()
|
|
12
|
+
@session
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def save_session(session)
|
|
16
|
+
@session = session
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def destroy_session
|
|
20
|
+
@session = nil
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
require 'optparse'
|
|
2
|
+
|
|
3
|
+
if ENV["SPARK_API_CONSOLE"].nil?
|
|
4
|
+
require 'spark_api'
|
|
5
|
+
else
|
|
6
|
+
puts "Enabling console mode for local gem"
|
|
7
|
+
Bundler.require(:default, "development") if defined?(Bundler)
|
|
8
|
+
path = File.expand_path(File.dirname(__FILE__) + "/../../../lib/")
|
|
9
|
+
$LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
|
|
10
|
+
require path + '/spark_api'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module SparkApi
|
|
14
|
+
module CLI
|
|
15
|
+
class ConsoleCLI
|
|
16
|
+
OPTIONS_ENV = {
|
|
17
|
+
:endpoint => "API_ENDPOINT",
|
|
18
|
+
# OAUTH2 Options
|
|
19
|
+
:access_uri => "ACCESS_URI",
|
|
20
|
+
:username=> "USERNAME",
|
|
21
|
+
:password=> "PASSWORD",
|
|
22
|
+
:client_id=> "CLIENT_ID",
|
|
23
|
+
:client_secret=> "CLIENT_SECRET",
|
|
24
|
+
# API AUTH Options
|
|
25
|
+
:api_key => "API_KEY",
|
|
26
|
+
:api_secret => "API_SECRET",
|
|
27
|
+
:api_user => "API_USER",
|
|
28
|
+
# OTHER
|
|
29
|
+
:debug=> "DEBUG",
|
|
30
|
+
:console => "SPARK_API_CONSOLE" # not a public option, meant to distinguish bin/spark_api and script/console
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
def self.execute(stdout, arguments=[])
|
|
34
|
+
options = setup_options(stdout,arguments)
|
|
35
|
+
libs = " -r irb/completion"
|
|
36
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
|
37
|
+
libs << (options[:oauth2] ? setup_oauth2 : setup_api_auth)
|
|
38
|
+
|
|
39
|
+
bundler = (options[:console] ? "bundle exec" : "")
|
|
40
|
+
cmd = "#{export_env(options)} #{bundler} #{irb} #{libs} --simple-prompt"
|
|
41
|
+
puts "Loading spark_api gem..."
|
|
42
|
+
exec "#{cmd}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.irb()
|
|
46
|
+
RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
def self.setup_options(stdout,arguments)
|
|
51
|
+
env_options = {
|
|
52
|
+
:oauth2 => false,
|
|
53
|
+
:endpoint => ENV[OPTIONS_ENV[:endpoint]],
|
|
54
|
+
# OAUTH2 Options
|
|
55
|
+
:access_uri => ENV[OPTIONS_ENV[:access_uri]],
|
|
56
|
+
:username=> ENV[OPTIONS_ENV[:username]],
|
|
57
|
+
:password=> ENV[OPTIONS_ENV[:password]],
|
|
58
|
+
:client_id=> ENV[OPTIONS_ENV[:client_id]],
|
|
59
|
+
:client_secret=> ENV[OPTIONS_ENV[:client_secret]],
|
|
60
|
+
# API AUTH Options
|
|
61
|
+
:api_key => ENV[OPTIONS_ENV[:api_key]],
|
|
62
|
+
:api_secret => ENV[OPTIONS_ENV[:api_secret]],
|
|
63
|
+
:api_user => ENV[OPTIONS_ENV[:api_user]],
|
|
64
|
+
:console => ENV[OPTIONS_ENV[:console]]
|
|
65
|
+
}
|
|
66
|
+
cli_options = {}
|
|
67
|
+
file_options = {}
|
|
68
|
+
parser = OptionParser.new do |opts|
|
|
69
|
+
opts.banner = <<-BANNER.gsub(/^ /,'')
|
|
70
|
+
#{version}
|
|
71
|
+
SparkApi Client Console - http://sparkplatform.com/docs/overview/api
|
|
72
|
+
|
|
73
|
+
Usage: #{File.basename($0)} [options]
|
|
74
|
+
|
|
75
|
+
Environment Variables: some options (as indicated below), will default to values of keys set in the environment.
|
|
76
|
+
|
|
77
|
+
Options are:
|
|
78
|
+
BANNER
|
|
79
|
+
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
|
+
opts.on("-e","--endpoint ENDPOINT",
|
|
85
|
+
"URI of the API.",
|
|
86
|
+
"Default: ENV['#{OPTIONS_ENV[:endpoint]}']") { |arg| cli_options[:endpoint] = arg }
|
|
87
|
+
|
|
88
|
+
# OAUTH2
|
|
89
|
+
opts.on("--client_id CLIENT_ID",
|
|
90
|
+
"OAuth2 client id",
|
|
91
|
+
"Default: ENV['#{OPTIONS_ENV[:client_id]}']") { |arg| cli_options[:client_id] = arg }
|
|
92
|
+
opts.on("--client_secret CLIENT_SECRET",
|
|
93
|
+
"OAuth2 client secret",
|
|
94
|
+
"Default: ENV['#{OPTIONS_ENV[:client_secret]}']") { |arg| cli_options[:client_secret] = arg }
|
|
95
|
+
opts.on("-u","--username USERNAME",
|
|
96
|
+
"OAuth2 username",
|
|
97
|
+
"Default: ENV['#{OPTIONS_ENV[:username]}']") { |arg| cli_options[:username] = arg }
|
|
98
|
+
opts.on("-p","--password PASSWORD",
|
|
99
|
+
"OAuth2 password",
|
|
100
|
+
"Default: ENV['#{OPTIONS_ENV[:password]}']") { |arg| cli_options[:password] = arg }
|
|
101
|
+
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
|
+
|
|
105
|
+
# API AUTH
|
|
106
|
+
opts.on("--api_key API_KEY",
|
|
107
|
+
"Authentication key for running the api using the default api authentication",
|
|
108
|
+
"Default: ENV['#{OPTIONS_ENV[:api_key]}']") { |arg| cli_options[:api_key] = arg }
|
|
109
|
+
opts.on("--api_secret API_SECRET",
|
|
110
|
+
"API secret for the api key",
|
|
111
|
+
"Default: ENV['#{OPTIONS_ENV[:api_secret]}']") { |arg| cli_options[:api_secret] = arg }
|
|
112
|
+
opts.on("--api_user API_USER",
|
|
113
|
+
"ID of the Spark user to run the client as.",
|
|
114
|
+
"Default: ENV['#{OPTIONS_ENV[:api_user]}']") { |arg| cli_options[:api_user] = arg }
|
|
115
|
+
|
|
116
|
+
opts.on("-f", "--file FILE",
|
|
117
|
+
"Load configuration for yaml file.") { |arg| file_options = parse_file_options(arg) }
|
|
118
|
+
opts.on("-d", "--debug",
|
|
119
|
+
"Show detailed request logging information.") { |arg| cli_options[:debug] = arg }
|
|
120
|
+
opts.on("-v", "--version",
|
|
121
|
+
"Show client version.") { stdout.puts version; exit }
|
|
122
|
+
opts.on("-h", "--help",
|
|
123
|
+
"Show this help message.") { stdout.puts opts; exit }
|
|
124
|
+
opts.parse!(arguments)
|
|
125
|
+
|
|
126
|
+
end
|
|
127
|
+
options = env_options.merge(file_options.merge(cli_options))
|
|
128
|
+
return options
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def self.setup_api_auth
|
|
132
|
+
" -r #{File.dirname(__FILE__) + '/../../lib/spark_api/cli/api_auth.rb'}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def self.setup_oauth2
|
|
136
|
+
" -r #{File.dirname(__FILE__) + '/../../lib/spark_api/cli/oauth2.rb'}"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def self.export_env(options)
|
|
140
|
+
run_env = ""
|
|
141
|
+
OPTIONS_ENV.each do |k,v|
|
|
142
|
+
run_env << " #{v}=\"#{options[k]}\"" unless options[k].nil?
|
|
143
|
+
end
|
|
144
|
+
run_env
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
private
|
|
148
|
+
def self.parse_file_options(file)
|
|
149
|
+
yaml = SparkApi::Configuration::YamlConfig.new(file)
|
|
150
|
+
return {:oauth2 => yaml.oauth2}.merge(yaml.client_keys.merge(yaml.oauth2_keys))
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def self.version
|
|
154
|
+
"SparkApi v#{SparkApi::VERSION}"
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|