responsys-api 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +5 -13
  2. data/.travis.yml +7 -2
  3. data/lib/responsys/api/all.rb +2 -2
  4. data/lib/responsys/api/authentication.rb +45 -0
  5. data/lib/responsys/api/client.rb +21 -50
  6. data/lib/responsys/api/session.rb +22 -35
  7. data/lib/responsys/api/session_pool.rb +32 -0
  8. data/lib/responsys/configuration.rb +7 -2
  9. data/lib/responsys/i18n/en.yml +35 -0
  10. data/lib/responsys_api.rb +7 -1
  11. data/responsys-api.gemspec +3 -2
  12. data/spec/api/campaign_spec.rb +5 -5
  13. data/spec/api/client_spec.rb +7 -69
  14. data/spec/api/list_spec.rb +6 -6
  15. data/spec/api/session_spec.rb +50 -0
  16. data/spec/api/table_spec.rb +12 -12
  17. data/spec/api_credentials.sample.yml +1 -1
  18. data/spec/fixtures/vcr_cassettes/api/campaign/trigger_custom_event_1.yml +45 -29
  19. data/spec/fixtures/vcr_cassettes/api/campaign/trigger_custom_event_2.yml +45 -29
  20. data/spec/fixtures/vcr_cassettes/api/campaign/trigger_message_1.yml +926 -29
  21. data/spec/fixtures/vcr_cassettes/api/campaign/trigger_message_2.yml +45 -29
  22. data/spec/fixtures/vcr_cassettes/api/client/expired_session.yml +1 -48
  23. data/spec/fixtures/vcr_cassettes/api/list/merge.yml +46 -28
  24. data/spec/fixtures/vcr_cassettes/api/list/retrieve.yml +927 -28
  25. data/spec/fixtures/vcr_cassettes/api/list/retrieve_single.yml +46 -28
  26. data/spec/fixtures/vcr_cassettes/api/list/retrieve_single_single.yml +46 -28
  27. data/spec/fixtures/vcr_cassettes/api/profile_extension/delete_profile_extension_records.yml +65 -0
  28. data/spec/fixtures/vcr_cassettes/api/profile_extension/merge_profile_extension_records.yml +46 -28
  29. data/spec/fixtures/vcr_cassettes/api/profile_extension/retrieve_profile_extension_records.yml +46 -28
  30. data/spec/fixtures/vcr_cassettes/api/table/create_with_pk.yml +927 -28
  31. data/spec/fixtures/vcr_cassettes/api/table/delete_with_pk.yml +46 -28
  32. data/spec/fixtures/vcr_cassettes/member/present1.yml +927 -28
  33. data/spec/fixtures/vcr_cassettes/member/present2.yml +46 -28
  34. data/spec/fixtures/vcr_cassettes/member/present3.yml +46 -30
  35. data/spec/fixtures/vcr_cassettes/member/present4.yml +46 -30
  36. data/spec/fixtures/vcr_cassettes/member/present5.yml +46 -30
  37. data/spec/fixtures/vcr_cassettes/member/retrieve_profile_extension.yml +92 -56
  38. data/spec/spec_helper.rb +9 -19
  39. metadata +43 -23
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MTlmMTI3NDdjZmE5MjYwYTllNzRiMTU3OTE1ZDc4OGQ2N2EwZTNhNQ==
5
- data.tar.gz: !binary |-
6
- ZjU1YjUxYWUxMWE0Yzg0NTk0YWRmYTAyNDYxMjI3YmQ1YzNiMzYyNA==
2
+ SHA1:
3
+ metadata.gz: 6f00d1395d9bcceca1e501060dda3682ba6c9efe
4
+ data.tar.gz: e7f470e8a49e3bdacc06696ae5eeab07f20686f6
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MjAwMmE5OWU3YzRhMjliZjNhZmQ2ODNkNGE3ZWEzOWY4NjAxYmJmMWU5YjE0
10
- ZDk1M2MwOTlmZjQyYWRmYTM5ODVkZDQwMzA1MjNmMTkyYWQ2NzJmZTc2NWFl
11
- NjdiNTlmMDNlMDMzY2M1YmVlNzYwNTJlZDNjNTEyZjg3NWE0OGE=
12
- data.tar.gz: !binary |-
13
- NTJlNjI3MDZkOWNhMWI2MDNjNTk3ZDAxMGQ3MWM1ZTdiODM5NGU3ODRjNGI3
14
- NmY5MGIxNjE2ZWZkMTc0MDZiOTQ5MzdhZTgzNDMyZWRjMGJhNGM0ZTNkN2Mx
15
- YmM2NjY1NTlhOWRhM2Y0NWY5MjkwYTgzZjBjODU1ZWRjNzdlZjU=
6
+ metadata.gz: 217b1ad9d39b0a44392e7b5ffbbbca9ed27e6d39ff776fae6a55fdd29d3d04b6bfdbe800ede0c767eecaeddd232418b5857bf37eb89caae4f902ce0a7fc25b02
7
+ data.tar.gz: 2a7fd19395a831029fb5e11b39194d560ba62514a0b26bb07b01a308bc5a87765e2fecd027cb14100130fa57af0b72eaf389a3801c4ae6fdb7e88a33464a5444
@@ -2,6 +2,11 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.1.2
5
-
6
5
  gemfile:
