omnicontacts 0.1.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/.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
|