Skip to content
Browse files

Merge git://github.com/mmangino/facebooker2

Conflicts:
	README
	lib/facebooker2.rb
	lib/facebooker2/rails/controller.rb
	lib/facebooker2/rails/helpers/facebook_connect.rb
	lib/facebooker2/rails/helpers/javascript.rb
  • Loading branch information...
2 parents f3c506c + 5969866 commit 86306b78255a1bd039da09c4fb5fd621a9c28845 @dekart committed Jun 4, 2011
View
4 .gitignore
@@ -0,0 +1,4 @@
+*.swp
+.bundle
+.rvmrc
+Gemfile.lock
View
4 Gemfile
@@ -0,0 +1,4 @@
+source "http://rubygems.org"
+source :gemcutter
+
+gemspec
View
93 README
@@ -1,93 +0,0 @@
-Facebooker2
-===========
-
-Provides rails helpers for interfacing with Facebook's OpenGraph Javascript
-API, http://developers.facebook.com/docs/reference/javascript/.
-
-Requires the mogli gem.
-
-
-Example
-=======
-
-0. Prerequisite: You need a facebook app. Have your API Key, Application
-Secret, and Application ID handy.
-
-1. Install facebooker2 as a plugin in your rails app.
-
-2. Create config/facebooker.yml with the appropriate environment.
-
-production:
- app_id: <your application id>
- secret: <your application secret>
- api_key: <your application key>
- callback_url: <your callback url>
-
-3. Create config/initializers/facebooker2.rb and place the following line in it
-
-Facebooker2.load_facebooker_yaml
-
-4. Add the following line to your app/controllers/application_controller.rb
-
-include Facebooker2::Rails::Controller
-
-5. Update your rails applications to use the rails helpers. This could be in a
-shared login partial.
-
-<%= fb_connect_async_js %>
-<% if current_facebook_user %>
- <%= "Welcome #{current_facebook_user.first_name} #{current_facebook_user.last_name}!" %>
- or
- <%= "Hello #{fb_name(current_facebook_user, :useyou => false)}!" # link to facebook profile
- %>
- <%= fb_logout_link("Logout of fb", request.url) %><br />
-<% else
- # you must explicitly request permissions for facebook user fields.
- # here we instruct facebook to ask the user for permission for our website
- # to access the user's facebook email and birthday
- %>
- <%= fb_login_and_redirect('<your URL here>', :perms => 'email,user_birthday') %>
-<% end %>
-
-Using with Canvas Applications
-==============================
-
-To improve integration with Facebook and iframe canvas applications, the primary goal
-being things like FB.ui work as a dialog rather than a popup, the application
-needs to be authenticated against the user's account via OAuth before use.
-
-0. Prerequisite: You need a Facebook app. Have your canvas page name handy.
-
-1. Install facebooker2.
-
-2. Create config/facebooker.yml as above, but add the following key:
-
-production:
- canvas_page_name: <your canvas page name>
-
-3. Add the following lines to your app/controllers/application_controller.rb
-
-include Facebooker2::Rails::Controller
-
-before_filter :ensure_canvas_connected_to_facebook
-
-rescue_from Facebooker2::OAuthException do |exception|
- redirect_to 'http://www.facebook.com/'
-end
-
-private
-def ensure_canvas_connected_to_facebook
- ensure_canvas_connected(:email)
-end
-
-4. Create a route that generates a URL for the OAuth callback and calls the appropriate
-action on your controller:
-
-match '/facebook_oauth_connect' => 'application#facebook_oauth_connect'
-
-5. Your canvas application will now ensure that the current user has authorized
-the application before anything else is allowed. The authorization and FB.ui dialogs
-will appear inline instead of as popups, improving user experience.
-
-Copyright (c) 2010 Mike Mangino, released under the MIT license
-Copyright (c) 2010 John Bintz, released under the MIT license
View
86 README.md
@@ -0,0 +1,86 @@
+Facebooker2
+===========
+
+Provides rails helpers for interfacing with [Facebook's OpenGraph Javascript
+API](http://developers.facebook.com/docs/reference/javascript/).
+
+Requires the mogli gem.
+
+
+Example
+-------
+
+0- Prerequisite: You need a facebook app. Have your API Key, Application
+Secret, and Application ID handy.
+
+1- Install facebooker2 as a plugin in your rails app.
+
+2- Create `config/facebooker.yml` with the appropriate environment.
+
+ production:
+ app_id: <your application id>
+ secret: <your application secret>
+ api_key: <your application key>
+ callback_url: <your callback url>
+
+3- Create `config/initializers/facebooker2.rb` and place the following line in it
+
+ Facebooker2.load_facebooker_yaml
+
+4- Add the following line to your `app/controllers/application_controller.rb`
+ (add it right after the line class `ApplicationController < ActionController::Base` so as to add the Facebooker2 instance methods to the Application controller)
+
+ include Facebooker2::Rails::Controller
+
+5- Update your rails applications to use the rails helpers. This could be in a
+shared login partial.
+
+ <%= fb_connect_async_js %>
+ <% if current_facebook_user %>
+ <%= "Welcome #{current_facebook_user.first_name} #{current_facebook_user.last_name}!" %>
+ or
+ <%= "Hello #{fb_name(current_facebook_user, :useyou => false)}!" # link to facebook profile %>
+ <%= fb_logout_link("Logout of fb", request.url) %><br />
+ <% else
+ # you must explicitly request permissions for facebook user fields.
+ # here we instruct facebook to ask the user for permission for our website
+ # to access the user's facebook email and birthday
+ %>
+ <%= fb_login_and_redirect('<your URL here>', :perms => 'email,user_birthday') %>
+ <% end %>
+
+Facebook canvas applications
+----------------------------
+
+If you are building an application that runs inside a Facebook canvas, all the coming requests from Facebook to your iframe will
+be [POST requests](http://developers.facebook.com/docs/canvas/post/).
+
+You can use the PostCanvas rack middleware to turn the Facebook POST requests back to GET requests and keep your app restful
+as described in [this blog post](http://blog.coderubik.com/?p=178).
+If you are using Rails 3, put this line of code inside your `config.ru` file :
+
+ use Rack::PostCanvas
+
+Also, if you plan on supporting IE 6/7 and use cookie authentication, you should add a P3P header to your response in order for IE to accept the cookie :
+
+ before_filter :set_p3p_header_for_third_party_cookies
+
+See [this blog post](http://www.softwareprojects.com/resources/programming/t-how-to-get-internet-explorer-to-use-cookies-inside-1612.html)
+and [this forum thread](http://forum.developers.facebook.net/viewtopic.php?id=452) for details.
+
+Contributing
+------------
+
+Unit tests use rspec and require the following environment configuration to run:
+ rails 2.3.10
+ rspec 1.3.1
+ rspec-rails 1.3.3
+ json 1.4.0
+
+Invoke tests on Mac/Linux by running `rake spec` from this directory
+
+Invoke tests on Windows by running `spec spec/` from this directory
+
+
+
+Copyright (c) 2010 Mike Mangino, released under the MIT license
View
11 Rakefile
@@ -1,16 +1,13 @@
require 'rake'
-require 'rake/testtask'
require 'rake/rdoctask'
+require 'spec/rake/spectask'
desc 'Default: run unit tests.'
-task :default => :test
+task :default => :spec
desc 'Test the facebooker2 plugin.'
-Rake::TestTask.new(:test) do |t|
- t.libs << 'lib'
- t.libs << 'test'
- t.pattern = 'test/**/*_test.rb'
- t.verbose = true
+Spec::Rake::SpecTask.new('spec') do |t|
+ t.spec_files = FileList['spec/**/*.rb']
end
desc 'Generate documentation for the facebooker2 plugin.'
View
9 facebooker2.gemspec
@@ -1,6 +1,6 @@
spec = Gem::Specification.new do |s|
s.name = 'facebooker2'
- s.version = '0.0.5'
+ s.version = '0.0.11'
s.summary = "Facebook Connect integration library for ruby and rails"
s.description = "Facebook Connect integration library for ruby and rails"
s.files = Dir['lib/**/*.rb']
@@ -9,6 +9,13 @@ spec = Gem::Specification.new do |s|
s.author = "Mike Mangino"
s.email = "mmangino@elevatedrails.com"
s.homepage = "http://developers.facebook.com/docs/api"
+
s.add_dependency('mogli', ">=0.0.12")
s.add_dependency('ruby-hmac')
+
+ s.add_development_dependency('rake', '~> 0.8.7')
+ s.add_development_dependency('rspec', '~> 1.3.1')
+ s.add_development_dependency('rspec-rails', '~> 1.3.1')
+ s.add_development_dependency('rails', '~> 2.3.10')
+ s.add_development_dependency('json', '~> 1.4.0')
end
View
1 lib/facebooker2.rb
@@ -70,4 +70,5 @@ def self.cast_to_facebook_id(object)
require "facebooker2/rails/helpers/request_forms"
require "facebooker2/rails/helpers/user"
require "facebooker2/rails/helpers"
+require "facebooker2/rack/post_canvas"
require "facebooker2/oauth_exception"
View
23 lib/facebooker2/rack/post_canvas.rb
@@ -0,0 +1,23 @@
+# Rack middleware that converts POST requests from Facebook to GET request.
+# When there is a signed_parameter in the request params, this is a request iniated by the top Facebook frame
+# It will be sent as a POST request that we want to convert to a GET request to keep the app restful
+# See for details : http://blog.coderubik.com/?p=178
+module Rack
+ class PostCanvas
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ request = Request.new(env)
+
+ if request.POST['signed_request']
+ env["REQUEST_METHOD"] = 'GET'
+ end
+
+ return @app.call(env)
+ end
+
+ end
+end
View
175 lib/facebooker2/rails/controller.rb
@@ -29,37 +29,49 @@ def current_facebook_client
@_current_facebook_client
end
-
-
+
+ # This mimics the getSession logic from the php facebook SDK
+ # https://github.com/facebook/php-sdk/blob/master/src/facebook.php#L333
+ #
def fetch_client_and_user
return if @_fb_user_fetched
-
- fetch_client_and_user_from_cookie
- fetch_client_and_user_from_signed_request unless @_current_facebook_client
-
+
+ # Try to authenticate from the signed request first
+ sig = fetch_client_and_user_from_signed_request
+ sig = fetch_client_and_user_from_cookie if @_current_facebook_client.nil? and !signed_request_from_logged_out_user?
+
+ #write the authentication params to a new cookie
+ if !@_current_facebook_client.nil?
+ #we may have generated the signature based on the params in @facebook_params, and the expiration here is different
+
+ set_fb_cookie(@_current_facebook_client.access_token, @_current_facebook_client.expiration, @_current_facebook_user.id, sig)
+ else
+ # if we do not have a client, delete the cookie
+ set_fb_cookie(nil,nil,nil,nil)
+ end
+
@_fb_user_fetched = true
end
def fetch_client_and_user_from_cookie
- app_id = Facebooker2.app_id
-
- hash_data = fb_cookie_hash_for_app_id(app_id)
-
- if hash_data and fb_cookie_signature_correct?(hash_data, Facebooker2.secret)
+ hash_data = fb_cookie_hash
+
+ if hash_data and fb_cookie_signature_correct?(fb_cookie_hash, Facebooker2.secret)
fb_create_user_and_client(
hash_data["access_token"],
hash_data["expires"],
hash_data["uid"]
)
+
+ fb_cookie_hash["sig"]
end
end
-
-
- def fb_create_user_and_client(token, expires, userid)
- client = Mogli::Client.new(token,expires.to_i)
- user = Mogli::User.new(:id => userid)
-
+
+ def fb_create_user_and_client(token, expires, user_id)
+ client = Mogli::Client.new(token, expires.to_i)
+ user = Mogli::User.new(:id => user_id)
+
fb_sign_in_user_and_client(user, client)
end
@@ -71,38 +83,56 @@ def fb_sign_in_user_and_client(user, client)
@_current_facebook_client = client
@_fb_user_fetched = true
end
-
-
- def fb_cookie_hash_for_app_id(app_id)
- return unless fb_cookie = fb_cookie_for_app_id(app_id)
-
- {}.tap do |hash|
- data = fb_cookie.gsub(/"/,"")
-
- data.split("&").each do |str|
- parts = str.split("=")
- hash[parts.first] = parts.last
- end
+
+ def fb_cookie_hash
+ return nil unless fb_cookie?
+
+ hash = {}
+
+ data = fb_cookie.gsub(/"/, "")
+
+ data.split("&").each do |str|
+ parts = str.split("=")
+
+ hash[parts.first] = parts.last
end
end
-
-
- def fb_cookie_for_app_id(app_id)
- cookies["fbs_#{app_id}"]
+
+ def fb_cookie?
+ !fb_cookie.nil?
end
-
-
+
+ def fb_cookie
+ cookies[fb_cookie_name]
+ end
+
+ def fb_cookie_name
+ "fbs_#{Facebooker2.app_id}"
+ end
+
+ # check if the expected signature matches the one from facebook
def fb_cookie_signature_correct?(hash, secret)
+ generate_signature(hash, secret) == hash["sig"]
+ end
+
+ # If the signed request is valid but contains no oauth token,
+ # the user is either logged out from Facebook or has not authorized the app
+ def signed_request_from_logged_out_user?
+ !facebook_params.empty? && facebook_params[:oauth_token].nil?
+ end
+
+ # compute the md5 sig based on access_token,expires,uid, and the app secret
+ def generate_signature(hash, secret)
sorted_keys = hash.keys.reject {|k| k == "sig" }.sort
test_string = ""
sorted_keys.each do |key|
- test_string += "#{key}=#{hash[key]}"
+ test_string << "#{key}=#{hash[key]}"
end
- test_string += secret
-
- Digest::MD5.hexdigest(test_string) == hash["sig"]
+ test_string << secret
+
+ Digest::MD5.hexdigest(test_string)
end
@@ -161,8 +191,75 @@ def fetch_client_and_user_from_signed_request
facebook_params[:expires],
facebook_params[:user_id]
)
+
+ if @_current_facebook_client
+ #compute a signature so we can store it in the cookie
+ sig_hash = {
+ "uid" => facebook_params[:user_id],
+ "access_token" => facebook_params[:oauth_token],
+ "expires" => facebook_params[:expires]
+ }
+
+ generate_signature(sig_hash, Facebooker2.secret)
+ end
end
end
+
+
+ # /**
+ # This method was shamelessly stolen from the php facebook SDK:
+ # https://github.com/facebook/php-sdk/blob/master/src/facebook.php
+ #
+ # Set a JS Cookie based on the _passed in_ session. It does not use the
+ # currently stored session -- you need to explicitly pass it in.
+ #
+ # If a nil access_token is passed in this method will actually delete the fbs_ cookie
+ #
+ # */
+ def set_fb_cookie(access_token,expires,uid,sig)
+
+ #default values for the cookie
+ value = 'deleted'
+ expires = Time.now.utc - 3600 unless expires != nil
+
+ # If the expires value is set to some large value in the future, then the 'offline access' permission has been
+ # granted. In the Facebook JS SDK, this causes a value of 0 to be set for the expires parameter. This value
+ # needs to be correct otherwise the request signing fails, so if the expires parameter retrieved from the graph
+ # api is more than a year in the future, then we set expires to 0 to match the JS SDK.
+ expires = 0 if expires > Time.now + 1.year
+
+ if access_token
+ # Retrieve the existing cookie data
+ data = fb_cookie_hash || {}
+ # Remove the deleted value if this has previously been set, as we don't want to include it as part of the
+ # request signing parameters
+ data.delete('deleted') if data.key?('deleted')
+ # Keep existing cookie data that could have been set by FB JS SDK
+ data.merge!('access_token' => access_token, 'uid' => uid, 'sig' => sig, 'expires' => expires.to_i.to_s)
+ # Create string to store in cookie
+ value = '"'
+ data.each do |k,v|
+ value += "#{k.to_s}=#{v.to_s}&"
+ end
+ value.chop!
+ value+='"'
+ end
+
+ # if an existing cookie is not set, we dont need to delete it
+ if (value == 'deleted' && (!fb_cookie? || fb_cookie == "" ))
+ return;
+ end
+
+ #My browser doesn't seem to save the cookie if I set expires
+ cookies[fb_cookie_name] = { :value=>value }#, :expires=>expires}
+ end
+
+
+ # For canvas apps, You need to set the p3p header in order to get IE 6/7 to accept the third-party cookie
+ # For details http://www.softwareprojects.com/resources/programming/t-how-to-get-internet-explorer-to-use-cookies-inside-1612.html
+ def set_p3p_header_for_third_party_cookies
+ response.headers['P3P'] = 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"'
+ end
# Appends facebook signed_request to params on redirect
def redirect_to(options = {}, response_status = {})
View
7 lib/facebooker2/rails/helpers/facebook_connect.rb
@@ -23,7 +23,8 @@ def fb_login_and_redirect(url, options = {})
text = options.delete(:text)
- content_tag("fb:login-button", text, options.merge(:onlogin => js))
+ #rails 3 only escapes non-html_safe strings, so get the raw string instead of the SafeBuffer
+ content_tag("fb:login-button",text,options.merge(:onlogin => js.to_str))
end
@@ -32,7 +33,7 @@ def fb_login(options = {}, &proc)
text = options.delete(:text)
- content_tag("fb:login-button", text, options.merge(:onlogin => js))
+ content_tag("fb:login-button", text, options.merge(:onlogin => js.to_str))
end
@@ -42,7 +43,7 @@ def fb_login(options = {}, &proc)
def fb_logout_link(text, url, *args)
function = "FB.logout(function() {window.location.href = '#{url}';})"
- link_to_function(text, function, *args)
+ link_to_function(text, function.to_str, *args)
end
View
13 lib/facebooker2/rails/helpers/javascript.rb
@@ -6,7 +6,7 @@ def fb_concat(str)
if ::Rails::VERSION::STRING.to_i > 2
str
else
- concat(str)
+ concat(str); ""
end
end
@@ -33,7 +33,6 @@ def fb_connect_js(*args, &block)
app_id = args.shift || Facebooker2.app_id
options.reverse_merge!(
- :wrap_tag => true,
:cookie => true,
:status => true,
:xfbml => true,
@@ -63,17 +62,17 @@ def fb_connect_js(*args, &block)
};
(function() {
- var s = document.createElement('div');
- s.setAttribute('id','fb-root');
- document.documentElement.getElementsByTagName("body")[0].appendChild(s);
var e = document.createElement('script');
e.src = document.location.protocol + '//#{ js_url }';
e.async = true;
- s.appendChild(e);
+ document.getElementById('fb-root').appendChild(e);
}());
JAVASCRIPT
- js = javascript_tag(js) if options[:wrap_tag]
+ js = <<-CODE
+ <div id='fb-root'></div>
+ <script type="text/javascript">#{ js }</script>
+ CODE
else
js = <<-CODE
<div id='fb-root'></div>
View
65 spec/helpers/javascript_spec.rb
@@ -0,0 +1,65 @@
+require "spec_helper"
+describe Facebooker2::Rails::Helpers::Javascript, :type=>:helper do
+ include Facebooker2::Rails::Helpers
+ describe "fb_connect_async_js" do
+ it "loads with defaults" do
+ js = fb_connect_async_js '12345'
+ js.should == <<-JAVASCRIPT
+ <div id="fb-root"></div>
+ <script>
+ window.fbAsyncInit = function() {
+ FB.init({
+ appId : '12345',
+ status : true, // check login status
+ cookie : true, // enable cookies to allow the server to access the session
+
+ xfbml : true // parse XFBML
+ });
+
+ };
+
+ (function() {
+ var e = document.createElement('script'); e.async = true;
+ e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
+ document.getElementById('fb-root').appendChild(e);
+ }());
+ </script>
+ JAVASCRIPT
+ end
+
+ it "disables cookies" do
+ js = fb_connect_async_js '12345', :cookie => false
+ js.include?("cookie : false").should be_true, js
+ end
+
+ it "disables checking login status" do
+ js = fb_connect_async_js '12345', :status => false
+ js.include?("status : false").should be_true, js
+ end
+
+ it "disables xfbml parsing" do
+ js = fb_connect_async_js '12345', :xfbml => false
+ js.include?("xfbml : false").should be_true, js
+ end
+
+ it "adds a channel url" do
+ js = fb_connect_async_js '12345', :channel_url => 'http://channel.url'
+ js.include?("channelUrl : 'http://channel.url'").should be_true, js
+ end
+
+ it "changes the default locale" do
+ js = fb_connect_async_js '12345', :locale => 'fr_FR'
+ js.include?("//connect.facebook.net/fr_FR/all.js").should be_true, js
+ end
+
+ # Can't get this to work!
+ # it "adds extra js" do
+ # helper.output_buffer = ""
+ # fb_connect_async_js do
+ # "FB.Canvas.setAutoResize();"
+ # end
+ # helper.output_buffer.include?("FB.Canvas.setAutoResize();").should be_true, helper.output_buffer
+ # end
+
+ end
+end
View
79 spec/rails/controller_spec.rb
@@ -25,16 +25,17 @@ class FakeController < ActionController::Base
describe "Cookie handling" do
it "knows if a cookie exists for this app" do
- controller.fb_cookie_for_app_id?(12345).should be_true
+ controller.fb_cookie.should be_true
end
it "knows when there isn't a cookie" do
- controller.fb_cookie_for_app_id?(432432).should be_false
+ controller.stub!(:cookies).and_return("")
+ controller.fb_cookie?.should be_false
end
it "gets the hash from the cookie" do
controller.stub!(:cookies).and_return("fbs_12345"=>"param1=val1&param2=val2")
- controller.fb_cookie_hash_for_app_id(12345).should == {"param1"=>"val1", "param2"=>"val2"}
+ controller.fb_cookie_hash.should == {"param1"=>"val1", "param2"=>"val2"}
end
it "creates a user from the cookie" do
@@ -59,6 +60,7 @@ class FakeController < ActionController::Base
end
it "creates a client from params" do
+ controller.stub!(:fb_cookie_hash).and_return({})
controller.stub!(:cookies).and_return({})
controller.stub!(:facebook_params).and_return(
:oauth_token => "103188716396725|2.N0kBq5D0cbwjTGm9J4xRgA__.3600.1279814400-585612657|Txwy8S7sWBIJnyAXebEgSx6ntgY.",
@@ -93,7 +95,39 @@ class FakeController < ActionController::Base
end
-
+ it "does not set a cookie if it is not required" do
+ controller.stub!(:cookies).and_return("")
+ controller.set_fb_cookie(nil,
+ Time.now,
+ "5436785463785",
+ "4337fcdee4cc68bb70ec495c0eebf89c").should be_nil
+ controller.fb_cookie.should be_nil
+ end
+
+ it "sets a valid cookie if the access token is not nil" do
+ tn = Time.now
+ controller.set_fb_cookie("114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.",
+ tn,
+ "5436785463785",
+ "4337fcdee4cc68bb70ec495c0eebf89c").should be_true
+ controller.fb_cookie[:value].should == "\"session_key=57f0206b01ad48bf84ac86f1-12451752&expires=#{tn.to_i}&uid=5436785463785&sig=4337fcdee4cc68bb70ec495c0eebf89c&secret=1e3375dcc4527e7ead0f82c095421690&access_token=114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.\""
+ end
+
+ it "sets a cookie with an expires value of 0 if the access token expires value is far in the future" do
+ controller.set_fb_cookie("114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.",
+ Time.now+2.year,
+ "5436785463785",
+ "4337fcdee4cc68bb70ec495c0eebf89c").should be_true
+ controller.fb_cookie[:value].should == "\"session_key=57f0206b01ad48bf84ac86f1-12451752&expires=0&uid=5436785463785&sig=4337fcdee4cc68bb70ec495c0eebf89c&secret=1e3375dcc4527e7ead0f82c095421690&access_token=114355055262088|57f0206b01ad48bf84ac86f1-12451752|63WyZjRQbzowpN8ibdIfrsg80OA.\""
+ end
+
+ it "sets a cookie with the value deleted if the access token is nil" do
+ controller.set_fb_cookie(nil,
+ Time.now,
+ "5436785463785",
+ "4337fcdee4cc68bb70ec495c0eebf89c").should be_true
+ controller.fb_cookie[:value].should == "deleted"
+ end
end
describe "Signed Request handling" do
@@ -111,9 +145,40 @@ class FakeController < ActionController::Base
it "doesn't provide facebook params if the sig is invalid" do
Facebooker2.secret = "mysecretkey"
controller.stub!(:params).and_return(:signed_request=>"invalid.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk4MjE2MDAsIm9hdXRoX3Rva2VuIjoiMTAzMTg4NzE2Mzk2NzI1fDIucnJRSktyRzFRYXpGYTFoa2Z6MWpMZ19fLjM2MDAuMTI3OTgyMTYwMC01MzI4Mjg4Njh8TWF4QVdxTWtVS3lKbEFwOVgwZldGWEF0M004LiIsInVzZXJfaWQiOiI1MzI4Mjg4NjgifQ")
- controller.facebook_params.should be_blank
-
+ controller.facebook_params.should be_blank
end
+
+ it "writes a cookie to the client if the sig is valid" do
+ controller.stub!(:params).and_return(:signed_request=>"N1JJFILX63MufS1zpHZwN109VK1ggzEsD0N4pH-yPtc.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk4MjE2MDAsIm9hdXRoX3Rva2VuIjoiMTAzMTg4NzE2Mzk2NzI1fDIucnJRSktyRzFRYXpGYTFoa2Z6MWpMZ19fLjM2MDAuMTI3OTgyMTYwMC01MzI4Mjg4Njh8TWF4QVdxTWtVS3lKbEFwOVgwZldGWEF0M004LiIsInVzZXJfaWQiOiI1MzI4Mjg4NjgifQ")
+ Facebooker2.secret = "mysecretkey"
+ controller.fetch_client_and_user.should be_true
+ controller.fb_cookie.should_not be_nil
+ sig = controller.generate_signature({"uid"=>controller.facebook_params[:user_id],
+ "access_token"=>controller.facebook_params[:oauth_token],
+ "expires"=>controller.facebook_params[:expires]},
+ Facebooker2.secret)
+
+ controller.fb_cookie[:value].should == "\"session_key=57f0206b01ad48bf84ac86f1-12451752&"+
+ "expires=1279821600&"+
+ "uid=532828868&"+
+ "sig=0d82b1bb944e5bf8e753a71ee72e9e23&"+
+ "secret=1e3375dcc4527e7ead0f82c095421690&"+
+ "access_token=103188716396725|2.rrQJKrG1QazFa1hkfz1jLg__.3600.1279821600-532828868|MaxAWqMkUKyJlAp9X0fWFXAt3M8.\""
+
+ end
+
+ it "uses the cookie if no signed_request is provided" do
+ controller.fetch_client_and_user.should be_true
+ controller.current_facebook_user.id.should == "12451752"
+ end
+
+ it "deletes the cookie if the signed_request does not contain a oauth token (logged out or unauthorized user)" do
+ controller.stub!(:facebook_params).and_return({"algorithm"=>"HMAC-SHA256", "issued_at"=>1300976861, "user"=>{"country"=>"ca", "locale"=>"fr_CA", "age"=>{"min"=>21}}})
+ controller.fetch_client_and_user.should be_true
+ controller.fb_cookie[:value].should == "deleted"
+ controller.current_facebook_user.should be_nil
+ end
+
end
describe "Methods" do
@@ -135,4 +200,4 @@ class FakeController < ActionController::Base
end
-end
+end
View
4 spec/spec.opts
@@ -0,0 +1,4 @@
+--colour
+--format progress
+--loadby mtime
+--reverse
View
14 spec/spec_helper.rb
@@ -1,4 +1,18 @@
require "rubygems"
+
+begin
+ require 'bundler'
+ begin
+ Bundler.setup(:default, :development)
+ rescue Bundler::BundlerError => e
+ $stderr.puts e.message
+ $stderr.puts "Run `bundle install` to install missing gems"
+ exit e.status_code
+ end
+rescue LoadError
+ # Not using bundler
+end
+
require "active_support"
require "action_pack"
require "action_view"

0 comments on commit 86306b7

Please sign in to comment.
Something went wrong with that request. Please try again.