Commit 405e1bec

mo kareem <email@mokhan.ca>
2011-04-19 03:40:48
allow for signing up using twitter account.
1 parent 033271e
app/controllers/authentications_controller.rb
@@ -8,10 +8,27 @@ class AuthenticationsController < ApplicationController
   # POST /authentications
   # POST /authentications.xml
   def create
-    auth = request.env["omniauth.auth"]
-    current_user.authentications.find_or_create_by_provider_and_uid(auth['provider'], auth['uid'])
-    flash[:notice] = "Authentication successful."
-    redirect_to authentications_url
+    omniauth = request.env["omniauth.auth"]
+    authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
+    if authentication
+      flash[:notice] = "Signed in successfully."
+      sign_in_and_redirect(:user, authentication.user)
+    elsif current_user
+      current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])
+      flash[:notice] = "Authentication successful."
+      redirect_to authentications_url
+    else
+      user = User.new
+      user.apply_omniauth(omniauth)
+      if user.save
+        flash[:notice] = "Signed in successfully."
+        sign_in_and_redirect(:user, user)
+      else
+        session[:omniauth] = omniauth.except('extra')
+        redirect_to new_user_registration_url
+      end
+    end
+
   end
 
   # DELETE /authentications/1
app/controllers/registrations_controller.rb
@@ -0,0 +1,17 @@
+class RegistrationsController < Devise::RegistrationsController
+  def create
+    super
+    session[:omniauth] = nil unless @user.new_record?
+  end
+  
+  private
+  
+  def build_resource(*args)
+    super
+    if session[:omniauth]
+      @user.apply_omniauth(session[:omniauth])
+      @user.valid?
+    end
+  end
+end
+
app/helpers/registrations_helper.rb
@@ -0,0 +1,2 @@
+module RegistrationsHelper
+end
app/models/authentication.rb
@@ -1,3 +1,11 @@
 class Authentication < ActiveRecord::Base
   belongs_to :user
+
+  def provider_name
+    if provider == 'open_id'
+      "OpenID"
+    else
+      provider.titleize
+    end
+  end
 end
app/models/user.rb
@@ -8,4 +8,13 @@ class User < ActiveRecord::Base
 
   # Setup accessible (or protected) attributes for your model
   attr_accessible :email, :password, :password_confirmation, :remember_me
+
+  def apply_omniauth(omniauth)
+    self.email = omniauth['user_info']['email'] if email.blank?
+    authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'])
+  end
+  
+  def password_required?
+    (authentications.empty? || !password.blank?) && super
+  end
 end
app/views/authentications/index.html.erb
@@ -6,7 +6,7 @@
       <% for authentication in @authentications %>
         <div class="authentication">
           <%= image_tag "#{authentication.provider}_32.png", :size => "32x32" %>
-          <div class="provider"><%= authentication.provider.titleize %></div>
+          <div class="provider"><%= authentication.provider_name %></div>
           <div class="uid"><%= authentication.uid %></div>
           <%= link_to "X", authentication, :confirm => 'Are you sure you want to remove this authentication option?', :method => :delete, :class => "remove" %>
         </div>
app/views/devise/sessions/new.html.erb
@@ -1,3 +1,4 @@
+
 <h2>Sign in</h2>
 
 <%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
@@ -13,5 +14,25 @@
 
   <p><%= f.submit "Sign in" %></p>
 <% end %>
+<%= render :partial => "devise/shared/links" %>
+
+<p>or</p>
+<h2>Sign in through one of these services</h2>
+<a href="/auth/twitter" class="auth_provider">
+  <%= image_tag "twitter_64.png", :size => "64x64", :alt => "Twitter" %>
+  Twitter
+</a>
+<a href="/auth/facebook" class="auth_provider">
+  <%= image_tag "facebook_64.png", :size => "64x64", :alt => "Facebook" %>
+  Facebook
+</a>
+<a href="/auth/google_apps" class="auth_provider">
+  <%= image_tag "google_64.png", :size => "64x64", :alt => "Google" %>
+  Google
+</a>
+<a href="/auth/open_id" class="auth_provider">
+  <%= image_tag "openid_64.png", :size => "64x64", :alt => "OpenID" %>
+  OpenID
+</a>
+<div class="clear"></div>
 
