spark_api 1.1.2 → 1.2.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 +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
data/script/oauth2_example.rb
CHANGED
@@ -15,8 +15,8 @@ SparkApi.configure do |config|
|
|
15
15
|
config.api_secret = "YOUR_CLIENT_SECRET"
|
16
16
|
config.callback = "YOUR_REDIRECT_URI"
|
17
17
|
config.version = "v1"
|
18
|
-
config.endpoint = "https://
|
19
|
-
config.auth_endpoint = "https://
|
18
|
+
config.endpoint = "https://sparkapi.com"
|
19
|
+
config.auth_endpoint = "https://sparkplatform.com/oauth2"
|
20
20
|
end
|
21
21
|
|
22
22
|
client = SparkApi.client
|
@@ -25,7 +25,7 @@ client = SparkApi.client
|
|
25
25
|
# Step 1:
|
26
26
|
# To get your code to post to /v1/oauth2/grant, send the end user to this URI, replacing the all-capped strings with
|
27
27
|
# the CGI-escaped credentials for your key:
|
28
|
-
# https://
|
28
|
+
# https://sparkplatform.com/oauth2?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI
|
29
29
|
# When the user has finished, they will land at:
|
30
30
|
# YOUR_REDIRECT_URI?code=CODE.
|
31
31
|
puts "Go here and log in to get your code: #{client.authenticator.authorization_url}"
|
data/spec/fixtures/base.json
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"D": {
|
3
|
+
"Success": true,
|
4
|
+
"Results": [
|
5
|
+
{
|
6
|
+
"Id":"20101230223226074204000000",
|
7
|
+
"ResourceUri":"/v1/contacts/20101230223226074204000000",
|
8
|
+
"Name":"First subscription",
|
9
|
+
"RecipientIds": ["20101230223226074307000000"]
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"Id":"20101230223226074205000000",
|
13
|
+
"ResourceUri":"/v1/contacts/20101230223226074205000000",
|
14
|
+
"Name":"Second subscription",
|
15
|
+
"RecipientIds": []
|
16
|
+
}
|
17
|
+
]
|
18
|
+
}
|
19
|
+
}
|
data/spec/mock_helper.rb
CHANGED
@@ -32,15 +32,19 @@ def stub_api_delete(service_path, stub_fixture="success.json", opts={})
|
|
32
32
|
log_stub(s)
|
33
33
|
end
|
34
34
|
def stub_api_post(service_path, body, stub_fixture="success.json", opts={})
|
35
|
-
|
36
|
-
|
35
|
+
if body.is_a?(Hash)
|
36
|
+
body = { :D => body } unless body.empty?
|
37
|
+
elsif !body.nil?
|
38
|
+
body = MultiJson.load(fixture(body).read)
|
39
|
+
end
|
40
|
+
body_str = body.nil? ? body : MultiJson.dump(body)
|
37
41
|
params = {:ApiUser => "foobar", :AuthToken => "c401736bf3d3f754f07c04e460e09573"}.merge(opts)
|
38
42
|
sig = $test_client.authenticator.sign_token("/#{SparkApi.version}#{service_path}", params, body_str)
|
39
43
|
s=stub_request(:post, "#{SparkApi.endpoint}/#{SparkApi.version}#{service_path}").
|
40
44
|
with(:query => {
|
41
45
|
:ApiSig => sig
|
42
46
|
}.merge(params),
|
43
|
-
:body =>
|
47
|
+
:body => body
|
44
48
|
)
|
45
49
|
if(block_given?)
|
46
50
|
yield s
|
@@ -50,15 +54,19 @@ def stub_api_post(service_path, body, stub_fixture="success.json", opts={})
|
|
50
54
|
log_stub(s)
|
51
55
|
end
|
52
56
|
def stub_api_put(service_path, body, stub_fixture="success.json", opts={})
|
53
|
-
|
54
|
-
|
57
|
+
if body.is_a? Hash
|
58
|
+
body = { :D => body }
|
59
|
+
elsif !body.nil?
|
60
|
+
body = MultiJson.load(fixture(body).read)
|
61
|
+
end
|
62
|
+
body_str = body.nil? ? body : MultiJson.dump(body)
|
55
63
|
params = {:ApiUser => "foobar", :AuthToken => "c401736bf3d3f754f07c04e460e09573"}.merge(opts)
|
56
64
|
sig = $test_client.authenticator.sign_token("/#{SparkApi.version}#{service_path}", params, body_str)
|
57
65
|
s=stub_request(:put, "#{SparkApi.endpoint}/#{SparkApi.version}#{service_path}").
|
58
66
|
with(:query => {
|
59
67
|
:ApiSig => sig
|
60
68
|
}.merge(params),
|
61
|
-
:body =>
|
69
|
+
:body => body
|
62
70
|
)
|
63
71
|
if(block_given?)
|
64
72
|
yield s
|
data/spec/oauth2_helper.rb
CHANGED
@@ -7,6 +7,7 @@ class TestOAuth2Provider < SparkApi::Authentication::BaseOAuth2Provider
|
|
7
7
|
@redirect_uri = "https://exampleapp.fbsdata.com/oauth-callback"
|
8
8
|
@client_id="example-id"
|
9
9
|
@client_secret="example-password"
|
10
|
+
@sparkbar_uri = "https://test.sparkplatform.com/appbar/authorize"
|
10
11
|
@session_cache = {}
|
11
12
|
end
|
12
13
|
|
@@ -56,6 +57,7 @@ class TestCLIOAuth2Provider < SparkApi::Authentication::BaseOAuth2Provider
|
|
56
57
|
nil
|
57
58
|
end
|
58
59
|
def session_timeout; 60; end
|
60
|
+
|
59
61
|
end
|
60
62
|
|
61
63
|
|
data/spec/spec_helper.rb
CHANGED
@@ -31,15 +31,12 @@ end
|
|
31
31
|
|
32
32
|
SparkApi.logger.info("Setup gem for rspec testing")
|
33
33
|
|
34
|
+
include SparkApi::Models
|
35
|
+
|
34
36
|
def reset_config
|
35
37
|
SparkApi.reset
|
36
|
-
SparkApi.configure
|
37
|
-
config.api_user = "foobar"
|
38
|
-
end
|
38
|
+
SparkApi.configure { |c| c.api_user = "foobar" }
|
39
39
|
end
|
40
|
-
reset_config
|
41
|
-
|
42
|
-
include SparkApi::Models
|
43
40
|
|
44
41
|
RSpec.configure do |config|
|
45
42
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
@@ -47,5 +44,5 @@ RSpec.configure do |config|
|
|
47
44
|
config.alias_example_to :on_put_it, :method => 'PUT'
|
48
45
|
config.alias_example_to :on_post_it, :method => 'POST'
|
49
46
|
config.alias_example_to :on_delete_it, :method => 'DELETE'
|
47
|
+
config.before(:all) { reset_config }
|
50
48
|
end
|
51
|
-
|
@@ -140,7 +140,6 @@ describe SparkApi::Authentication::ApiAuth do
|
|
140
140
|
|
141
141
|
context "when the server says the session is expired (even if we disagree)" do
|
142
142
|
it "should reset the session and reauthenticate" do
|
143
|
-
reset_config
|
144
143
|
count = 0
|
145
144
|
# Make sure the auth request goes out twice.
|
146
145
|
stub_request(:post, "https://api.sparkapi.com/#{SparkApi.version}/session").
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
require './spec/oauth2_helper'
|
3
|
+
|
4
|
+
describe SparkApi::Authentication::OAuth2Impl::SparkbarFaradayMiddleware do
|
5
|
+
subject { SparkApi::Authentication::OAuth2Impl::SparkbarFaradayMiddleware.new("test") }
|
6
|
+
# Make sure the client boostraps the right plugin based on configuration.
|
7
|
+
it "should parse token on successful response" do
|
8
|
+
env = {
|
9
|
+
:body => '{"token":"sp4rkb4rt0k3n"}',
|
10
|
+
:status => 201
|
11
|
+
}
|
12
|
+
subject.on_complete env
|
13
|
+
env[:body]["token"].should eq("sp4rkb4rt0k3n")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should raise error on unsuccessful response" do
|
17
|
+
env = {
|
18
|
+
:body => '{"token":"sp4rkb4rt0k3n"}',
|
19
|
+
:status => 500
|
20
|
+
}
|
21
|
+
expect {subject.on_complete env }.to raise_error(SparkApi::ClientError)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should raise error on invalid json" do
|
25
|
+
env = {
|
26
|
+
:body => '{"BORKBORKBORK"}',
|
27
|
+
:status => 200
|
28
|
+
}
|
29
|
+
expect {subject.on_complete env }.to raise_error(MultiJson::DecodeError)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SparkApi::Authentication::SingleSessionProvider do
|
4
|
+
subject { SparkApi::Authentication::SingleSessionProvider.new({ :access_token => "the_token" }) }
|
5
|
+
it "should initialize a new session with access_token" do
|
6
|
+
subject.load_session.should respond_to(:access_token)
|
7
|
+
subject.load_session.access_token.should eq("the_token")
|
8
|
+
end
|
9
|
+
end
|
@@ -2,8 +2,12 @@ require './spec/spec_helper'
|
|
2
2
|
require './spec/oauth2_helper'
|
3
3
|
|
4
4
|
describe SparkApi::Authentication::OAuth2 do
|
5
|
+
before(:all) { SparkApi.reset } # dump api user stuff from other tests
|
5
6
|
let(:provider) { TestOAuth2Provider.new() }
|
6
|
-
let(:client) { SparkApi::Client.new({
|
7
|
+
let(:client) { SparkApi::Client.new({
|
8
|
+
:authentication_mode => SparkApi::Authentication::OAuth2,
|
9
|
+
:oauth2_provider => provider,
|
10
|
+
:sparkbar_uri => "https://test.sparkplatform.com/appbar/authorize"}) }
|
7
11
|
subject {client.authenticator }
|
8
12
|
# Make sure the client boostraps the right plugin based on configuration.
|
9
13
|
describe "plugin" do
|
@@ -50,7 +54,6 @@ describe SparkApi::Authentication::OAuth2 do
|
|
50
54
|
end
|
51
55
|
end
|
52
56
|
|
53
|
-
|
54
57
|
describe "logout" do
|
55
58
|
let(:session) { mock_oauth_session }
|
56
59
|
it "should logout when there is an active session" do
|
@@ -96,6 +99,24 @@ describe SparkApi::Authentication::OAuth2 do
|
|
96
99
|
subject.request(:post, "/#{SparkApi.version}/contacts", contact, args).status.should eq(201)
|
97
100
|
end
|
98
101
|
end
|
102
|
+
|
103
|
+
describe "sparkbar_token" do
|
104
|
+
let(:session) { mock_oauth_session }
|
105
|
+
it "should fetch a sparkbar token" do
|
106
|
+
c = stub_request(:post, "https://test.sparkplatform.com/appbar/authorize").
|
107
|
+
with(:body => "access_token=#{session.access_token}").
|
108
|
+
to_return(:body => '{"token":"sp4rkb4rt0k3n"}')
|
109
|
+
subject.session = session
|
110
|
+
subject.sparkbar_token.should eq("sp4rkb4rt0k3n")
|
111
|
+
end
|
112
|
+
it "should raise an error on missing sparkbar token" do
|
113
|
+
c = stub_request(:post, "https://test.sparkplatform.com/appbar/authorize").
|
114
|
+
with(:body => "access_token=#{session.access_token}").
|
115
|
+
to_return(:body => '{"foo":"bar"}')
|
116
|
+
subject.session = session
|
117
|
+
expect {subject.sparkbar_token }.to raise_error(SparkApi::ClientError)
|
118
|
+
end
|
119
|
+
end
|
99
120
|
|
100
121
|
context "with an expired session" do
|
101
122
|
context "and a valid refresh token" do
|
@@ -246,7 +267,7 @@ describe "password authentication" do
|
|
246
267
|
end
|
247
268
|
describe SparkApi::Authentication::OAuth2Impl do
|
248
269
|
it "should load a provider" do
|
249
|
-
example = "SparkApi::Authentication::OAuth2Impl::
|
270
|
+
example = "SparkApi::Authentication::OAuth2Impl::CLIProvider"
|
250
271
|
SparkApi::Authentication::OAuth2Impl.load_provider(example,{}).class.to_s.should eq(example)
|
251
272
|
prefix = "::#{example}"
|
252
273
|
SparkApi::Authentication::OAuth2Impl.load_provider(prefix,{}).class.to_s.should eq(example)
|
@@ -282,4 +303,9 @@ describe SparkApi::Authentication::OAuthSession do
|
|
282
303
|
session.start_time.should eq(DateTime.parse(args[:start_time]))
|
283
304
|
JSON.parse(session.to_json).should eq(JSON.parse(args.to_json))
|
284
305
|
end
|
306
|
+
|
307
|
+
it "should not expire if expires_in is nil" do
|
308
|
+
session = SparkApi::Authentication::OAuthSession.new
|
309
|
+
session.expired?.should eq(false)
|
310
|
+
end
|
285
311
|
end
|
@@ -1,19 +1,12 @@
|
|
1
1
|
require './spec/spec_helper'
|
2
2
|
|
3
3
|
describe SparkApi::Authentication do
|
4
|
-
before(:all) do
|
5
|
-
SparkApi.reset
|
6
|
-
end
|
7
|
-
|
8
|
-
after(:all) do
|
9
|
-
reset_config
|
10
|
-
end
|
11
|
-
|
12
4
|
it "should give me a session object" do
|
13
5
|
stub_auth_request
|
14
6
|
stub_request(:get, "#{SparkApi.endpoint}/#{SparkApi.version}/session/c401736bf3d3f754f07c04e460e09573").
|
15
7
|
with(:query => {
|
16
|
-
:ApiSig => "
|
8
|
+
:ApiSig => "d4cea51b4a6b9eb930e4320866aae7d0",
|
9
|
+
:ApiUser => "foobar",
|
17
10
|
:AuthToken => "c401736bf3d3f754f07c04e460e09573"
|
18
11
|
}).
|
19
12
|
to_return(:body => fixture("session.json"))
|
@@ -26,7 +19,8 @@ describe SparkApi::Authentication do
|
|
26
19
|
stub_auth_request
|
27
20
|
stub_request(:delete, "#{SparkApi.endpoint}/#{SparkApi.version}/session/c401736bf3d3f754f07c04e460e09573").
|
28
21
|
with(:query => {
|
29
|
-
:ApiSig => "
|
22
|
+
:ApiSig => "d4cea51b4a6b9eb930e4320866aae7d0",
|
23
|
+
:ApiUser => "foobar",
|
30
24
|
:AuthToken => "c401736bf3d3f754f07c04e460e09573"
|
31
25
|
}).
|
32
26
|
to_return(:body => fixture("success.json"))
|
@@ -8,11 +8,12 @@ describe SparkApi::Configuration::YamlConfig, "Yaml Config" do
|
|
8
8
|
subject.api_env.should eq("development")
|
9
9
|
subject.load_file(api_file)
|
10
10
|
subject.oauth2?.should eq(false)
|
11
|
+
subject.ssl_verify?.should eq(false)
|
11
12
|
subject.api_key.should eq("demo_key")
|
12
13
|
subject.api_secret.should eq("t3sts3cr3t")
|
13
14
|
subject.endpoint.should eq("https://developers.sparkapi.com")
|
14
15
|
subject.name.should eq("test_key")
|
15
|
-
subject.client_keys.keys.should =~ [:api_key, :api_secret, :endpoint]
|
16
|
+
subject.client_keys.keys.should =~ [:api_key, :api_secret, :endpoint, :ssl_verify]
|
16
17
|
subject.oauth2_keys.keys.should eq([])
|
17
18
|
end
|
18
19
|
it "should load a configured api key for production" do
|
@@ -47,7 +48,7 @@ describe SparkApi::Configuration::YamlConfig, "Yaml Config" do
|
|
47
48
|
subject.oauth2_provider.should eq("SparkApi::TestOAuth2Provider")
|
48
49
|
subject.name.should eq("test_oauth")
|
49
50
|
subject.client_keys.keys.should =~ [:endpoint, :oauth2_provider]
|
50
|
-
subject.oauth2_keys.keys.should =~ [:authorization_uri, :client_id, :access_uri, :client_secret, :redirect_uri]
|
51
|
+
subject.oauth2_keys.keys.should =~ [:authorization_uri, :client_id, :access_uri, :client_secret, :redirect_uri, :sparkbar_uri]
|
51
52
|
end
|
52
53
|
it "should load a configured api key for production" do
|
53
54
|
subject.stub(:env){ {"SPARK_API_ENV" => "production"} }
|
@@ -66,7 +67,7 @@ describe SparkApi::Configuration::YamlConfig, "Yaml Config" do
|
|
66
67
|
|
67
68
|
it "should list available keys" do
|
68
69
|
SparkApi::Configuration::YamlConfig.stub(:config_path) { "spec/config/spark_api" }
|
69
|
-
subject.class.config_keys.should =~ ["test_key", "test_oauth"]
|
70
|
+
subject.class.config_keys.should =~ ["test_key", "test_oauth", "test_single_session_oauth"]
|
70
71
|
end
|
71
72
|
end
|
72
73
|
end
|