7
- - Gemfile
6
+ - Gemfile
7
+ notifications:
8
+ email:
9
+ on_success: never
10
+ on_failure: never
11
+ slack:
12
+ secure: 8b8dwwpHEw7vYd5Vma/BK2dZBrKYpFtu8TN8+NtpW8Xp+boYY3hEaFCeeEySzDvacCBZFKjjvDxverOFd4jqml2MtOukNZ/zlFc7ZVybGsNirfisNucS7auvwoWPwVrzrHoNpB5nTLU4tm0tWdaKkfLa4Yssr/tEO8yBIGwT8ds=
@@ -1,15 +1,15 @@
1
+ require "responsys/api/authentication"
1
2
  require "responsys/api/folder"
2
3
  require "responsys/api/list"
3
- require "responsys/api/session"
4
4
  require "responsys/api/table"
5
5
  require "responsys/api/campaign"
6
6
 
7
7
  module Responsys
8
8
  module Api
9
9
  module All
10
+ include Responsys::Api::Authentication
10
11
  include Responsys::Api::Folder
11
12
  include Responsys::Api::List
12
- include Responsys::Api::Session
13
13
  include Responsys::Api::Table
14
14
  include Responsys::Api::Campaign
15
15
  end
@@ -0,0 +1,45 @@
1
+ module Responsys
2
+ module Api
3
+ module Authentication
4
+ def login
5
+ logout if logged_in?
6
+
7
+ response = run(:login, credentials)
8
+ establish_session_id(response)
9
+ establish_jsession_id(response)
10
+ set_session_credentials
11
+ end
12
+
13
+ def logout
14
+ return unless logged_in?
15
+
16
+ run_with_credentials(:logout, nil)
17
+ destroy_session_objects
18
+ end
19
+
20
+ def logged_in?
21
+ !(session_id.nil? || jsession_id.nil? || header.nil?)
22
+ end
23
+
24
+ private
25
+
26
+ def establish_session_id(login_response)
27
+ @session_id = login_response.body[:login_response][:result][:session_id]
28
+ end
29
+
30
+ def establish_jsession_id(login_response)
31
+ @jsession_id = login_response.http.cookies[0]
32
+ end
33
+
34
+ def set_session_credentials
35
+ @header = { SessionHeader: { sessionId: session_id } }
36
+ end
37
+
38
+ def destroy_session_objects
39
+ @session_id = nil
40
+ @jsession_id = nil
41
+ @header = nil
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,68 +1,39 @@
1
- require "responsys/configuration"
2
- require "savon"
3
- require "responsys/helper"
4
- require "responsys/api/all"
5
- require "responsys/api/object/all"
6
- require "singleton"
7
-
8
1
  module Responsys