-<%= render :partial => "devise/shared/links" %>
\ No newline at end of file
app/views/registrations/edit.html.erb
@@ -0,0 +1,25 @@
+<h2>Edit <%= resource_name.to_s.humanize %></h2>
+
+<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
+  <%= devise_error_messages! %>
+
+  <p><%= f.label :email %><br />
+  <%= f.email_field :email %></p>
+
+  <p><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
+  <%= f.password_field :password %></p>
+
+  <p><%= f.label :password_confirmation %><br />
+  <%= f.password_field :password_confirmation %></p>
+
+  <p><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
+  <%= f.password_field :current_password %></p>
+
+  <p><%= f.submit "Update" %></p>
+<% end %>
+
+<h3>Cancel my account</h3>
+
+<p>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.</p>
+
+<%= link_to "Back", :back %>
app/views/registrations/new.html.erb
@@ -0,0 +1,39 @@
+<h2>Sign up</h2>
+
+<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
+  <%= devise_error_messages! %>
+
+  <p><%= f.label :email %><br />
+  <%= f.email_field :email %></p>
+
+<% if @user.password_required? %>
+  <p><%= f.label :password %><br />
+  <%= f.password_field :password %></p>
+
+  <p><%= f.label :password_confirmation %><br />
+  <%= f.password_field :password_confirmation %></p>
+<% end %>
+
+  <p><%= f.submit "Sign up" %></p>
+<% end %>
+
+<%= render :partial => "devise/shared/links" %>
+<p>or</p>
+<h2>Sign up through one of these services</h2>
+<a href="/auth/twitter" class="auth_provider">
+  <%= image_tag "twitter_64.png", :size => "64x64", :alt => "Twitter" %>
+  Twitter
+</a>
+<a href="/auth/facebook" class="auth_provider">
+  <%= image_tag "facebook_64.png", :size => "64x64", :alt => "Facebook" %>
+  Facebook
+</a>
+<a href="/auth/google_apps" class="auth_provider">
+  <%= image_tag "google_64.png", :size => "64x64", :alt => "Google" %>
+  Google
+</a>
+<a href="/auth/open_id" class="auth_provider">
+  <%= image_tag "openid_64.png", :size => "64x64", :alt => "OpenID" %>
+  OpenID
+</a>
+<div class="clear"></div>
config/routes.rb
@@ -1,11 +1,13 @@
 Cake::Application.routes.draw do
+  match '/auth/:provider/callback' => 'authentications#create'
+  devise_for :users, :controllers => {:registrations => 'registrations'}
   resources :authentications
-
   get "dashboard/index"
-
   get "home/index"
-
-  devise_for :users
+  authenticate :user do
+    root :to => "home#index"
+  end
+  root :to => "devise:sessions#new"
 
   # The priority is based upon order of creation:
   # first created -> highest priority.
@@ -57,10 +59,6 @@ Cake::Application.routes.draw do
   # You can have the root of your site routed with "root"
   # just remember to delete public/index.html.
   #root :to => "home#index"
-  authenticate :user do
-    root :to => "home#index"
-  end
-  root :to => "devise:sessions#new"
 
   # See how all your routes lay out with "rake routes"
 
@@ -68,5 +66,4 @@ Cake::Application.routes.draw do
   # Note: This route will make all actions in every controller accessible via GET requests.
   # match ':controller(/:action(/:id(.:format)))'
   #
-  match '/auth/:provider/callback' => 'authentications#create'
 end
public/stylesheets/scaffold.css
@@ -54,3 +54,24 @@ div.field, div.actions {
   font-size: 12px;
   list-style: square;
 }
+.auth_provider img {
+  display: block;
+}
+
+.auth_provider {
+  float: left;
+  text-decoration: none;
+  margin-right: 20px;
+  text-align: center;
+  margin-bottom: 10px;
+}
+.clear {
+  clear: both;
+  height: 0;
+  overflow: hidden;
+}
+.width100{width: 100%;}
+.width50{width: 50%;}
+.floatLeft{float:left;}
+.floatRight{float:right;}
+
test/functional/registrations_controller_test.rb
@@ -0,0 +1,8 @@
+require 'test_helper'
+
+class RegistrationsControllerTest < ActionController::TestCase
+  # Replace this with your real tests.
+  test "the truth" do
+    assert true
+  end
+end
test/unit/helpers/registrations_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class RegistrationsHelperTest < ActionView::TestCase
+end