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.
Files changed (257) hide show
  1. data/History.txt +139 -0
  2. data/LICENSE +14 -0
  3. data/README.md +153 -0
  4. data/Rakefile +18 -0
  5. data/VERSION +1 -0
  6. data/bin/spark_api +8 -0
  7. data/bin/spark_api~ +8 -0
  8. data/lib/spark_api.rb +46 -0
  9. data/lib/spark_api/authentication.rb +55 -0
  10. data/lib/spark_api/authentication/api_auth.rb +104 -0
  11. data/lib/spark_api/authentication/api_auth.rb~ +104 -0
  12. data/lib/spark_api/authentication/base_auth.rb +47 -0
  13. data/lib/spark_api/authentication/base_auth.rb~ +47 -0
  14. data/lib/spark_api/authentication/oauth2.rb +198 -0
  15. data/lib/spark_api/authentication/oauth2.rb~ +199 -0
  16. data/lib/spark_api/authentication/oauth2_impl/grant_type_base.rb +87 -0
  17. data/lib/spark_api/authentication/oauth2_impl/grant_type_base.rb~ +87 -0
  18. data/lib/spark_api/authentication/oauth2_impl/grant_type_code.rb +48 -0
  19. data/lib/spark_api/authentication/oauth2_impl/grant_type_code.rb~ +49 -0
  20. data/lib/spark_api/authentication/oauth2_impl/grant_type_password.rb +44 -0
  21. data/lib/spark_api/authentication/oauth2_impl/grant_type_password.rb~ +45 -0
  22. data/lib/spark_api/authentication/oauth2_impl/grant_type_refresh.rb +35 -0
  23. data/lib/spark_api/authentication/oauth2_impl/grant_type_refresh.rb~ +36 -0
  24. data/lib/spark_api/authentication/oauth2_impl/middleware.rb +38 -0
  25. data/lib/spark_api/authentication/oauth2_impl/middleware.rb~ +39 -0
  26. data/lib/spark_api/authentication/oauth2_impl/password_provider.rb +24 -0
  27. data/lib/spark_api/authentication/oauth2_impl/password_provider.rb~ +25 -0
  28. data/lib/spark_api/cli.rb +158 -0
  29. data/lib/spark_api/cli.rb~ +158 -0
  30. data/lib/spark_api/cli/api_auth.rb +8 -0
  31. data/lib/spark_api/cli/api_auth.rb~ +8 -0
  32. data/lib/spark_api/cli/oauth2.rb +14 -0
  33. data/lib/spark_api/cli/oauth2.rb~ +14 -0
  34. data/lib/spark_api/cli/setup.rb +47 -0
  35. data/lib/spark_api/cli/setup.rb~ +47 -0
  36. data/lib/spark_api/client.rb +27 -0
  37. data/lib/spark_api/configuration.rb +54 -0
  38. data/lib/spark_api/configuration.rb~ +54 -0
  39. data/lib/spark_api/configuration/yaml.rb +101 -0
  40. data/lib/spark_api/configuration/yaml.rb~ +101 -0
  41. data/lib/spark_api/connection.rb +42 -0
  42. data/lib/spark_api/faraday.rb +64 -0
  43. data/lib/spark_api/faraday.rb~ +64 -0
  44. data/lib/spark_api/models.rb +33 -0
  45. data/lib/spark_api/models.rb~ +33 -0
  46. data/lib/spark_api/models/account.rb +115 -0
  47. data/lib/spark_api/models/account.rb~ +115 -0
  48. data/lib/spark_api/models/base.rb +118 -0
  49. data/lib/spark_api/models/base.rb~ +118 -0
  50. data/lib/spark_api/models/connect_prefs.rb +10 -0
  51. data/lib/spark_api/models/connect_prefs.rb~ +10 -0
  52. data/lib/spark_api/models/constraint.rb +16 -0
  53. data/lib/spark_api/models/constraint.rb~ +16 -0
  54. data/lib/spark_api/models/contact.rb +49 -0
  55. data/lib/spark_api/models/contact.rb~ +49 -0
  56. data/lib/spark_api/models/custom_fields.rb +12 -0
  57. data/lib/spark_api/models/custom_fields.rb~ +12 -0
  58. data/lib/spark_api/models/document.rb +11 -0
  59. data/lib/spark_api/models/document.rb~ +11 -0
  60. data/lib/spark_api/models/finders.rb +45 -0
  61. data/lib/spark_api/models/finders.rb~ +45 -0
  62. data/lib/spark_api/models/idx_link.rb +47 -0
  63. data/lib/spark_api/models/idx_link.rb~ +47 -0
  64. data/lib/spark_api/models/listing.rb +197 -0
  65. data/lib/spark_api/models/listing.rb~ +197 -0
  66. data/lib/spark_api/models/listing_cart.rb +72 -0
  67. data/lib/spark_api/models/listing_cart.rb~ +72 -0
  68. data/lib/spark_api/models/market_statistics.rb +33 -0
  69. data/lib/spark_api/models/market_statistics.rb~ +33 -0
  70. data/lib/spark_api/models/message.rb +21 -0
  71. data/lib/spark_api/models/message.rb~ +21 -0
  72. data/lib/spark_api/models/note.rb +41 -0
  73. data/lib/spark_api/models/note.rb~ +41 -0
  74. data/lib/spark_api/models/notification.rb +42 -0
  75. data/lib/spark_api/models/notification.rb~ +42 -0
  76. data/lib/spark_api/models/open_house.rb +24 -0
  77. data/lib/spark_api/models/open_house.rb~ +24 -0
  78. data/lib/spark_api/models/photo.rb +70 -0
  79. data/lib/spark_api/models/photo.rb~ +70 -0
  80. data/lib/spark_api/models/property_types.rb +7 -0
  81. data/lib/spark_api/models/property_types.rb~ +7 -0
  82. data/lib/spark_api/models/saved_search.rb +16 -0
  83. data/lib/spark_api/models/saved_search.rb~ +16 -0
  84. data/lib/spark_api/models/shared_listing.rb +35 -0
  85. data/lib/spark_api/models/shared_listing.rb~ +35 -0
  86. data/lib/spark_api/models/standard_fields.rb +50 -0
  87. data/lib/spark_api/models/standard_fields.rb~ +50 -0
  88. data/lib/spark_api/models/subresource.rb +19 -0
  89. data/lib/spark_api/models/subresource.rb~ +19 -0
  90. data/lib/spark_api/models/system_info.rb +14 -0
  91. data/lib/spark_api/models/system_info.rb~ +14 -0
  92. data/lib/spark_api/models/tour_of_home.rb +24 -0
  93. data/lib/spark_api/models/tour_of_home.rb~ +24 -0
  94. data/lib/spark_api/models/video.rb +16 -0
  95. data/lib/spark_api/models/video.rb~ +16 -0
  96. data/lib/spark_api/models/virtual_tour.rb +18 -0
  97. data/lib/spark_api/models/virtual_tour.rb~ +18 -0
  98. data/lib/spark_api/multi_client.rb +59 -0
  99. data/lib/spark_api/multi_client.rb~ +59 -0
  100. data/lib/spark_api/paginate.rb +109 -0
  101. data/lib/spark_api/paginate.rb~ +109 -0
  102. data/lib/spark_api/primary_array.rb +29 -0
  103. data/lib/spark_api/primary_array.rb~ +29 -0
  104. data/lib/spark_api/request.rb +96 -0
  105. data/lib/spark_api/request.rb~ +96 -0
  106. data/lib/spark_api/response.rb +70 -0
  107. data/lib/spark_api/response.rb~ +70 -0
  108. data/lib/spark_api/version.rb +4 -0
  109. data/lib/spark_api/version.rb~ +4 -0
  110. data/script/console +6 -0
  111. data/script/console~ +6 -0
  112. data/script/example.rb +27 -0
  113. data/script/example.rb~ +27 -0
  114. data/spec/fixtures/accounts/all.json +160 -0
  115. data/spec/fixtures/accounts/my.json +74 -0
  116. data/spec/fixtures/accounts/my_portal.json +20 -0
  117. data/spec/fixtures/accounts/my_put.json +5 -0
  118. data/spec/fixtures/accounts/my_save.json +5 -0
  119. data/spec/fixtures/accounts/office.json +142 -0
  120. data/spec/fixtures/accounts/password_save.json +6 -0
  121. data/spec/fixtures/authentication_failure.json +7 -0
  122. data/spec/fixtures/base.json +13 -0
  123. data/spec/fixtures/contacts/contacts.json +28 -0
  124. data/spec/fixtures/contacts/my.json +19 -0
  125. data/spec/fixtures/contacts/new.json +11 -0
  126. data/spec/fixtures/contacts/new_empty.json +8 -0
  127. data/spec/fixtures/contacts/new_notify.json +11 -0
  128. data/spec/fixtures/contacts/post.json +10 -0
  129. data/spec/fixtures/contacts/tags.json +11 -0
  130. data/spec/fixtures/count.json +10 -0
  131. data/spec/fixtures/empty.json +3 -0
  132. data/spec/fixtures/errors/expired.json +7 -0
  133. data/spec/fixtures/errors/failure.json +5 -0
  134. data/spec/fixtures/errors/failure_with_constraint.json +17 -0
  135. data/spec/fixtures/errors/failure_with_msg.json +7 -0
  136. data/spec/fixtures/generic_delete.json +1 -0
  137. data/spec/fixtures/generic_failure.json +5 -0
  138. data/spec/fixtures/listing_carts/add_listing.json +13 -0
  139. data/spec/fixtures/listing_carts/add_listing_post.json +5 -0
  140. data/spec/fixtures/listing_carts/empty.json +5 -0
  141. data/spec/fixtures/listing_carts/listing_cart.json +19 -0
  142. data/spec/fixtures/listing_carts/new.json +12 -0
  143. data/spec/fixtures/listing_carts/post.json +10 -0
  144. data/spec/fixtures/listing_carts/remove_listing.json +13 -0
  145. data/spec/fixtures/listings/constraints.json +18 -0
  146. data/spec/fixtures/listings/constraints_with_pagination.json +24 -0
  147. data/spec/fixtures/listings/document_index.json +19 -0
  148. data/spec/fixtures/listings/multiple.json +69 -0
  149. data/spec/fixtures/listings/no_subresources.json +38 -0
  150. data/spec/fixtures/listings/open_houses.json +21 -0
  151. data/spec/fixtures/listings/photos/index.json +469 -0
  152. data/spec/fixtures/listings/photos/new.json +12 -0
  153. data/spec/fixtures/listings/photos/post.json +20 -0
  154. data/spec/fixtures/listings/put.json +5 -0
  155. data/spec/fixtures/listings/put_expiration_date.json +5 -0
  156. data/spec/fixtures/listings/saved_search.json +17 -0
  157. data/spec/fixtures/listings/shared_listing_get.json +14 -0
  158. data/spec/fixtures/listings/shared_listing_new.json +9 -0
  159. data/spec/fixtures/listings/shared_listing_post.json +10 -0
  160. data/spec/fixtures/listings/tour_of_homes.json +23 -0
  161. data/spec/fixtures/listings/videos_index.json +18 -0
  162. data/spec/fixtures/listings/virtual_tours_index.json +42 -0
  163. data/spec/fixtures/listings/with_documents.json +52 -0
  164. data/spec/fixtures/listings/with_permissions.json +44 -0
  165. data/spec/fixtures/listings/with_photos.json +110 -0
  166. data/spec/fixtures/listings/with_supplement.json +39 -0
  167. data/spec/fixtures/listings/with_videos.json +54 -0
  168. data/spec/fixtures/listings/with_vtour.json +48 -0
  169. data/spec/fixtures/logo_fbs.png +0 -0
  170. data/spec/fixtures/messages/new.json +14 -0
  171. data/spec/fixtures/messages/new_empty.json +7 -0
  172. data/spec/fixtures/messages/new_with_recipients.json +15 -0
  173. data/spec/fixtures/messages/post.json +5 -0
  174. data/spec/fixtures/notes/add.json +11 -0
  175. data/spec/fixtures/notes/agent_shared.json +11 -0
  176. data/spec/fixtures/notes/agent_shared_empty.json +7 -0
  177. data/spec/fixtures/notes/new.json +5 -0
  178. data/spec/fixtures/notifications/mark_read.json +1 -0
  179. data/spec/fixtures/notifications/new.json +8 -0
  180. data/spec/fixtures/notifications/new_empty.json +7 -0
  181. data/spec/fixtures/notifications/notifications.json +43 -0
  182. data/spec/fixtures/notifications/post.json +10 -0
  183. data/spec/fixtures/notifications/unread.json +10 -0
  184. data/spec/fixtures/oauth2/access.json +3 -0
  185. data/spec/fixtures/oauth2/access_with_old_refresh.json +5 -0
  186. data/spec/fixtures/oauth2/access_with_refresh.json +5 -0
  187. data/spec/fixtures/oauth2/authorization_code_body.json +7 -0
  188. data/spec/fixtures/oauth2/error.json +3 -0
  189. data/spec/fixtures/oauth2/password_body.json +7 -0
  190. data/spec/fixtures/oauth2/refresh_body.json +7 -0
  191. data/spec/fixtures/oauth2_error.json +3 -0
  192. data/spec/fixtures/property_types/property_types.json +31 -0
  193. data/spec/fixtures/session.json +10 -0
  194. data/spec/fixtures/standardfields/city.json +1031 -0
  195. data/spec/fixtures/standardfields/nearby.json +53 -0
  196. data/spec/fixtures/standardfields/standardfields.json +188 -0
  197. data/spec/fixtures/standardfields/stateorprovince.json +36 -0
  198. data/spec/fixtures/success.json +5 -0
  199. data/spec/json_helper.rb +76 -0
  200. data/spec/mock_helper.rb +124 -0
  201. data/spec/oauth2_helper.rb +68 -0
  202. data/spec/spec_helper.rb +48 -0
  203. data/spec/unit/flexmls_api_spec.rb~ +23 -0
  204. data/spec/unit/spark_api/authentication/api_auth_spec.rb +169 -0
  205. data/spec/unit/spark_api/authentication/api_auth_spec.rb~ +169 -0
  206. data/spec/unit/spark_api/authentication/base_auth_spec.rb +10 -0
  207. data/spec/unit/spark_api/authentication/base_auth_spec.rb~ +10 -0
  208. data/spec/unit/spark_api/authentication/oauth2_impl/grant_type_base_spec.rb +10 -0
  209. data/spec/unit/spark_api/authentication/oauth2_impl/grant_type_base_spec.rb~ +10 -0
  210. data/spec/unit/spark_api/authentication/oauth2_spec.rb +205 -0
  211. data/spec/unit/spark_api/authentication/oauth2_spec.rb~ +205 -0
  212. data/spec/unit/spark_api/authentication_spec.rb +38 -0
  213. data/spec/unit/spark_api/authentication_spec.rb~ +38 -0
  214. data/spec/unit/spark_api/configuration/yaml_spec.rb +72 -0
  215. data/spec/unit/spark_api/configuration/yaml_spec.rb~ +72 -0
  216. data/spec/unit/spark_api/configuration_spec.rb +122 -0
  217. data/spec/unit/spark_api/configuration_spec.rb~ +122 -0
  218. data/spec/unit/spark_api/faraday_spec.rb +90 -0
  219. data/spec/unit/spark_api/faraday_spec.rb~ +90 -0
  220. data/spec/unit/spark_api/models/account_spec.rb +176 -0
  221. data/spec/unit/spark_api/models/base_spec.rb +106 -0
  222. data/spec/unit/spark_api/models/connect_prefs_spec.rb +9 -0
  223. data/spec/unit/spark_api/models/constraint_spec.rb +19 -0
  224. data/spec/unit/spark_api/models/contact_spec.rb +108 -0
  225. data/spec/unit/spark_api/models/contact_spec.rb~ +108 -0
  226. data/spec/unit/spark_api/models/document_spec.rb +32 -0
  227. data/spec/unit/spark_api/models/listing_cart_spec.rb +127 -0
  228. data/spec/unit/spark_api/models/listing_cart_spec.rb~ +127 -0
  229. data/spec/unit/spark_api/models/listing_spec.rb +320 -0
  230. data/spec/unit/spark_api/models/listing_spec.rb~ +320 -0
  231. data/spec/unit/spark_api/models/message_spec.rb +47 -0
  232. data/spec/unit/spark_api/models/message_spec.rb~ +47 -0
  233. data/spec/unit/spark_api/models/note_spec.rb +63 -0
  234. data/spec/unit/spark_api/models/note_spec.rb~ +63 -0
  235. data/spec/unit/spark_api/models/notification_spec.rb +62 -0
  236. data/spec/unit/spark_api/models/notification_spec.rb~ +62 -0
  237. data/spec/unit/spark_api/models/open_house_spec.rb +39 -0
  238. data/spec/unit/spark_api/models/photo_spec.rb +92 -0
  239. data/spec/unit/spark_api/models/property_types_spec.rb +33 -0
  240. data/spec/unit/spark_api/models/saved_search_spec.rb +40 -0
  241. data/spec/unit/spark_api/models/shared_listing_spec.rb +45 -0
  242. data/spec/unit/spark_api/models/shared_listing_spec.rb~ +45 -0
  243. data/spec/unit/spark_api/models/standard_fields_spec.rb +60 -0
  244. data/spec/unit/spark_api/models/system_info_spec.rb +83 -0
  245. data/spec/unit/spark_api/models/tour_of_home_spec.rb +44 -0
  246. data/spec/unit/spark_api/models/video_spec.rb +36 -0
  247. data/spec/unit/spark_api/models/virtual_tour_spec.rb +44 -0
  248. data/spec/unit/spark_api/multi_client_spec.rb +56 -0
  249. data/spec/unit/spark_api/multi_client_spec.rb~ +56 -0
  250. data/spec/unit/spark_api/paginate_spec.rb +224 -0
  251. data/spec/unit/spark_api/paginate_spec.rb~ +224 -0
  252. data/spec/unit/spark_api/primary_array_spec.rb +41 -0
  253. data/spec/unit/spark_api/primary_array_spec.rb~ +41 -0
  254. data/spec/unit/spark_api/request_spec.rb +344 -0
  255. data/spec/unit/spark_api/request_spec.rb~ +344 -0
  256. data/spec/unit/spark_api_spec.rb +23 -0
  257. 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