9
2
  module Api
10
3
  class Client
11
- include Singleton
12
4
  include Responsys::Api::All
5
+ attr_accessor :client
13
6
 
14
- attr_accessor :credentials, :client, :session_id, :jsession_id, :header
15
-
16
- def initialize
17
- settings = Responsys.configuration.settings
18
- @credentials = {
19
- username: settings[:username],
20
- password: settings[:password]
21
- }
22
-
23
- ssl_version = settings[:ssl_version] || :TLSv1
24
-
25
- if settings[:debug]
26
- @client = Savon.client(wsdl: settings[:wsdl], element_form_default: :qualified, ssl_version: ssl_version, log_level: :debug, log: true, pretty_print_xml: true)
27
- else
28
- @client = Savon.client(wsdl: settings[:wsdl], element_form_default: :qualified, ssl_version: ssl_version)
29
- end
7
+ #TODO allows to keep the use of .instance. The client is no longer a singleton so it needs to be removed in a newer release.
8
+ class << self
9
+ alias :instance :new
30
10
  end
31
11
 
32
12
  def api_method(action, message = nil, response_type = :hash)
33
13
  raise Responsys::Helper.get_message("api.client.api_method.wrong_action_#{action.to_s}") if action.to_sym == :login || action.to_sym == :logout
34
14
 
35
- begin
36
- login
37
-
38
- response = run_with_credentials(action, message, jsession_id, header)
39
-
40
- case response_type
41
- when :result
42
- Responsys::Helper.format_response_result(response, action)
43
- when :hash
44
- Responsys::Helper.format_response_hash(response, action)
15
+ SessionPool.instance.with do |session|
16
+ begin
17
+ session.login
18
+ response = session.run_with_credentials(action, message)
19
+ case response_type
20
+ when :result
21
+ Responsys::Helper.format_response_result(response, action)
22
+ when :hash
23
+ Responsys::Helper.format_response_hash(response, action)
24
+ end
25
+ rescue Exception => e
26
+ Responsys::Helper.format_response_with_errors(e)
27
+ ensure
28
+ session.logout
45
29
  end
46
-
47
- rescue Exception => e
48
- Responsys::Helper.format_response_with_errors(e)
49
- ensure
50
- logout
51
30
  end
52
31
  end
53
32
 
54
33
  def available_operations
55
- @client.operations
56
- end
57
-
58
- private
59
-
60
- def run(method, message)
61
- @client.call(method.to_sym, message: message)
62
- end
63
-
64
- def run_with_credentials(method, message, cookie, header)
65
- @client.call(method.to_sym, message: message, cookies: cookie, soap_header: header)
34
+ SessionPool.instance.with do |session|
35
+ session.operations
36
+ end
66
37
  end
67
38
  end
68
39
  end
@@ -1,44 +1,31 @@
1
1
  module Responsys
2
2
  module Api
3
- module Session
4
- def login
5
- logout if logged_in?
6
-
7
- response = run("login", credentials)
8
- establish_session_id(response)
9
- establish_jsession_id(response)
10
- set_session_credentials
11
- end
12
-
13
- def logout
14
- return unless logged_in?
15
-
16
- run_with_credentials(:logout, nil, jsession_id, header)
17
- destroy_session_objects
18
- end
19
-
20
- def logged_in?
21
- !(session_id.nil? || jsession_id.nil? || header.nil?)
22
- end
23
-
24
- private
25
-
26
- def establish_session_id(login_response)
27
- @session_id = login_response.body[:login_response][:result][:session_id]
28
- end
29
-
30
- def establish_jsession_id(login_response)
31
- @jsession_id = login_response.http.cookies[0]
3
+ class Session
4
+ attr_accessor :credentials, :session_id, :jsession_id, :header
5
+ include Responsys::Api::Authentication
6
+
7
+ def initialize
8
+ settings = Responsys.configuration.settings
9
+ @credentials = {
10
+ username: settings[:username],
11
+ password: settings[:password]
12
+ }
13
+
14
+ ssl_version = settings[:ssl_version] || :TLSv1
15
+
16
+ if settings[:debug]
17
+ @savon_client = Savon.client(wsdl: settings[:wsdl], element_form_default: :qualified, ssl_version: ssl_version, log_level: :debug, log: true, pretty_print_xml: true)
18
+ else
19
+ @savon_client = Savon.client(wsdl: settings[:wsdl], element_form_default: :qualified, ssl_version: ssl_version)
20
+ end
32
21
  end
