lib/koala.rb in koala-0.7.2 vs lib/koala.rb in koala-0.7.3
- old
+ new
@@ -50,10 +50,15 @@
# Fetches the given path in the Graph API.
args["access_token"] = @access_token || @app_access_token if @access_token || @app_access_token
# make the request via the provided service
result = Koala.make_request(path, args, verb, options)
+ # Check for any 500 errors before parsing the body
+ # since we're not guaranteed that the body is valid JSON
+ # in the case of a server error
+ raise APIError.new({"type" => "HTTP #{result.status.to_s}", "message" => "Response body: #{result.body}"}) if result.status >= 500
+
# Parse the body as JSON and check for errors if provided a mechanism to do so
# Note: Facebook sometimes sends results like "true" and "false", which aren't strictly objects
# and cause JSON.parse to fail -- so we account for that by wrapping the result in []
body = response = JSON.parse("[#{result.body.to_s}]")[0]
if error_checking_block
@@ -101,15 +106,14 @@
@app_id = app_id
@app_secret = app_secret
@oauth_callback_url = oauth_callback_url
end
- def get_user_from_cookie(cookie_hash)
+ def get_user_info_from_cookie(cookie_hash)
# Parses the cookie set by the official Facebook JavaScript SDK.
#
- # cookies should be a dictionary-like object mapping cookie names to
- # cookie values.
+ # cookies should be a Hash, like the one Rails provides
#
# If the user is logged in via Facebook, we return a dictionary with the
# keys "uid" and "access_token". The former is the user's Facebook ID,
# and the latter can be used to make authenticated requests to the Graph API.
# If the user is not logged in, we return None.
@@ -130,12 +134,24 @@
auth_string = components.keys.sort.collect {|a| a == "sig" ? nil : "#{a}=#{components[a]}"}.reject {|a| a.nil?}.join("")
sig = Digest::MD5.hexdigest(auth_string + @app_secret)
sig == components["sig"] && (components["expires"] == "0" || Time.now.to_i < components["expires"].to_i) ? components : nil
end
end
+ alias_method :get_user_info_from_cookies, :get_user_info_from_cookie
+
+ def get_user_from_cookie(cookies)
+ # overload this to be backward compatible with older implementations
+ # icky ruby magic, but it's _really_ cool we can do this
+ info = get_user_info_from_cookies(cookies)
+ string = info["uid"]
+
+ overload_as_hash(string, info)
+ end
alias_method :get_user_from_cookies, :get_user_from_cookie
+ # URLs
+
def url_for_oauth_code(options = {})
# for permissions, see http://developers.facebook.com/docs/authentication/permissions
permissions = options[:permissions]
scope = permissions ? "&scope=#{permissions.is_a?(Array) ? permissions.join(",") : permissions}" : ""
@@ -155,22 +171,38 @@
callback = options[:callback] || @oauth_callback_url
raise ArgumentError, "url_for_access_token must get a callback either from the OAuth object or in the parameters!" unless callback
"https://#{GRAPH_SERVER}/oauth/access_token?client_id=#{@app_id}&redirect_uri=#{callback}&client_secret=#{@app_secret}&code=#{code}"
end
- def get_access_token(code)
+ def get_access_token_info(code)
# convenience method to get a parsed token from Facebook for a given code
# should this require an OAuth callback URL?
get_token_from_server(:code => code, :redirect_uri => @oauth_callback_url)
end
- def get_app_access_token
+ def get_access_token(code)
+ info = get_access_token_info(code)
+ # upstream methods will throw errors if needed
+ string = info["access_token"]
+
+ overload_as_hash(string, info)
+ end
+
+ def get_app_access_token_info
# convenience method to get a the application's sessionless access token
get_token_from_server({:type => 'client_cred'}, true)
end
- def get_tokens_from_session_keys(sessions)
+ def get_app_access_token
+ info = get_app_access_token_info
+ string = info["access_token"]
+
+ overload_as_hash(string, info)
+ end
+
+ # from session keys
+ def get_token_info_from_session_keys(sessions)
# fetch the OAuth tokens from Facebook
response = fetch_token_string({
:type => 'client_cred',
:sessions => sessions.join(",")
}, true, "exchange_sessions")
@@ -182,12 +214,25 @@
end
JSON.parse(response)
end
+ def get_tokens_from_session_keys(sessions)
+ # get the original hash results
+ results = get_token_info_from_session_keys(sessions)
+ # now recollect them as backward-compatible strings
+ # for easier use
+ results.collect do |r|
+ string = r["access_token"]
+
+ overload_as_hash string, r
+ end
+ end
+
def get_token_from_session_key(session)
# convenience method for a single key
+ # gets the overlaoded strings automatically
get_tokens_from_session_keys([session])[0]
end
protected
@@ -213,9 +258,26 @@
def fetch_token_string(args, post = false, endpoint = "access_token")
Koala.make_request("oauth/#{endpoint}", {
:client_id => @app_id,
:client_secret => @app_secret
}.merge!(args), post ? "post" : "get").body
+ end
+
+ # overload the object to be accessible as a hash
+ # used to make get_*_token methods backward compatible
+ # icky ruby magic, but it's _really_ cool we can do this
+ def overload_as_hash(obj, hash)
+ command = <<-EOS
+ def [](index)
+ puts "WARNING: get_app_access_token now provides the access token as a string; use get_app_access_token_info if you want the hash with expirations. Otherwise you no longer need to call [] to get the token itself."
+ hash = #{hash.inspect}
+ hash[index]
+ end
+ EOS
+
+ (class << obj; self; end).class_eval command
+
+ obj
end
end
end
# finally, set up the http service Koala methods used to make requests