Permalink
Browse files

Let you exchange a session_key for an access_token

  • Loading branch information...
1 parent 7466dab commit 65c9b703c368d243a0a4cbafbff2bfee27746765 Kristján Pétursson committed with mmangino May 29, 2010
Showing with 138 additions and 76 deletions.
  1. +17 −4 lib/mogli/authenticator.rb
  2. +32 −25 lib/mogli/client.rb
  3. +37 −9 spec/authenticator_spec.rb
  4. +52 −38 spec/client_spec.rb
View
@@ -1,22 +1,35 @@
require "cgi"
+require 'mogli/client'
+
module Mogli
class Authenticator
attr_reader :client_id, :secret, :callback_url
-
+
def initialize(client_id,secret,callback_url)
@client_id = client_id
@secret = secret
@callback_url = callback_url
end
-
+
def authorize_url(options = {})
options_part = "&" + options.map {|k,v| "#{k}=#{v.kind_of?(Array) ? v.join(',') : v}" }.join('&') unless options.empty?
"https://graph.facebook.com/oauth/authorize?client_id=#{client_id}&redirect_uri=#{CGI.escape(callback_url)}#{options_part}"
end
-
+
def access_token_url(code)
"https://graph.facebook.com/oauth/access_token?client_id=#{client_id}&redirect_uri=#{CGI.escape(callback_url)}&client_secret=#{secret}&code=#{CGI.escape(code)}"
end
-
+
+ def get_access_token_for_session_key(session_keys)
+ keystr = session_keys.is_a?(Array) ?
+ session_keys.join(',') : session_keys
+ client = Mogli::Client.new
+ client.post("oauth/exchange_sessions", nil,
+ {:type => 'client_cred',
+ :client_id => client_id,
+ :client_secret => secret,
+ :sessions => keystr})
+ end
+
end
end
View
@@ -6,28 +6,28 @@ class Client
attr_reader :access_token
attr_reader :default_params
attr_reader :expiration
-
+
include HTTParty
include Mogli::Client::Event
- include Mogli::Client::User
+ include Mogli::Client::User
class UnrecognizeableClassError < Exception; end
-
+
def api_path(path)
"https://graph.facebook.com/#{path}"
end
-
+
def initialize(access_token = nil,expiration=nil)
@access_token = access_token
# nil expiration means extended access
expiration = Time.now.to_i + 10*365*24*60*60 if expiration.nil? or expiration == 0
@expiration = Time.at(expiration)
@default_params = @access_token ? {:access_token=>access_token} : {}
end
-
+
def expired?
expiration and expiration < Time.now
end
-
+
def self.create_from_code_and_authenticator(code,authenticator)
post_data = get(authenticator.access_token_url(code))
parts = post_data.split("&")
@@ -37,42 +37,49 @@ def self.create_from_code_and_authenticator(code,authenticator)
end
new(hash["access_token"],hash["expires"].to_s.to_i)
end
-
+
+ def self.create_from_session_key(session_key, client_id, secret)
+ authenticator = Mogli::Authenticator.new(client_id, secret, nil)
+ access_data = authenticator.get_access_token_for_session_key(session_key)
+ new(access_data['access_token'],
+ Time.now.to_i + access_data['expires'].to_i)
+ end
+
def post(path,klass,body_args)
- data = self.class.post(api_path(path),:body=>default_params.merge(body_args))
+ data = self.class.post(api_path(path),:body=>default_params.merge(body_args))
map_data(data,klass)
end
-
+
def delete(path)
self.class.delete(api_path(path),:query=>default_params)
end
-
+
def get_and_map(path,klass=nil,body_args = {})
data = self.class.get(api_path(path),:query=>default_params.merge(body_args))
map_data(data,klass)
end
-
+
def get_and_map_url(url,klass=nil)
data = self.class.get(url)
map_data(data,klass)
end
-
+
def map_data(data,klass=nil)
raise_error_if_necessary(data)
hash_or_array = extract_hash_or_array(data,klass)
hash_or_array = map_to_class(hash_or_array,klass) if klass
hash_or_array
end
-
+
#protected
-
+
def extract_hash_or_array(hash_or_array,klass)
return nil if hash_or_array == false
return hash_or_array if hash_or_array.nil? or hash_or_array.kind_of?(Array)
return extract_fetching_array(hash_or_array,klass) if hash_or_array.has_key?("data")
return hash_or_array
end
-
+
def extract_fetching_array(hash,klass)
f = Mogli::FetchingArray.new
f.concat(hash["data"])
@@ -84,7 +91,7 @@ def extract_fetching_array(hash,klass)
end
f
end
-
+
def map_to_class(hash_or_array,klass)
return nil if hash_or_array.nil?
if hash_or_array.kind_of?(Array)
@@ -93,24 +100,24 @@ def map_to_class(hash_or_array,klass)
hash_or_array = create_instance(klass,hash_or_array)
end
end
-
+
def create_instance(klass,data)
klass = determine_class(klass,data)
if klass.nil?
raise UnrecognizeableClassError.new("unable to recognize klass for #{klass.inspect} => #{data.inspect}")
end
klass.new(data,self)
end
-
+
def constantize_string(klass)
klass.is_a?(String) ? Mogli.const_get(klass) : klass
end
-
+
def determine_class(klass_or_klasses,data)
klasses = Array(klass_or_klasses).map { |k| constantize_string(k)}
klasses.detect {|klass| klass.recognize?(data)} || klasses.first
end
-
+
def raise_error_if_necessary(data)
if data.kind_of?(Hash)
if data.keys.size == 1 and data["error"]
@@ -120,22 +127,22 @@ def raise_error_if_necessary(data)
end
end
end
-
+
def fields_to_serialize
[:access_token,:default_params,:expiration]
end
-
+
# Only serialize the bare minimum to recreate the session.
def marshal_load(variables)#:nodoc:
fields_to_serialize.each_with_index{|field, index| instance_variable_set("@#{field}", variables[index])}
end
- # Only serialize the bare minimum to recreate the session.
+ # Only serialize the bare minimum to recreate the session.
def marshal_dump#:nodoc:
fields_to_serialize.map{|field| send(field)}
end
- # Only serialize the bare minimum to recreate the session.
+ # Only serialize the bare minimum to recreate the session.
def to_yaml( opts = {} )#nodoc
YAML::quick_emit(self.object_id, opts) do |out|
out.map(taguri) do |map|
@@ -145,6 +152,6 @@ def to_yaml( opts = {} )#nodoc
end
end
end
-
+
end
end
View
@@ -1,32 +1,60 @@
require "spec_helper"
describe Mogli::Authenticator do
-
+
let :authenticator do
Mogli::Authenticator.new("123456","secret","http://example.com/url")
end
-
+
it "has the client id" do
authenticator.client_id.should == "123456"
end
-
+
it "has the secret" do
authenticator.secret.should == "secret"
end
-
+
it "has the callback url" do
authenticator.callback_url.should == "http://example.com/url"
end
-
+
it "creates the authorize_url" do
authenticator.authorize_url.should == "https://graph.facebook.com/oauth/authorize?client_id=123456&redirect_uri=http%3A%2F%2Fexample.com%2Furl"
end
-
+
it "creates the authorize_url with scopes as an array" do
- authenticator.authorize_url(:scope=>[:user_photos,:user_videos,:stream_publish]).should ==
- "https://graph.facebook.com/oauth/authorize?client_id=123456&redirect_uri=http%3A%2F%2Fexample.com%2Furl&scope=user_photos,user_videos,stream_publish"
+ authenticator.authorize_url(:scope=>[:user_photos,:user_videos,:stream_publish]).should ==
+ "https://graph.facebook.com/oauth/authorize?client_id=123456&redirect_uri=http%3A%2F%2Fexample.com%2Furl&scope=user_photos,user_videos,stream_publish"
end
-
+
it "creates the access_token_url" do
authenticator.access_token_url("mycode").should == "https://graph.facebook.com/oauth/access_token?client_id=123456&redirect_uri=http%3A%2F%2Fexample.com%2Furl&client_secret=secret&code=mycode"
end
+
+ it "can trade session_keys for access_tokens" do
+ Mogli::Client.should_receive(:post).
+ with("https://graph.facebook.com/oauth/exchange_sessions",
+ :body => {:type => "client_cred", :client_id => "123456",
+ :client_secret => "secret",
+ :sessions => "mysessionkey,yoursessionkey"}).
+ and_return([{"access_token" => "myaccesstoken", "expires" => 5000},
+ {"access_token" => "youraccesstoken", "expires" => 5000}])
+
+ authenticator.
+ get_access_token_for_session_key(["mysessionkey","yoursessionkey"]).
+ should == [{"access_token" => "myaccesstoken", "expires" => 5000},
+ {"access_token" => "youraccesstoken", "expires" => 5000}]
+ end
+
+ it "can trade one session_key for an access_tokens" do
+ Mogli::Client.should_receive(:post).
+ with("https://graph.facebook.com/oauth/exchange_sessions",
+ :body => {:type => "client_cred", :client_id => "123456",
+ :client_secret => "secret", :sessions => "mysessionkey"}).
+ and_return({"access_token" => "myaccesstoken", "expires" => 5000})
+
+ authenticator.
+ get_access_token_for_session_key("mysessionkey").
+ should == {"access_token" => "myaccesstoken", "expires" => 5000}
+ end
+
end
Oops, something went wrong.

0 comments on commit 65c9b70

Please sign in to comment.