33
22
 
34
- def set_session_credentials
35
- @header = { SessionHeader: { sessionId: session_id } }
23
+ def run(method, message)
24
+ @savon_client.call(method.to_sym, message: message)
36
25
  end
37
26
 
38
- def destroy_session_objects
39
- @session_id = nil
40
- @jsession_id = nil
41
- @header = nil
27
+ def run_with_credentials(method, message)
28
+ @savon_client.call(method.to_sym, message: message, cookies: jsession_id, soap_header: header)
42
29
  end
43
30
  end
44
31
  end
@@ -0,0 +1,32 @@
1
+ require "singleton"
2
+
3
+ module Responsys
4
+ module Api
5
+ class SessionPool
6
+ include Singleton
7
+ attr_accessor :pool
8
+ ACCEPTED_SETTINGS = [:timeout, :size]
9
+
10
+ class << self
11
+ alias :init :instance
12
+ end
13
+
14
+ def initialize
15
+ settings = Responsys.configuration.settings[:sessions]
16
+ params = if settings
17
+ settings.select { |option, value| ACCEPTED_SETTINGS.include?(option) }
18
+ else
19
+ {}
20
+ end
21
+
22
+ @pool = ConnectionPool.new(params) { Responsys::Api::Session.new }
23
+ end
24
+
25
+ def with
26
+ @pool.with do |session|
27
+ yield session
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -7,7 +7,11 @@ module Responsys
7
7
  username: nil,
8
8
  password: nil,
9
9
  wsdl: "",
10
- debug: false
10
+ debug: false,
11
+ sessions: {
12
+ size: 80,
13
+ timeout: 30
14
+ }
11
15
  }
12
16
  end
13
17
  end
@@ -22,5 +26,6 @@ module Responsys
22
26
 
23
27
  def self.configure
24
28
  yield(configuration)
29
+ Responsys::Api::SessionPool.init
25
30
  end
26
- end
31
+ end
@@ -18,6 +18,41 @@ en:
18
18
  empty_event: The event_name or event_id must be specified
19
19
  incorrect_event_object: "custom_event must be a CustomEvent instance"
20
20
  client:
21
+ available_methods:
22
+ - wsdl
23
+ - endpoint
24
+ - namespace
25
+ - raise_errors
26
+ - proxy
27
+ - headers
28
+ - open_timeout
29
+ - read_timeout
30
+ - ssl_verify_mode
31
+ - ssl_version
32
+ - ssl_cert_file
33
+ - ssl_cert_key_file
34
+ - ssl_ca_cert_file
35
+ - ssl_cert_key_password
36
+ - convert_request_keys_to
37
+ - soap_header
38
+ - element_form_default
39
+ - env_namespace
40
+ - namespace_identifier
41
+ - namespaces
42
+ - encoding
43
+ - soap_version
44
+ - basic_auth
45
+ - digest_auth
46
+ - wsse_auth
47
+ - wsse_timestamp
48
+ - ntlm
49
+ - strip_namespaces
50
+ - convert_response_tags_to
51
+ - logger
52
+ - log_level
53
+ - log
54
+ - filters
55
+ - pretty_print_xml
21
56
  api_method:
