omnicontacts 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +39 -0
- data/README.md +83 -0
- data/Rakefile +6 -0
- data/lib/omnicontacts.rb +12 -0
- data/lib/omnicontacts/authorization/oauth1.rb +122 -0
- data/lib/omnicontacts/authorization/oauth2.rb +84 -0
- data/lib/omnicontacts/builder.rb +30 -0
- data/lib/omnicontacts/http_utils.rb +88 -0
- data/lib/omnicontacts/importer.rb +9 -0
- data/lib/omnicontacts/importer/gmail.rb +54 -0
- data/lib/omnicontacts/importer/hotmail.rb +46 -0
- data/lib/omnicontacts/importer/yahoo.rb +64 -0
- data/lib/omnicontacts/middleware/base_oauth.rb +97 -0
- data/lib/omnicontacts/middleware/oauth1.rb +68 -0
- data/lib/omnicontacts/middleware/oauth2.rb +66 -0
- data/omnicontacts.gemspec +25 -0
- data/spec/omnicontacts/authorization/oauth1_spec.rb +82 -0
- data/spec/omnicontacts/authorization/oauth2_spec.rb +92 -0
- data/spec/omnicontacts/http_utils_spec.rb +68 -0
- data/spec/omnicontacts/importer/gmail_spec.rb +40 -0
- data/spec/omnicontacts/importer/hotmail_spec.rb +47 -0
- data/spec/omnicontacts/importer/yahoo_spec.rb +42 -0
- data/spec/omnicontacts/middleware/oauth1_spec.rb +71 -0
- data/spec/omnicontacts/middleware/oauth2_spec.rb +62 -0
- data/spec/spec_helper.rb +10 -0
- metadata +139 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
require "omnicontacts/middleware/oauth2"
|
2
|
+
require "rexml/document"
|
3
|
+
|
4
|
+
module OmniContacts
|
5
|
+
module Importer
|
6
|
+
class Gmail < Middleware::OAuth2
|
7
|
+
|
8
|
+
attr_reader :auth_host, :authorize_path, :auth_token_path, :scope
|
9
|
+
|
10
|
+
def initialize *args
|
11
|
+
super *args
|
12
|
+
@auth_host = "accounts.google.com"
|
13
|
+
@authorize_path = "/o/oauth2/auth"
|
14
|
+
@auth_token_path = "/o/oauth2/token"
|
15
|
+
@scope = "https://www.google.com/m8/feeds"
|
16
|
+
@contacts_host = "www.google.com"
|
17
|
+
@contacts_path = "/m8/feeds/contacts/default/full"
|
18
|
+
end
|
19
|
+
|
20
|
+
def fetch_contacts_using_access_token access_token, token_type
|
21
|
+
contacts_response = https_get(@contacts_host, @contacts_path, contacts_req_params, contacts_req_headers(access_token, token_type))
|
22
|
+
parse_contacts contacts_response
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def contacts_req_params
|
28
|
+
{ "max-results" => "100"}
|
29
|
+
end
|
30
|
+
|
31
|
+
def contacts_req_headers token, token_type
|
32
|
+
{"GData-Version" => "3.0", "Authorization" => "#{token_type} #{token}"}
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_contacts contacts_as_xml
|
36
|
+
xml = REXML::Document.new(contacts_as_xml)
|
37
|
+
contacts = []
|
38
|
+
xml.elements.each('//entry') do |entry|
|
39
|
+
gd_email = entry.elements['gd:email']
|
40
|
+
if gd_email
|
41
|
+
contact = {:email => gd_email.attributes['address']}
|
42
|
+
gd_name = entry.elements['gd:name']
|
43
|
+
if gd_name
|
44
|
+
contact[:name] = gd_name.elements['gd:fullName'].text
|
45
|
+
end
|
46
|
+
contacts << contact
|
47
|
+
end
|
48
|
+
end
|
49
|
+
contacts
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "omnicontacts/middleware/oauth2"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module OmniContacts
|
5
|
+
module Importer
|
6
|
+
class Hotmail < Middleware::OAuth2
|
7
|
+
|
8
|
+
attr_reader :auth_host, :authorize_path, :auth_token_path, :scope
|
9
|
+
|
10
|
+
def initialize *args
|
11
|
+
super *args
|
12
|
+
@auth_host = "oauth.live.com"
|
13
|
+
@authorize_path = "/authorize"
|
14
|
+
@scope = "wl.basic"
|
15
|
+
@auth_token_path = "/token"
|
16
|
+
@contacts_host = "apis.live.net"
|
17
|
+
@contacts_path = "/v5.0/me/contacts"
|
18
|
+
end
|
19
|
+
|
20
|
+
def fetch_contacts_using_access_token access_token, access_token_secret
|
21
|
+
contacts_response = https_get(@contacts_host, @contacts_path, :access_token =>access_token)
|
22
|
+
contacts_from_response contacts_response
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def contacts_from_response contacts_as_json
|
28
|
+
json = JSON.parse(escape_windows_format(contacts_as_json))
|
29
|
+
result = []
|
30
|
+
json["data"].each do |contact|
|
31
|
+
result << {:email => contact["name"]} if valid_email? contact["name"]
|
32
|
+
end
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
def escape_windows_format value
|
37
|
+
value.gsub(/[\r\s]/,'')
|
38
|
+
end
|
39
|
+
|
40
|
+
def valid_email? value
|
41
|
+
/\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/.match(value)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "omnicontacts/middleware/oauth1"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module OmniContacts
|
5
|
+
module Importer
|
6
|
+
class Yahoo < Middleware::OAuth1
|
7
|
+
|
8
|
+
attr_reader :auth_host, :auth_token_path, :auth_path, :access_token_path
|
9
|
+
|
10
|
+
def initialize *args
|
11
|
+
super *args
|
12
|
+
@auth_host = "api.login.yahoo.com"
|
13
|
+
@auth_token_path = "/oauth/v2/get_request_token"
|
14
|
+
@auth_path = "/oauth/v2/request_auth"
|
15
|
+
@access_token_path = "/oauth/v2/get_token"
|
16
|
+
@contacts_host = "social.yahooapis.com"
|
17
|
+
end
|
18
|
+
|
19
|
+
def fetch_contacts_from_token_and_verifier auth_token, auth_token_secret, auth_verifier
|
20
|
+
(access_token, access_token_secret, guid) = fetch_access_token(auth_token, auth_token_secret, auth_verifier, ["xoauth_yahoo_guid"])
|
21
|
+
contacts_path = "/v1/user/#{guid}/contacts"
|
22
|
+
contacts_response = http_get(@contacts_host, contacts_path, contacts_req_params(access_token, access_token_secret, contacts_path) )
|
23
|
+
contacts_from_response contacts_response
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def contacts_req_params access_token, access_token_secret, contacts_path
|
29
|
+
params = {
|
30
|
+
:format => "json",
|
31
|
+
:oauth_consumer_key => consumer_key,
|
32
|
+
:oauth_nonce => encode(random_string),
|
33
|
+
:oauth_signature_method => "HMAC-SHA1",
|
34
|
+
:oauth_timestamp => timestamp,
|
35
|
+
:oauth_token => access_token,
|
36
|
+
:oauth_version => OmniContacts::Authorization::OAuth1::OAUTH_VERSION,
|
37
|
+
:view => "compact"
|
38
|
+
}
|
39
|
+
contacts_url = "http://#{@contacts_host}#{contacts_path}"
|
40
|
+
params["oauth_signature"] = oauth_signature("GET", contacts_url, params, access_token_secret)
|
41
|
+
params
|
42
|
+
end
|
43
|
+
|
44
|
+
def contacts_from_response contacts_as_json
|
45
|
+
json = JSON.parse(contacts_as_json)
|
46
|
+
result = []
|
47
|
+
json["contacts"]["contact"].each do |entry|
|
48
|
+
contact = {}
|
49
|
+
entry["fields"].each do |field|
|
50
|
+
contact[:email] = field["value"] if field["type"] == "email"
|
51
|
+
if field["type"] == "name"
|
52
|
+
name = field["value"]["givenName"]
|
53
|
+
surname = field["value"]["familyName"]
|
54
|
+
contact[:name] = "#{name} #{surname}" if name && surname
|
55
|
+
end
|
56
|
+
end
|
57
|
+
result << contact if contact[:email]
|
58
|
+
end
|
59
|
+
result
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# This class contains the common behavior for middlewares
|
2
|
+
# implementing either versions of OAuth.
|
3
|
+
#
|
4
|
+
# Extending classes are required to implement
|
5
|
+
# the following methods:
|
6
|
+
# * request_authorization_from_user
|
7
|
+
# * fetch_contatcs
|
8
|
+
module OmniContacts
|
9
|
+
module Middleware
|
10
|
+
class BaseOAuth
|
11
|
+
|
12
|
+
attr_reader :ssl_ca_file
|
13
|
+
|
14
|
+
def initialize app, options
|
15
|
+
@app = app
|
16
|
+
@listening_path = "/contacts/" + class_name
|
17
|
+
@ssl_ca_file = options[:ssl_ca_file]
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def class_name
|
23
|
+
self.class.name.split('::').last.downcase
|
24
|
+
end
|
25
|
+
|
26
|
+
public
|
27
|
+
|
28
|
+
# Rack callback. It handles three cases:
|
29
|
+
# * user visit middleware entru point.
|
30
|
+
# In this case request_authorization_from_user is called
|
31
|
+
# * user is redirected back to the application
|
32
|
+
# from the authorization site. In this case the list
|
33
|
+
# of contacts is fetched and stored in the variables
|
34
|
+
# omnicontacts.contacts within the Rack env variable.
|
35
|
+
# Once that is done the next middleware component is called.
|
36
|
+
# * user visits any other resource. In this case the request
|
37
|
+
# is simply forwarded to the next middleware component.
|
38
|
+
def call env
|
39
|
+
@env = env
|
40
|
+
if env["PATH_INFO"] =~ /^#{@listening_path}\/?$/
|
41
|
+
handle_initial_request
|
42
|
+
elsif env["PATH_INFO"] =~ /^#{redirect_path}/
|
43
|
+
handle_callback
|
44
|
+
else
|
45
|
+
@app.call(env)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def handle_initial_request
|
52
|
+
execute_and_rescue_exceptions do
|
53
|
+
request_authorization_from_user
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def handle_callback
|
58
|
+
execute_and_rescue_exceptions do
|
59
|
+
@env["omnicontacts.contacts"] = fetch_contacts
|
60
|
+
@app.call(@env)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# This method rescues executes a block of code and
|
65
|
+
# rescue all exceptions. In case of an exception the
|
66
|
+
# user is redirected to the failure endpoint.
|
67
|
+
def execute_and_rescue_exceptions
|
68
|
+
yield
|
69
|
+
rescue AuthorizationError => e
|
70
|
+
handle_error :not_authorized, e
|
71
|
+
rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e
|
72
|
+
handle_error :timeout, e
|
73
|
+
rescue ::RuntimeError => e
|
74
|
+
handle_error :internal_error, e
|
75
|
+
end
|
76
|
+
|
77
|
+
def handle_error error_type, exception
|
78
|
+
logger << ("Error #{error_type} while processing #{@env["PATH_INFO"]}: #{exception.message}") if logger
|
79
|
+
[302, {"location" => "/contacts/failure?error_message=#{error_type}"}, []]
|
80
|
+
end
|
81
|
+
|
82
|
+
def session
|
83
|
+
raise "You must provide a session to use OmniContacts" unless @env["rack.session"]
|
84
|
+
@env["rack.session"]
|
85
|
+
end
|
86
|
+
|
87
|
+
def logger
|
88
|
+
@env["rack.errors"] if @env
|
89
|
+
end
|
90
|
+
|
91
|
+
def base_prop_name
|
92
|
+
"omnicontacts." + class_name
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "omnicontacts/authorization/oauth1"
|
2
|
+
require "omnicontacts/middleware/base_oauth"
|
3
|
+
|
4
|
+
# This class is an OAuth 1.0 Rack middleware.
|
5
|
+
#
|
6
|
+
# Extending classes are required to
|
7
|
+
# implement the following methods:
|
8
|
+
# * fetch_token_from_token_and_verifier -> this method has to
|
9
|
+
# fetch the list of contacts from the authorization server.
|
10
|
+
module OmniContacts
|
11
|
+
module Middleware
|
12
|
+
class OAuth1 < BaseOAuth
|
13
|
+
include Authorization::OAuth1
|
14
|
+
|
15
|
+
attr_reader :consumer_key, :consumer_secret, :callback_path
|
16
|
+
|
17
|
+
def initialize app, consumer_key, consumer_secret, options = {}
|
18
|
+
super app, options
|
19
|
+
@consumer_key = consumer_key
|
20
|
+
@consumer_secret = consumer_secret
|
21
|
+
@callback_path = options[:callback_path] ||= "/contacts/#{class_name}/callback"
|
22
|
+
@token_prop_name = "#{base_prop_name}.oauth_token"
|
23
|
+
end
|
24
|
+
|
25
|
+
def callback
|
26
|
+
host_url_from_rack_env(@env) + callback_path
|
27
|
+
end
|
28
|
+
|
29
|
+
alias :redirect_path :callback_path
|
30
|
+
|
31
|
+
# Obtains an authorization token from the server,
|
32
|
+
# stores it and the session and redirect the user
|
33
|
+
# to the authorization website.
|
34
|
+
def request_authorization_from_user
|
35
|
+
(auth_token, auth_token_secret) = fetch_authorization_token
|
36
|
+
session[@token_prop_name] = auth_token
|
37
|
+
session[token_secret_prop_name(auth_token)] = auth_token_secret
|
38
|
+
redirect_to_authorization_site(auth_token)
|
39
|
+
end
|
40
|
+
|
41
|
+
def token_secret_prop_name oauth_token
|
42
|
+
"#{base_prop_name}.#{oauth_token}.oauth_token_secret"
|
43
|
+
end
|
44
|
+
|
45
|
+
def redirect_to_authorization_site auth_token
|
46
|
+
[302, {"location" => authorization_url(auth_token)}, []]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Parses the authorization token from the query string and
|
50
|
+
# obtain the relative secret from the session.
|
51
|
+
# Finally it calls fetch_contacts_from_token_and_verifier.
|
52
|
+
# If token is found in the query string an AuhorizationError
|
53
|
+
# is raised.
|
54
|
+
def fetch_contacts
|
55
|
+
params = query_string_to_map(@env["QUERY_STRING"])
|
56
|
+
oauth_token = params["oauth_token"]
|
57
|
+
oauth_verifier = params["oauth_verifier"]
|
58
|
+
oauth_token_secret = session[token_secret_prop_name(oauth_token)]
|
59
|
+
if oauth_token && oauth_verifier && oauth_token_secret
|
60
|
+
fetch_contacts_from_token_and_verifier(oauth_token, oauth_token_secret, oauth_verifier)
|
61
|
+
else
|
62
|
+
raise AuthorizationError.new("User did not grant access to contacts list")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "omnicontacts/authorization/oauth2"
|
2
|
+
require "omnicontacts/middleware/base_oauth"
|
3
|
+
|
4
|
+
# This class is a OAuth 2 Rack middleware.
|
5
|
+
#
|
6
|
+
# Extending class are required to implement
|
7
|
+
# the following methods:
|
8
|
+
# * fetch_contacts_using_access_token -> it
|
9
|
+
# fetches the list of contacts from the authorization
|
10
|
+
# server.
|
11
|
+
module OmniContacts
|
12
|
+
module Middleware
|
13
|
+
class OAuth2 < BaseOAuth
|
14
|
+
include Authorization::OAuth2
|
15
|
+
|
16
|
+
attr_reader :client_id, :client_secret, :redirect_path
|
17
|
+
|
18
|
+
def initialize app, client_id, client_secret, options ={}
|
19
|
+
super app, options
|
20
|
+
@client_id = client_id
|
21
|
+
@client_secret = client_secret
|
22
|
+
@redirect_path = options[:redirect_path] ||= "/contacts/#{class_name}/callback"
|
23
|
+
@ssl_ca_file = options[:ssl_ca_file]
|
24
|
+
end
|
25
|
+
|
26
|
+
def request_authorization_from_user
|
27
|
+
[302, {"location" => authorization_url}, []]
|
28
|
+
end
|
29
|
+
|
30
|
+
def redirect_uri
|
31
|
+
host_url_from_rack_env(@env) + redirect_path
|
32
|
+
end
|
33
|
+
|
34
|
+
# It extract the authorization code from the query string.
|
35
|
+
# It uses it to obtain an access token.
|
36
|
+
# If the authorization code has a refresh token associated
|
37
|
+
# with it in the session, it uses the obtain an access token.
|
38
|
+
# It fetches the list of contacts and stores the refresh token
|
39
|
+
# associated with the access token in the session.
|
40
|
+
# Finally it returns the list of contacts.
|
41
|
+
# If no authorization code is found in the query string an
|
42
|
+
# AuthoriazationError is raised.
|
43
|
+
def fetch_contacts
|
44
|
+
code = query_string_to_map(@env["QUERY_STRING"])["code"]
|
45
|
+
if code
|
46
|
+
refresh_token = session[refresh_token_prop_name(code)]
|
47
|
+
(access_token, token_type, refresh_token) = if refresh_token
|
48
|
+
refresh_access_token(refresh_token)
|
49
|
+
else
|
50
|
+
fetch_access_token(code)
|
51
|
+
end
|
52
|
+
contacts = fetch_contacts_using_access_token(access_token, token_type)
|
53
|
+
session[refresh_token_prop_name(code)] = refresh_token if refresh_token
|
54
|
+
contacts
|
55
|
+
else
|
56
|
+
raise AuthorizationError.new("User did not grant access to contacts list")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def refresh_token_prop_name code
|
61
|
+
"#{base_prop_name}.#{code}.refresh_token"
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path('../lib/omnicontacts', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = 'omnicontacts'
|
6
|
+
gem.description = %q{A generalized Rack middleware for importing contacts from major email providers.}
|
7
|
+
gem.authors = ['Diego Castorina']
|
8
|
+
gem.email = ['diegocastorina@gmail.com']
|
9
|
+
|
10
|
+
gem.add_runtime_dependency 'rack'
|
11
|
+
gem.add_runtime_dependency 'json'
|
12
|
+
|
13
|
+
gem.add_development_dependency 'simplecov'
|
14
|
+
gem.add_development_dependency 'rake'
|
15
|
+
gem.add_development_dependency 'rack-test'
|
16
|
+
gem.add_development_dependency 'rspec'
|
17
|
+
|
18
|
+
gem.version = OmniContacts::VERSION
|
19
|
+
gem.files = `git ls-files`.split("\n")
|
20
|
+
gem.homepage = 'http://github.com/Diego81/omnicontacts'
|
21
|
+
gem.require_paths = ['lib']
|
22
|
+
gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if gem.respond_to? :required_rubygems_version=
|
23
|
+
gem.summary = gem.description
|
24
|
+
gem.test_files = `git ls-files -- {spec}/*`.split("\n")
|
25
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "omnicontacts/authorization/oauth1"
|
3
|
+
|
4
|
+
describe OmniContacts::Authorization::OAuth1 do
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
OAuth1TestClass= Struct.new(:consumer_key, :consumer_secret, :auth_host, :auth_token_path, :auth_path, :access_token_path, :callback)
|
8
|
+
class OAuth1TestClass
|
9
|
+
include OmniContacts::Authorization::OAuth1
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:test_target) do
|
14
|
+
OAuth1TestClass.new("consumer_key", "secret1", "auth_host", "auth_token_path", "auth_path", "access_token_path", "callback")
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "fetch_authorization_token" do
|
18
|
+
|
19
|
+
it "should request the token providing all mandatory parameters" do
|
20
|
+
test_target.should_receive(:https_post) do |host, path, params|
|
21
|
+
host.should eq(test_target.auth_host)
|
22
|
+
path.should eq(test_target.auth_token_path)
|
23
|
+
params[:oauth_consumer_key].should eq(test_target.consumer_key)
|
24
|
+
params[:oauth_nonce].should_not be_nil
|
25
|
+
params[:oauth_signature_method].should eq("PLAINTEXT")
|
26
|
+
params[:oauth_signature].should eq(test_target.consumer_secret + "%26")
|
27
|
+
params[:oauth_timestamp].should_not be_nil
|
28
|
+
params[:oauth_version].should eq("1.0")
|
29
|
+
params[:oauth_callback].should eq(test_target.callback)
|
30
|
+
"oauth_token=token&oauth_token_secret=token_secret"
|
31
|
+
end
|
32
|
+
test_target.fetch_authorization_token
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should successfully parse the result" do
|
36
|
+
test_target.should_receive(:https_post).and_return("oauth_token=token&oauth_token_secret=token_secret")
|
37
|
+
test_target.fetch_authorization_token.should eq(["token", "token_secret"])
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should raise an error if request is invalid" do
|
41
|
+
test_target.should_receive(:https_post).and_return("invalid_request")
|
42
|
+
expect{test_target.fetch_authorization_token}.should raise_error
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "authorization_url" do
|
48
|
+
subject{test_target.authorization_url("token")}
|
49
|
+
it{should eq("https://#{test_target.auth_host}#{test_target.auth_path}?oauth_token=token")}
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "fetch_access_token" do
|
53
|
+
it "should request the access token using all required parameters" do
|
54
|
+
auth_token = "token"
|
55
|
+
auth_token_secret = "token_secret"
|
56
|
+
auth_verifier = "verifier"
|
57
|
+
test_target.should_receive(:https_post) do |host, path, params|
|
58
|
+
host.should eq(test_target.auth_host)
|
59
|
+
path.should eq(test_target.access_token_path)
|
60
|
+
params[:oauth_consumer_key].should eq(test_target.consumer_key)
|
61
|
+
params[:oauth_nonce].should_not be_nil
|
62
|
+
params[:oauth_signature_method].should eq("PLAINTEXT")
|
63
|
+
params[:oauth_version].should eq("1.0")
|
64
|
+
params[:oauth_signature].should eq("#{test_target.consumer_secret}%26#{auth_token_secret}")
|
65
|
+
params[:oauth_token].should eq(auth_token)
|
66
|
+
params[:oauth_verifier].should eq(auth_verifier)
|
67
|
+
"oauth_token=access_token&oauth_token_secret=access_token_secret&other_param=other_value"
|
68
|
+
end
|
69
|
+
test_target.fetch_access_token auth_token, auth_token_secret, auth_verifier, ["other_param"]
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should successfully extract access_token and the other fields" do
|
73
|
+
test_target.should_receive(:https_post).and_return("oauth_token=access_token&oauth_token_secret=access_token_secret&other_param=other_value")
|
74
|
+
test_target.fetch_access_token("token","token_scret","verified",["other_param"]).should eq(["access_token", "access_token_secret", "other_value"])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "oauth_signature" do
|
79
|
+
subject{ test_target.oauth_signature("GET", "http://social.yahooapis.com/v1/user", {:name => "diego", :surname => "castorina"}, "secret2")}
|
80
|
+
it{ should eq("ZqWoQISWcuz%2FSDnDxWihtsFDKwc%3D")}
|
81
|
+
end
|
82
|
+
end
|