Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit 322773f2a482862aa65bfe74fab45301b6f5e1d4 @langalex langalex committed Jul 14, 2009
Showing with 1,084 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +20 −0 MIT-LICENSE
  3. +90 −0 README.md
  4. +27 −0 Rakefile
  5. +59 −0 app/controllers/simple_facebook_connect/connect_controller.rb
  6. +15 −0 app/views/shared/_facebook_connect_button.html.erb
  7. +4 −0 config/simple_facebook_connect_routes.rb
  8. +14 −0 generators/simple_facebook_connect_features/simple_facebook_connect_features_generator.rb
  9. +9 −0 generators/simple_facebook_connect_features/templates/facebook_auth_getsession.xml
  10. +27 −0 generators/simple_facebook_connect_features/templates/facebook_connect.feature
  11. +19 −0 generators/simple_facebook_connect_features/templates/facebook_connect_steps.rb
  12. +44 −0 generators/simple_facebook_connect_features/templates/facebook_connect_stubs.rb
  13. +119 −0 generators/simple_facebook_connect_features/templates/facebook_users_getinfo.xml
  14. +13 −0 generators/simple_facebook_connect_migration/simple_facebook_connect_migration_generator.rb
  15. +17 −0 generators/simple_facebook_connect_migration/templates/migration.rb
  16. +35 −0 init.rb
  17. +14 −0 lib/simple_facebook_connect.rb
  18. +11 −0 lib/simple_facebook_connect/controller_extension.rb
  19. +13 −0 lib/simple_facebook_connect/extensions/routes.rb
  20. +161 −0 lib/simple_facebook_connect/parser.rb
  21. +34 −0 lib/simple_facebook_connect/service.rb
  22. +73 −0 lib/simple_facebook_connect/session.rb
  23. +26 −0 lib/simple_facebook_connect/user.rb
  24. +21 −0 lib/simple_facebook_connect/user_extension.rb
  25. +1 −0 rails/init.rb
  26. +9 −0 spec/fixtures/facebook.auth.getSession/default.xml
  27. +119 −0 spec/fixtures/facebook.users.getInfo/default.xml
  28. +12 −0 spec/lib/simple_facebook_connect/parser_spec.rb
  29. +16 −0 spec/lib/simple_facebook_connect/user_extension_spec.rb
  30. +30 −0 spec/lib/simple_facebook_connect/user_spec.rb
  31. +31 −0 spec/spec_helper.rb