22
57
  wrong_action_login: Please use the dedicated login method
23
58
  wrong_action_logout: Please use the dedicated logout method
@@ -1,9 +1,15 @@
1
1
  require "i18n"
2
+ require "connection_pool"
3
+ require "savon"
2
4
 
3
5
  I18n.load_path.concat Dir.glob( File.dirname(__FILE__) + "/responsys/i18n/*.yml" )
4
6
 
5
7
  require "responsys/exceptions/all"
6
8
  require "responsys/helper"
7
9
  require "responsys/configuration"
10
+ require "responsys/api/all"
11
+ require "responsys/api/object/all"
12
+ require "responsys/api/session_pool"
13
+ require "responsys/api/session"
8
14
  require "responsys/api/client"
9
- require "responsys/member"
15
+ require "responsys/member"
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "responsys-api"
7
- spec.version = "0.1.0"
7
+ spec.version = "0.2.1"
8
8
  spec.authors = ["Dan DeMeyere", "Florian Lorrain", "Morgan Griggs", "Mike Rocco"]
9
9
  spec.email = ["dan@thredup.com", "florian.lorrain@thredup.com", "morgan@thredup.com", "michael.rocco@thredup.com"]
10
10
  spec.description = "A gem to integrate with the Responsys SOAP API"
@@ -21,9 +21,10 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency "savon", "2.6.0"
22
22
  spec.add_dependency "wasabi", "3.3.0"
23
23
  spec.add_dependency "i18n", "~> 0.6"
24
+ spec.add_dependency "connection_pool", "2.0.0"
24
25
  spec.add_development_dependency "bundler", "~> 1.3"
25
26
  spec.add_development_dependency "rake", "~> 10.3"
26
- spec.add_development_dependency "rspec", "~> 3.0"
27
+ spec.add_development_dependency "rspec", "~> 3.1.0"
27
28
  spec.add_development_dependency "vcr", "~> 2.5"
28
29
  spec.add_development_dependency "webmock", "~> 1.9"
29
30
  end
@@ -11,20 +11,20 @@ describe Responsys::Api::Campaign do
11
11
  let(:custom_event) { Responsys::Api::Object::CustomEvent.new(DATA[:custom_events][:custom_event1][:name]) }
12
12
 
13
13
  before(:all) do
14
- @client = Responsys::Api::Client.instance
14
+ @client = Responsys::Api::Client.new
15
15
  end
16
16
 
17
17
  context "Trigger Message" do
18
18
  it "should return a status of ok when triggering a message for one recipient" do
19
19
  VCR.use_cassette("api/campaign/trigger_message_1") do
20
- response = Responsys::Api::Client.instance.trigger_message(campaign, [recipientData1])
20
+ response = Responsys::Api::Client.new.trigger_message(campaign, [recipientData1])
21
21
  expect(response[:status]).to eq("ok")
22
22
  end
23
23
  end
24
24
 
25
25
  it "should return a status of ok when triggering a message for more than one recipient" do
26
26
  VCR.use_cassette("api/campaign/trigger_message_2") do
27
- response = Responsys::Api::Client.instance.trigger_message(campaign, [recipientData1,recipientData2])
27
+ response = Responsys::Api::Client.new.trigger_message(campaign, [recipientData1,recipientData2])
28
28
  expect(response[:status]).to eq("ok")
29
29
  end
30
30
  end
@@ -43,14 +43,14 @@ describe Responsys::Api::Campaign do
43
43
  context "#trigger_custom_event" do
44
44
  it "should return a status of ok when triggering a custom event for one recipient" do
45
45
  VCR.use_cassette("api/campaign/trigger_custom_event_1") do
46
- response = Responsys::Api::Client.instance.trigger_custom_event(custom_event, [recipientData1])
46
+ response = Responsys::Api::Client.new.trigger_custom_event(custom_event, [recipientData1])
47
47
  expect(response[:status]).to eq("ok")
