lib/koala.rb in koala-0.4.1 vs lib/koala.rb in koala-0.5.0

- old
+ new

@@ -104,11 +104,11 @@ # Most write operations require extended permissions. For example, # publishing wall posts requires the "publish_stream" permission. See # http://developers.facebook.com/docs/authentication/ for details about # extended permissions. - raise GraphAPIError.new(nil, "Write operations require an access token") unless @access_token + raise GraphAPIError.new({"type" => "KoalaMissingAccessToken", "message" => "Write operations require an access token"}) unless @access_token api("#{parent_object}/#{connection_name}", args, "post") end def put_wall_post(message, attachment = {}, profile_id = "me") # Writes a wall post to the given profile's wall. @@ -159,27 +159,28 @@ # and cause JSON.parse to fail # so we account for that response = JSON.parse("[#{result}]")[0] # check for errors - if response.is_a?(Hash) && error = response["error"] - raise GraphAPIError.new(error["code"], error["message"]) + if response.is_a?(Hash) && error_details = response["error"] + raise GraphAPIError.new(error_details) end response end end class GraphAPIError < Exception - attr_accessor :code - def initialize(code, message) - super(message) - self.code = code + attr_accessor :fb_error_type + def initialize(details = {}) + self.fb_error_type = details["type"] + super("#{fb_error_type}: #{details["message"]}") end end - class OAuth + class OAuth + attr_accessor :app_id, :app_secret, :oauth_callback_url def initialize(app_id, app_secret, oauth_callback_url = nil) @app_id = app_id @app_secret = app_secret @oauth_callback_url = oauth_callback_url end @@ -205,30 +206,64 @@ # since we no longer get individual cookies, we have to separate out the components ourselves components = {} fb_cookie.split("&").map {|param| param = param.split("="); components[param[0]] = param[1]} + # generate the signature and make sure it matches what we expect 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"].to_i == 0 || Time.now.to_i < components["expires"].to_i) ? components : nil + 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_from_cookies, :get_user_from_cookie 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}" : "" callback = options[:callback] || @oauth_callback_url + raise ArgumentError, "url_for_oauth_code must get a callback either from the OAuth object or in the options!" unless callback # Creates the URL for oauth authorization for a given callback and optional set of permissions "https://#{GRAPH_SERVER}/oauth/authorize?client_id=#{@app_id}&redirect_uri=#{callback}#{scope}" end - def url_for_access_token(code, callback = @oauth_callback_url) + def url_for_access_token(code, options = {}) # Creates the URL for the token corresponding to a given code generated by Facebook + if options.is_a?(String) # changing the arguments + puts "Deprecation warning: url_for_access_token now takes an options hash as the second argument; pass the callback as :callback." + options = {:callback => options} + end + 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 parse_access_token(response_text) + components = response_text.split("&").inject({}) do |hash, bit| + key, value = bit.split("=") + hash.merge!(key => value) + end + components + end + + def fetch_token_string(code) + Koala.make_request("oauth/access_token", { + :client_id => @app_id, + :redirect_uri => @oauth_callback_url, + :client_secret => @app_secret, + :code => code + }, "get") + end + + def get_access_token(code) + result = fetch_token_string(code) + + # if we have an error, parse the error JSON and raise an error + raise GraphAPIError.new((JSON.parse(result)["error"] rescue nil) || {}) if result =~ /error/ + # otherwise, parse the access token + parse_access_token(result) end end end # finally, set up the http service Koala methods used to make requests \ No newline at end of file