@@ -0,0 +1 @@
+*.sqlite3
@@ -0,0 +1,20 @@
+Copyright (c) 2009 [name of plugin creator]
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,90 @@
+## Simple Facebook Connect
+
+This plugin adds the ability to sign in/sign up using facebook connect to your Rails application.
+
+## Disclaimer
+
+Most of the code here is a direct rip-off of the facebooker gem. We wanted something much simpler than facebooker so we took the code we needed, refactored and changed bits and pieces and here we are.
+
+## Basic process
+
+With this plugin you will add the well know facebook connect button to your site. When a visitor clicks on it:
+
+* she will be redirected to facebook
+* after signing in at facebook be directed back to your signup page
+* there she will sign up as usual but without being asked to enter a password
+* after signing up she will be able to sign into your site by clicking the facebook connect button
+
+When an existing user of your site clicks the button he will also be able to log in via facebook, given the email address he signed up with at your site is also known to facebook.
+
+## Installation
+
+This plugin assumes you have a `User` model with an `email` attribute. It will add some extensions to your `User` model and controllers in order to provide the necessary hooks and calls for facebook to authenticate your users.
+
+Install the gem:
+
+ sudo gem install upstream-simple_facebook_connect
+
+Add it as a dependency to your Rails application:
+
+ # environment.rb
+ gem 'upstream-simple_facebook_connect', :source => 'http://gems.github.com'
+
+Run the migration generator and migrate:
+
+ script/generate simple_facebook_connect_migration
+ rake db:migrate
+ rake db:test:clone
+
+Add the facebook connect button to your sign up and/or sign in pages. We have prepared a partial for you:
+
+ <%= render :partial => 'shared/facebook_connect_button' %>
+
+Add this to your signup action (`users/create` in most cases):
+
+ class UsersController < ApplicationController
+ def create
+ @user = # initialize user
+ ....
+ @user.fb_uid = facebook_user.uid if facebook_user
+ @user.save
+ end
+ end
+
+Change your signup form to not show any password fields when signing up via facebook:
+
+ <%- unless facebook_user -%>
+ <%= f.password_field :password -%>
+ ...
+ <%- end -%>
+
+Provide a `log_in(user)` method, either in your `ApplicationController` or by subclassing `SimpleFacebookConnect::ConnectController`:
+
+ class AppicationController < ActionController::Base
+
+ ...
+
+ private
+
+ def log_in(user)
+ session[:user_id] = user.id # or whatever your app does
+ redirect_to account_path
+ end
+ end
+
+Optional step (well, you really should do this): Generate Cucumber Features:
+
+ script/generate simple_facebook_connect_features
+
+This will generate a feature, step definitions and fixtures to test the facebook connect integration. You will probably have to adjust those files to fit your app, for example we are using _Machinist_ to generate `User` instances.
+
+Finally: run the features and by now everything should be green. Congrats.
+
+## Links
+
+* facebooker: http://facebooker.rubyforge.org/
+* contact: http://upstream-berlin.com
+* email: alex [at] upstream-berlin dot com
+
+
+Copyright (c) 2009 Alexander Lang, Frank Prößdorf, released under the MIT license
@@ -0,0 +1,27 @@
+# encoding: utf-8
+
+require 'rubygems'
+require 'rake'
+require 'spec/rake/spectask'
+
+begin
+ require 'jeweler'
+ Jeweler::Tasks.new do |gem|
+ gem.name = "simple_facebook_connect"
+ gem.summary = %Q{This plugin adds the ability to sign in/sign up using facebook connect to your Rails application.}
+ gem.email = "alex@upstream-berlin.com"
+ gem.homepage = "http://github.com/upstream/simple_facebook_connect"
+ gem.authors = ["Alexander Lang", 'Frank Prößdorf']
+ end
+
+rescue LoadError
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
+end
+
+desc 'Default: run specs.'
+task :default => :spec
+
+desc "Run all specs"
+Spec::Rake::SpecTask.new(:spec) do |t|
+ t.spec_files = FileList['spec/**/*_spec.rb']
+end
@@ -0,0 +1,59 @@
+module SimpleFacebookConnect
+ class ConnectController < ApplicationController
+
+ def authenticate
+ redirect_to new_facebook_session.login_url
+ end
+
+ def connect
+ begin
+ new_facebook_session(params['auth_token'])
+ if facebook_user
+ unless log_in_via_fb_id(facebook_user) || log_in_via_email_hash(facebook_user)
+ redirect_to(signup_path)
+ end
+ else
+ render(:nothing => true)
+ end
+ rescue StandardError => e
+ Rails.logger.warn e.message
+ redirect_to fb_authenticate_path
+ end
+ end
+
+ private
+
+ def signup_path
+ new_user_path(:fb_user => 1)
+ end
+
+ def new_facebook_session(token = nil)
+ facebook_session = Session.new(SimpleFacebookConnect.api_key, SimpleFacebookConnect.secret_key)
+ if token
+ facebook_session.auth_token = token
+ facebook_session.secure!
+ session[:facebook_session] = facebook_session
+ end
+ facebook_session
+ end
+
+ def log_in_via_fb_id(facebook_user)
+ if user = ::User.find_by_fb_uid(facebook_user.uid)
+ log_in(user)
+ true
+ end
+ end
+
+ def log_in_via_email_hash(facebook_user)
+ facebook_user.email_hashes.each do |hash|
+ if user = ::User.find_by_email_hash(hash)
+ user.update_attribute(:fb_uid, facebook_user.uid)
+ log_in(user)
+ return true
+ end
+ end
+ false
+ end
+
+ end
+end
@@ -0,0 +1,15 @@
+<fb:login-button onclick="redirect_to_authenticate()"></fb:login-button>
+<%= javascript_include_tag 'http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php' %>
+<script type="text/javascript" charset="utf-8">
+ function redirect_to_authenticate() {
+ FB.Facebook.get_sessionState().waitUntilReady(function() {
+ window.location = window.facebook_authenticate_location;
+ });
+ };
+
+ window.api_key = "<%= SimpleFacebookConnect.api_key %>";
+ window.facebook_authenticate_location = '<%= fb_authenticate_path %>';
+ window.xd_receiver = '/xd_receiver.html';
+
+ FB.init(window.api_key, window.xd_receiver);
+</script>
@@ -0,0 +1,4 @@
+ActionController::Routing::Routes.draw do |map|
+ map.fb_connect '/fb/connect', :controller => 'simple_facebook_connect/connect', action: 'connect'
+ map.fb_authenticate '/fb/authenticate', :controller => 'simple_facebook_connect/connect', action: 'authenticate'
+end
@@ -0,0 +1,14 @@
+class SimpleFacebookConnectFeaturesGenerator < Rails::Generator::Base
+ def manifest
+ record do |r|
+ r.file 'facebook_connect.feature', "features/facebook_connect.feature"
+ r.file 'facebook_connect_steps.rb', "features/step_definitions/facebook_connect_steps.rb"
+ r.file 'facebook_connect_stubs.rb', "features/support/facebook_connect_stubs.rb"
+
+ r.directory 'features/fixtures/facebook.auth.getSession'
+ r.file 'facebook_auth_getsession.xml', "features/fixtures/facebook.auth.getSession/default.xml"
+ r.directory 'features/fixtures/facebook.users.getInfo'
+ r.file 'facebook_users_getinfo.xml', "features/fixtures/facebook.users.getInfo/default.xml"
+ end
+ end
+end
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<auth_getSession_response
+ xmlns="http://api.facebook.com/1.0/"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd">
+ <session_key>5f34e11bfb97c762e439e6a5-8055</session_key>
+ <uid>8055</uid>
+ <expires>1173309298</expires>
+</auth_getSession_response>
@@ -0,0 +1,27 @@
+Feature: facebook connect
+ In order to get more users
+ As a site owner
+ I want users to easily sign in and sign up via facebook
+
+ Scenario: sign in via facebook when being connected
+ Given a user who is connected via facebook
+ When I go to the start page
+ And I sign in via facebook
+ Then I should see "Welcome"
+
+ Scenario: sign in via facebook when not being connected
+ Given a user with the email "email@person.com"
+ When I go to the start page
+ And I sign in via facebook
+ Then I should see "Welcome"
+
+ Scenario: sign up via facebook
+ When I go to the start page
+ And I sign up via facebook
+ Then I should not see "Password"
+ When I fill in "Email" with "email@person.com"
+ And I press "Sign Up"
+
+ Then I should see "instructions for confirming"
+ And a confirmation message should be sent to "email@person.com"
+ And my facebook id should be set
@@ -0,0 +1,19 @@
+When /I sign up via facebook/ do
+ get fb_authenticate_path
+ response.redirected_to.should include('facebook.com')
+ # go to facebook and come back with auth token
+ post fb_connect_path, auth_token: '3e4a22bb2f5ed75114b0fc9995ea85f1'
+ visit response.redirected_to
+end
+
+When /I sign in via facebook/ do
+ When 'I sign up via facebook'
+end
+
+Then 'my facebook id should be set' do
+ User.last.fb_uid.should == 8055 # taken from xml fixture
+end
+
+Given /a user who is connected via facebook/ do
+ User.make fb_uid: 8055 # make from machinist
+end
@@ -0,0 +1,44 @@
+module SimpleFacebookConnect
+ module ServiceStub
+ def read_fixture(method)
+ if File.exists?(fixture_path(method, 'default'))
+ File.read fixture_path(method, 'default')
+ else
+ e.message << "\nFacebook API Reference: http://wiki.developers.facebook.com/index.php/#{method.sub(/^facebook\./, '')}#Example_Return_XML"
+ raise e
+ end
+ end
+
+ def post(params)
+ method = params.delete(:method)
+ params.delete_if {|k,_| [:v, :api_key, :call_id, :sig].include?(k) }
+ Parser.parse(method, read_fixture(method))
+ end
+
+ private
+
+ def fixture_path(method, filename)
+ File.join(Rails.root + 'features/fixtures', method, "#{filename}.xml")
+ end
+ end
+
+ module SessionStub
+ def service
+ unless @service
+ service = Service.new(Session::API_SERVER_BASE_URL, Session::API_PATH_REST, @api_key)
+ service.extend(ServiceStub)
+ @service = service
+ else
+ @service
+ end
+ end
+ end
+end
+
+SimpleFacebookConnect::Session.class_eval do
+ def self.new(*args)
+ session = super
+ session.extend SimpleFacebookConnect::SessionStub
+ session
+ end
+end
Oops, something went wrong.

0 comments on commit 322773f

Please sign in to comment.