48
48
  end
49
49
  end
50
50
 
51
51
  it "should return a status of ok when triggering a custom event for more than one recipient" do
52
52
  VCR.use_cassette("api/campaign/trigger_custom_event_2") do
53
- response = Responsys::Api::Client.instance.trigger_custom_event(custom_event, [recipientData1,recipientData2])
53
+ response = Responsys::Api::Client.new.trigger_custom_event(custom_event, [recipientData1,recipientData2])
54
54
  expect(response[:status]).to eq("ok")
55
55
  end
56
56
  end
@@ -1,77 +1,15 @@
1
1
  require "spec_helper.rb"
2
- require "responsys/api/client"
3
- require "singleton"
4
2
 
5
3
  describe Responsys::Api::Client do
6
4
 
7
- context "Authentication" do
8
- subject { Responsys::Api::Client.instance }
9
- let(:savon_client) { double("savon client") }
10
-
11
- before(:context) do
12
- @credentials = { username: CREDENTIALS["username"], password: CREDENTIALS["password"] }
13
- end
14
-
15
- after(:context) do
16
- Singleton.__init__(Responsys::Api::Client)
17
- end
18
-
19
- it "should set the credentials" do
20
- allow_any_instance_of(Responsys::Api::Client).to receive(:login).and_return(nil)
21
-
22
- responsys = Responsys::Api::Client.instance
23
-
24
- expect(responsys.credentials).to eq({ username: CREDENTIALS["username"], password: CREDENTIALS["password"] })
25
- end
26
-
27
- context "login" do
28
- before(:example) do
29
- response = double("response")
30
-
31
- cookies = %w(fake_jsession_id)
32
- body = {
33
- login_response: {
34
- result: {
35
- session_id: "fake_session_id"
36
- }
37
- }
38
- }
39
-
40
- allow(response).to receive(:body).and_return(body)
41
- allow(response).to receive(:http).and_return(double("cookies", cookies: cookies))
42
-
43
- allow(Savon).to receive(:client).with({ wsdl: CREDENTIALS["wsdl"], element_form_default: :qualified, ssl_version: :TLSv1}).and_return(savon_client) #Avoid the verification of the wsdl
44
- allow_any_instance_of(Responsys::Api::Client).to receive(:run).with("login", @credentials).and_return(response) #Verification of credentials
45
- allow(savon_client).to receive(:call).with(:login, @credentials ).and_return(response) #Actual login call
46
-
47
- Singleton.__init__(Responsys::Api::Client)
48
- end
49
-
50
- it "should set the session ids" do
51
- subject.login
52
-
53
- expect(subject.header).to eq({ SessionHeader: { sessionId: "fake_session_id" } }) #Test the ids are right
54
- expect(subject.jsession_id).to eq("fake_jsession_id")
55
- end
56
-
57
- it "should refuse the access to api_method for login" do
58
- expect{ subject.api_method(:login) }.to raise_error("Please use the dedicated login method")
59
- end
5
+ describe "Authentication methods" do
6
+ it "should refuse the access to api_method for logout" do
7
+ expect{ subject.api_method(:logout) }.to raise_error("Please use the dedicated logout method")
60
8
  end
61
9
 
62
- context "logout" do
63
- subject { Responsys::Api::Client.instance }
64
-
65
- it "should logout" do
66
- allow(subject).to receive(:logged_in?).and_return(true)
67
- expect(subject).to receive(:run_with_credentials).with(:logout, anything, anything, anything) #Check the call is actually being done
68
-
69
- subject.logout
70
- end
71
-
72
- it "should refuse the access to api_method for logout" do
73
- expect{ subject.api_method(:logout) }.to raise_error("Please use the dedicated logout method")
74
- end
10
+ it "should refuse the access to api_method for login" do
11
+ expect{ subject.api_method(:login) }.to raise_error("Please use the dedicated login method")
75
12
  end
76
13
  end
77
- end
14
+
15
+ end