icontact-api 0.2 → 0.3.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/Gemfile +7 -0
- data/History.txt +1 -5
- data/{README.txt → README.rdoc} +3 -1
- data/Rakefile +13 -25
- data/VERSION +1 -0
- data/lib/icontact-api.rb +1 -1
- data/lib/icontact/api.rb +11 -9
- data/spec/api_spec.rb +52 -28
- metadata +61 -58
- data.tar.gz.sig +0 -0
- data/Manifest.txt +0 -13
- metadata.gz.sig +0 -0
data/Gemfile
ADDED
data/History.txt
CHANGED
data/{README.txt → README.rdoc}
RENAMED
@@ -39,11 +39,13 @@ class BetaApi < Icontact::Api
|
|
39
39
|
API_USERNAME='username'
|
40
40
|
API_PASSWORD='password'
|
41
41
|
API_KEY = 'YOUR_API_KEY'
|
42
|
+
API_SECRET = 'YOUR_API_SECRET'
|
42
43
|
DOMAIN = "http://app.beta.icontact.com/icp"
|
43
44
|
|
44
45
|
def initialize(username = BetaApi::API_USERNAME, password = BetaApi::API_PASSWORD)
|
45
46
|
super(username, password)
|
46
|
-
self.
|
47
|
+
self.key = API_KEY
|
48
|
+
self.secret = API_SECRET
|
47
49
|
self.domain = DOMAIN
|
48
50
|
end
|
49
51
|
end
|
data/Rakefile
CHANGED
@@ -1,29 +1,17 @@
|
|
1
|
-
%w[rubygems rake rake/clean
|
1
|
+
%w[rubygems rake rake/clean].each { |f| require f }
|
2
2
|
require File.dirname(__FILE__) + '/lib/icontact-api'
|
3
|
-
require 'hoe'
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
]
|
18
|
-
|
19
|
-
p.clean_globs |= %w[**/.DS_Store tmp *.log]
|
20
|
-
path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
|
21
|
-
p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
|
22
|
-
p.rsync_args = '-av --delete --ignore-errors'
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "icontact-api"
|
8
|
+
gem.summary = %Q{A thin wrapper around the iContact API}
|
9
|
+
gem.authors = ["Kevin Olbrich"]
|
10
|
+
gem.email = ["kevin.olbrich+icontact-api@gmail.com"]
|
11
|
+
gem.homepage = "http://github.com/olbrich/IContact-API"
|
12
|
+
end
|
13
|
+
Jeweler::GemcutterTasks.new
|
14
|
+
rescue LoadError
|
15
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
23
16
|
end
|
24
17
|
|
25
|
-
require 'newgem/tasks' # load /tasks/*.rake
|
26
|
-
Dir['tasks/**/*.rake'].each { |t| load t }
|
27
|
-
|
28
|
-
# TODO - want other tests/tasks run by default? Add them to the list
|
29
|
-
# task :default => [:spec, :features]
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.0
|
data/lib/icontact-api.rb
CHANGED
data/lib/icontact/api.rb
CHANGED
@@ -1,24 +1,25 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'net/http'
|
3
2
|
require 'net/https'
|
4
3
|
require 'json'
|
5
4
|
|
6
5
|
class Icontact
|
7
6
|
class Api
|
8
|
-
VERSION = "0.
|
9
|
-
API_VERSION = "2.
|
10
|
-
|
7
|
+
VERSION = "0.3"
|
8
|
+
API_VERSION = "2.2"
|
9
|
+
URL = 'https://app.icontact.com/icp'
|
11
10
|
API_KEY = "API_KEY"
|
12
11
|
attr_accessor :username
|
13
12
|
attr_accessor :password
|
14
13
|
attr_accessor :app_id
|
15
|
-
attr_accessor :
|
14
|
+
attr_accessor :url
|
15
|
+
attr_accessor :api_version
|
16
16
|
|
17
|
-
def initialize(username, password)
|
17
|
+
def initialize(username=nil, password=nil)
|
18
18
|
self.username = username
|
19
19
|
self.password = password
|
20
|
-
self.
|
20
|
+
self.url = URL
|
21
21
|
self.app_id = API_KEY
|
22
|
+
self.api_version = API_VERSION
|
22
23
|
end
|
23
24
|
|
24
25
|
# Package up any options into a query string and format it properly for the server
|
@@ -54,7 +55,7 @@ class Icontact
|
|
54
55
|
# data exchange. Also accepts text/xml for either, but then you have to deal with XML encoding and decoding
|
55
56
|
# manually
|
56
57
|
def apply_headers(req)
|
57
|
-
req.add_field('API-Version',
|
58
|
+
req.add_field('API-Version', self.api_version)
|
58
59
|
req.add_field('accept','application/json')
|
59
60
|
req.add_field('Content-Type','application/json')
|
60
61
|
req.add_field('API-Appid', self.app_id)
|
@@ -82,7 +83,7 @@ class Icontact
|
|
82
83
|
# options passed as optional parameter show up as an array
|
83
84
|
options = options.first if options.kind_of? Array
|
84
85
|
query_options = self.class.package_query_params(options)
|
85
|
-
full_url = URI.parse("#{self.
|
86
|
+
full_url = URI.parse("#{self.url}#{url}#{query_options}")
|
86
87
|
|
87
88
|
# create an object of the class required to process this method
|
88
89
|
klass = Object.module_eval("::Net::HTTP::#{kind.to_s.capitalize}", __FILE__, __LINE__)
|
@@ -93,6 +94,7 @@ class Icontact
|
|
93
94
|
|
94
95
|
http = Net::HTTP.new(full_url.host, full_url.port)
|
95
96
|
http.use_ssl = true
|
97
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
96
98
|
response = http.start do |web|
|
97
99
|
web.request(request)
|
98
100
|
end
|
data/spec/api_spec.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
2
|
|
3
3
|
describe Icontact::Api do
|
4
|
+
before(:each) do
|
5
|
+
@mock_time = mock('Time', :getgm => 999999)
|
6
|
+
Time.stub!(:now).and_return(@mock_time)
|
7
|
+
Kernel.stub!(:rand).and_return(111)
|
8
|
+
end
|
9
|
+
|
4
10
|
describe "api" do
|
5
11
|
before(:each) do
|
6
12
|
@api = Icontact::Api.new('mock_username', 'mock_password')
|
7
13
|
@response = mock('response',:code=>200, :body=>"body")
|
8
|
-
|
9
|
-
|
10
|
-
Net::HTTP.stub!(:new).and_return(@mock_http_session)
|
14
|
+
@mock_http_request = mock('http', :request=>@response)
|
15
|
+
Net::HTTP.stub!(:start).and_yield(@mock_http_request)
|
11
16
|
end
|
12
17
|
|
13
|
-
describe "an
|
18
|
+
describe "an http request", :shared=>true do
|
14
19
|
it "should apply headers to the request" do
|
15
20
|
@mock_request = mock("Request", :body= => true)
|
16
21
|
@api.should_receive(:apply_headers).and_return(@mock_request)
|
@@ -22,13 +27,8 @@ describe Icontact::Api do
|
|
22
27
|
do_request(:limit=>10)
|
23
28
|
end
|
24
29
|
|
25
|
-
it "should use ssl" do
|
26
|
-
@mock_http_session.should_receive(:use_ssl=).with(true)
|
27
|
-
do_request
|
28
|
-
end
|
29
|
-
|
30
30
|
it "should send the request" do
|
31
|
-
|
31
|
+
Net::HTTP.should_receive(:start)
|
32
32
|
do_request
|
33
33
|
end
|
34
34
|
|
@@ -38,8 +38,8 @@ describe Icontact::Api do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
describe "an
|
42
|
-
it_should_behave_like "an
|
41
|
+
describe "an http request with a body", :shared=>true do
|
42
|
+
it_should_behave_like "an http request"
|
43
43
|
|
44
44
|
it "should package the data into the body" do
|
45
45
|
@api.class.should_receive(:body_encoder)
|
@@ -53,7 +53,7 @@ describe Icontact::Api do
|
|
53
53
|
@api.get("/a", options)
|
54
54
|
end
|
55
55
|
|
56
|
-
it_should_behave_like "an
|
56
|
+
it_should_behave_like "an http request"
|
57
57
|
end
|
58
58
|
|
59
59
|
describe ".post" do
|
@@ -61,7 +61,7 @@ describe Icontact::Api do
|
|
61
61
|
@api.post("/a", {}, options)
|
62
62
|
end
|
63
63
|
|
64
|
-
it_should_behave_like "an
|
64
|
+
it_should_behave_like "an http request with a body"
|
65
65
|
end
|
66
66
|
|
67
67
|
describe ".put" do
|
@@ -69,7 +69,7 @@ describe Icontact::Api do
|
|
69
69
|
@api.put("/a", {}, options)
|
70
70
|
end
|
71
71
|
|
72
|
-
it_should_behave_like "an
|
72
|
+
it_should_behave_like "an http request with a body"
|
73
73
|
end
|
74
74
|
|
75
75
|
describe '.delete' do
|
@@ -77,10 +77,25 @@ describe Icontact::Api do
|
|
77
77
|
@api.delete("/a", options)
|
78
78
|
end
|
79
79
|
|
80
|
-
it_should_behave_like "an
|
80
|
+
it_should_behave_like "an http request"
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
+
describe ".request_signature" do
|
85
|
+
before(:each) do
|
86
|
+
@api = Icontact::Api.new('username','password')
|
87
|
+
Kernel.stub!(:rand).and_return(111)
|
88
|
+
@mock_time = mock('Time', :getgm => 999999)
|
89
|
+
Time.stub!(:now).and_return(@mock_time)
|
90
|
+
Digest::SHA1.stub!(:hexdigest).and_return('api_signature')
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should generate an API Signature" do
|
94
|
+
Digest::SHA1.should_receive(:hexdigest).with('API_SECRETpasswordtimestamp/urlrandomGET').and_return('api_signature')
|
95
|
+
@api.request_signature('get','timestamp''/url', 'random', '').should == "api_signature"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
84
99
|
describe ".apply_headers" do
|
85
100
|
before(:each) do
|
86
101
|
@request = mock('Request', :add_field=>true)
|
@@ -88,16 +103,16 @@ describe Icontact::Api do
|
|
88
103
|
end
|
89
104
|
|
90
105
|
def do_apply_headers
|
91
|
-
@api.apply_headers(@request)
|
106
|
+
@api.apply_headers(:get, @request, 'http://fakeurl.com')
|
92
107
|
end
|
93
108
|
|
94
|
-
it "should add an
|
95
|
-
@request.should_receive(:add_field).with('
|
109
|
+
it "should add an API_VERSION header to indicate we are using the 2.0 version of the API" do
|
110
|
+
@request.should_receive(:add_field).with('API_VERSION', @api.class::API_VERSION)
|
96
111
|
do_apply_headers
|
97
112
|
end
|
98
113
|
|
99
114
|
it "should add an ACCEPT header indicating we want a JSON object back" do
|
100
|
-
@request.should_receive(:add_field).with('
|
115
|
+
@request.should_receive(:add_field).with('ACCEPT', 'application/json')
|
101
116
|
do_apply_headers
|
102
117
|
end
|
103
118
|
|
@@ -106,22 +121,31 @@ describe Icontact::Api do
|
|
106
121
|
do_apply_headers
|
107
122
|
end
|
108
123
|
|
109
|
-
it "should add an
|
110
|
-
@request.should_receive(:add_field).with('
|
124
|
+
it "should add an API_KEY header to verify that our application is authrorized to use the API" do
|
125
|
+
@request.should_receive(:add_field).with('API_KEY', @api.class::API_KEY)
|
111
126
|
do_apply_headers
|
112
127
|
end
|
113
128
|
|
114
|
-
it "should add an
|
115
|
-
@request.should_receive(:add_field).with('
|
129
|
+
it "should add an API_USERNAME header to verify that our user is authorized to use the API" do
|
130
|
+
@request.should_receive(:add_field).with('API_USERNAME', 'username')
|
116
131
|
do_apply_headers
|
117
132
|
end
|
118
|
-
|
119
|
-
it "should add an
|
120
|
-
@request.should_receive(:add_field).with('
|
133
|
+
|
134
|
+
it "should add an API_TIMESTAMP header to prevent old requests from being replayed" do
|
135
|
+
@request.should_receive(:add_field).with('API_TIMESTAMP', 999999)
|
136
|
+
do_apply_headers
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should add an API_NUMBER header" do
|
140
|
+
@request.should_receive(:add_field).with('API_NUMBER', 111)
|
121
141
|
do_apply_headers
|
122
142
|
end
|
123
|
-
|
124
143
|
|
144
|
+
it "should add an API_SIGNATURE header to ensure this api request is valid" do
|
145
|
+
@api.should_receive(:request_signature).and_return('api_signature')
|
146
|
+
@request.should_receive(:add_field).with('API_SIGNATURE', 'api_signature')
|
147
|
+
do_apply_headers
|
148
|
+
end
|
125
149
|
end
|
126
150
|
|
127
151
|
describe "class methods" do
|
metadata
CHANGED
@@ -1,84 +1,81 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: icontact-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 19
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Kevin Olbrich
|
8
14
|
autorequire:
|
9
15
|
bindir: bin
|
10
|
-
cert_chain:
|
11
|
-
- |
|
12
|
-
-----BEGIN CERTIFICATE-----
|
13
|
-
MIIDPDCCAiSgAwIBAgIBADANBgkqhkiG9w0BAQUFADBEMRYwFAYDVQQDDA1rZXZp
|
14
|
-
bi5vbGJyaWNoMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
|
15
|
-
FgNjb20wHhcNMDkwMzA3MTUwMzQ5WhcNMTAwMzA3MTUwMzQ5WjBEMRYwFAYDVQQD
|
16
|
-
DA1rZXZpbi5vbGJyaWNoMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJ
|
17
|
-
k/IsZAEZFgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvza3W
|
18
|
-
J5Dloirbhpge6teyZNfvOzuo478vtqnU/c6S8o2EerBkmWm88J+ipItO3U2HDPgP
|
19
|
-
a7THrx41/QEj1oG15mO6wtBLf0Z+AOJFAmf+Th8x3b46b3Voo1+suON67fCqCz+U
|
20
|
-
L5V2I5NBNywCte5Nzjh7knLkHr+rUCCKAIPK6vq+sASMIgmlhzZUuQfdRZMhRVZP
|
21
|
-
clMwf9sIp7LUTq2b/LCdP2dlGFydb1cyvaHjho+X/pk5uWKcr1OkrZtYFdxyeGU4
|
22
|
-
ZTtqEd5vaNTacYf0vGBfPfiolIfbmOa8Pgfyj8zkjBug/iukM/YGmwL1KAk8Qs+/
|
23
|
-
gInxSkyPxa7zkYTzAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0G
|
24
|
-
A1UdDgQWBBS+y2GRZjETz6d3jHKosqOZ6Ll+zjANBgkqhkiG9w0BAQUFAAOCAQEA
|
25
|
-
f3hCt6NBuESjAN4fkpbcfi3/Nj06aNl6CAfryfKaOaIfLcypT5nqP1qtqqGih5ne
|
26
|
-
QCe7jmtZHOGFC/SSlCS8obHSkCGn2cfUl/InfpF/YQnZV0Kp8esihuVmEjO0SgEU
|
27
|
-
yf46wW9Nh4byKctkgKMlWnIqwAyk4G1dD/le6MGJutb4pv5hT9qm1vaTFkAcy1Qu
|
28
|
-
1VMZa+MH6xnINGdFyV8T7AYL5BaQTbp2WYsfbOvy3ZfxbpP5O3wc3wter/Cyp8pu
|
29
|
-
Wvn0/+13roT+v5T5yFIpu6NbSpuqvRaKZvS+n2ZgwS10rUPFydzn+335umE4vsfH
|
30
|
-
4Umf0rf1f8h+GJia5xXYww==
|
31
|
-
-----END CERTIFICATE-----
|
16
|
+
cert_chain: []
|
32
17
|
|
33
|
-
date:
|
18
|
+
date: 2011-04-27 00:00:00 -04:00
|
34
19
|
default_executable:
|
35
20
|
dependencies:
|
36
21
|
- !ruby/object:Gem::Dependency
|
37
|
-
name: json
|
38
22
|
type: :runtime
|
39
|
-
|
40
|
-
|
23
|
+
prerelease: false
|
24
|
+
name: json
|
25
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
41
27
|
requirements:
|
42
28
|
- - ">="
|
43
29
|
- !ruby/object:Gem::Version
|
44
|
-
|
45
|
-
|
30
|
+
hash: 3
|
31
|
+
segments:
|
32
|
+
- 0
|
33
|
+
version: "0"
|
34
|
+
requirement: *id001
|
46
35
|
- !ruby/object:Gem::Dependency
|
47
|
-
name: newgem
|
48
36
|
type: :development
|
49
|
-
|
50
|
-
|
37
|
+
prerelease: false
|
38
|
+
name: bundler
|
39
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
51
41
|
requirements:
|
52
|
-
- -
|
42
|
+
- - ~>
|
53
43
|
- !ruby/object:Gem::Version
|
54
|
-
|
55
|
-
|
44
|
+
hash: 15
|
45
|
+
segments:
|
46
|
+
- 1
|
47
|
+
- 0
|
48
|
+
version: "1.0"
|
49
|
+
requirement: *id002
|
56
50
|
- !ruby/object:Gem::Dependency
|
57
|
-
name: hoe
|
58
51
|
type: :development
|
59
|
-
|
60
|
-
|
52
|
+
prerelease: false
|
53
|
+
name: jeweler
|
54
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
61
56
|
requirements:
|
62
57
|
- - ">="
|
63
58
|
- !ruby/object:Gem::Version
|
64
|
-
|
65
|
-
|
66
|
-
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
requirement: *id003
|
64
|
+
description:
|
67
65
|
email:
|
68
|
-
- kevin.olbrich@gmail.com
|
66
|
+
- kevin.olbrich+icontact-api@gmail.com
|
69
67
|
executables: []
|
70
68
|
|
71
69
|
extensions: []
|
72
70
|
|
73
71
|
extra_rdoc_files:
|
74
|
-
-
|
75
|
-
- Manifest.txt
|
76
|
-
- README.txt
|
72
|
+
- README.rdoc
|
77
73
|
files:
|
74
|
+
- Gemfile
|
78
75
|
- History.txt
|
79
|
-
-
|
80
|
-
- README.txt
|
76
|
+
- README.rdoc
|
81
77
|
- Rakefile
|
78
|
+
- VERSION
|
82
79
|
- lib/icontact-api.rb
|
83
80
|
- lib/icontact/api.rb
|
84
81
|
- script/console
|
@@ -89,33 +86,39 @@ files:
|
|
89
86
|
- spec/spec_helper.rb
|
90
87
|
- tasks/rspec.rake
|
91
88
|
has_rdoc: true
|
92
|
-
homepage:
|
89
|
+
homepage: http://github.com/olbrich/IContact-API
|
93
90
|
licenses: []
|
94
91
|
|
95
92
|
post_install_message:
|
96
|
-
rdoc_options:
|
97
|
-
|
98
|
-
- README.txt
|
93
|
+
rdoc_options: []
|
94
|
+
|
99
95
|
require_paths:
|
100
96
|
- lib
|
101
97
|
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
102
99
|
requirements:
|
103
100
|
- - ">="
|
104
101
|
- !ruby/object:Gem::Version
|
102
|
+
hash: 3
|
103
|
+
segments:
|
104
|
+
- 0
|
105
105
|
version: "0"
|
106
|
-
version:
|
107
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
108
|
requirements:
|
109
109
|
- - ">="
|
110
110
|
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
112
|
+
segments:
|
113
|
+
- 0
|
111
114
|
version: "0"
|
112
|
-
version:
|
113
115
|
requirements: []
|
114
116
|
|
115
|
-
rubyforge_project:
|
116
|
-
rubygems_version: 1.3.
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 1.3.7
|
117
119
|
signing_key:
|
118
120
|
specification_version: 3
|
119
|
-
summary:
|
120
|
-
test_files:
|
121
|
-
|
121
|
+
summary: A thin wrapper around the iContact API
|
122
|
+
test_files:
|
123
|
+
- spec/api_spec.rb
|
124
|
+
- spec/spec_helper.rb
|
data.tar.gz.sig
DELETED
Binary file
|
data/Manifest.txt
DELETED
metadata.gz.sig
DELETED
Binary file
|