Skip to content

Commit

Permalink
Omniauth for Google and Facebook
Browse files Browse the repository at this point in the history
  • Loading branch information
sachac committed Dec 26, 2011
1 parent 0b9b05f commit 196d592
Show file tree
Hide file tree
Showing 33 changed files with 291 additions and 5 deletions.
5 changes: 4 additions & 1 deletion Gemfile
Expand Up @@ -55,7 +55,10 @@ gem 'nifty-generators'
#gem 'sparklines_generator'
gem 'workflow'
gem 'devise'
gem 'web-app-theme'
gem 'omniauth', :git => 'git://github.com/intridea/omniauth.git'
gem 'omniauth-facebook'
gem 'omniauth-twitter'
gem 'omniauth-openid'
gem 'ruby_parser'
group :assets do
gem 'therubyracer'
Expand Down
42 changes: 40 additions & 2 deletions Gemfile.lock
@@ -1,3 +1,11 @@
GIT
remote: git://github.com/intridea/omniauth.git
revision: 7c9c8da1c4240c4b4ebb40f35de807ed8a341a23
specs:
omniauth (1.0.1)
hashie (~> 1.2)
rack (~> 1.0)

GIT
remote: git://github.com/mbleigh/acts-as-taggable-on.git
revision: 0662e665866d4a668158d1ceff91fc243b3f63f6
Expand Down Expand Up @@ -52,6 +60,7 @@ GEM
multi_json (~> 1.0)
acts-as-tree-with-dotted-ids (1.0.0)
activerecord (>= 3.0.0)
addressable (2.2.6)
arel (2.2.1)
barometer (0.7.3)
httparty (>= 0.4.5)
Expand Down Expand Up @@ -115,6 +124,10 @@ GEM
factory_girl_rails (1.3.0)
factory_girl (~> 2.2.0)
railties (>= 3.0.0)
faraday (0.7.5)
addressable (~> 2.2.6)
multipart-post (~> 1.1.3)
rack (< 2, >= 1.1.0)
fastercsv (1.5.4)
ffi (1.0.9)
forgery (0.5.0)
Expand All @@ -134,6 +147,7 @@ GEM
haml (~> 3.0)
railties (~> 3.0)
handles_sortable_columns (0.1.3)
hashie (1.2.0)
hike (1.2.1)
hpricot (0.8.4)
httparty (0.8.0)
Expand Down Expand Up @@ -167,13 +181,31 @@ GEM
text-table (~> 1.2)
multi_json (1.0.4)
multi_xml (0.4.1)
multipart-post (1.1.4)
mysql (2.8.1)
n_gram (0.0.1)
narray (0.6.0.1)
net-http-digest_auth (1.1.1)
net-http-persistent (1.9)
nifty-generators (0.4.6)
nokogiri (1.5.0)
oauth (0.4.5)
oauth2 (0.5.1)
faraday (~> 0.7.4)
multi_json (~> 1.0.3)
omniauth-facebook (1.1.0)
omniauth-oauth2 (~> 1.0.0)
omniauth-oauth (1.0.0)
oauth
omniauth (~> 1.0)
omniauth-oauth2 (1.0.0)
oauth2 (~> 0.5.0)
omniauth (~> 1.0)
omniauth-openid (1.0.1)
omniauth (~> 1.0)
rack-openid (~> 1.3.1)
omniauth-twitter (0.0.7)
omniauth-oauth (~> 1.0)
orm_adapter (0.0.5)
polyglot (0.3.3)
prawn (0.8.4)
Expand All @@ -191,6 +223,9 @@ GEM
rack (>= 0.4)
rack-mount (0.8.3)
rack (>= 1.0.0)
rack-openid (1.3.1)
rack (>= 1.1.0)
ruby-openid (>= 2.1.8)
rack-ssl (1.3.2)
rack
rack-test (0.6.1)
Expand Down Expand Up @@ -240,6 +275,7 @@ GEM
railties (~> 3.0)
rspec (~> 2.7.0)
ruby-ole (1.2.11.2)
ruby-openid (2.1.8)
ruby_parser (2.3.1)
sexp_processor (~> 3.0)
rubyvis (0.4.1)
Expand Down Expand Up @@ -292,7 +328,6 @@ GEM
multi_json (>= 1.0.2)
warden (1.0.5)
rack (>= 1.0)
web-app-theme (0.7.0)
webrobots (0.0.12)
nokogiri (>= 1.4.4)
will_paginate (3.0.2)
Expand Down Expand Up @@ -338,6 +373,10 @@ DEPENDENCIES
n_gram
narray
nifty-generators
omniauth!
omniauth-facebook
omniauth-openid
omniauth-twitter
rails (= 3.1)
rails-dev-tweaks
rails-settings-cached
Expand All @@ -352,7 +391,6 @@ DEPENDENCIES
subdomain-fu!
therubyracer
uglifier
web-app-theme
will_paginate
workflow
yaml_db
3 changes: 3 additions & 0 deletions app/assets/javascripts/services.js.coffee
@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
3 changes: 3 additions & 0 deletions app/assets/javascripts/signups.js.coffee
@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
3 changes: 3 additions & 0 deletions app/assets/stylesheets/services.css.scss
@@ -0,0 +1,3 @@
// Place all the styles related to the services controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
3 changes: 3 additions & 0 deletions app/assets/stylesheets/signups.css.scss
@@ -0,0 +1,3 @@
// Place all the styles related to the Signups controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
107 changes: 107 additions & 0 deletions app/controllers/services_controller.rb
@@ -0,0 +1,107 @@
class ServicesController < ApplicationController
skip_authorization_check :only => [:create]
def index
authorize! :manage_account, current_account
@services = current_account.services.all
end

def create
omniauth = request.env['omniauth.auth']
service_route = params[:service] || 'no service (invalid callback)'
unless omniauth and params[:service]
flash[:error] = 'Error while authenticating via ' + service_route.capitalize + '.'
redirect_to new_user_session_path and return
end
case service_route
when 'facebook'
email = omniauth['extra']['raw_info']['email']
name = omniauth['extra']['raw_info']['name']
uid = omniauth['extra']['raw_info']['id']
provider = omniauth['provider']
when 'twitter'
email = '' # Twitter API never returns the email address
name = omniauth['user_info']['name']
uid = omniauth['uid']
provider = omniauth['provider']
when 'google'
email = omniauth['info']['email']
name = omniauth['info']['name']
provider = omniauth['provider']
uid = omniauth['uid']
else
render :text => omniauth.to_yaml
return
end
if uid.blank? or provider.blank?
flash[:error] = service_route.capitalize + ' returned invalid data for the user id.'
redirect_to new_user_session_path and return
end
auth = Service.find_by_provider_and_uid(provider, uid)
if user_signed_in?
if !auth
current_account.services.create(:provider => provider, :uid => uid, :uname => name, :uemail => email)
flash[:notice] = 'Sign in via ' + provider.capitalize + ' has been added to your account.'
redirect_to services_path and return
else
flash[:notice] = service_route.capitalize + ' is already linked to your account.'
redirect_to services_path and return
end
end

if auth
flash[:notice] = 'Signed in successfully via ' + provider.capitalize + '.'
sign_in_and_redirect(:user, auth.user)
else
# check if this user is already registered with this email address; get out if no email has been provided
if !email.blank?
# search for a user with this email address
existing_user = User.find_by_email(email)
if existing_user
# map this new login method via a service provider to an existing account if the email address is the same
existing_user.services.create(:provider => provider, :uid => uid, :uname => name, :uemail => email)
flash[:notice] = 'Sign in via ' + provider.capitalize + ' has been added to your account ' + existing_user.email + '. Signed in successfully!'
sign_in_and_redirect(:user, existing_user)
elsif Devise.mappings[:user].registerable?
# let's create a new user: register this user and add this authentication method for this user
name = name[0, 39] if name.length > 39 # otherwise our user validation will hit us
# new user, set email, a random password and take the name from the authentication service
user = User.new :email => email, :password => SecureRandom.hex(10), :fullname => name, :username => name
# add this authentication service to our new user
user.services.build(:provider => provider, :uid => uid, :uname => name, :uemail => email)

# do not send confirmation email, we directly save and confirm the new record
user.skip_confirmation!
user.save!
user.confirm!

# flash and sign in
flash[:notice] = 'Your account on Quantified Awesome has been created via ' + provider.capitalize + '. In your profile you can change your personal information and add a local password.'
sign_in_and_redirect(:user, user)
else
# Not accepting new users yet
signup = Signup.find_by_email(email)
if signup
flash[:notice] = "Thanks! Still not ready to take on new users, but you're still on the list!"
redirect_to root_path and return
else
signup = Signup.create(:email => email)
flash[:notice] = "Thanks for your interest! When Quantified Awesome is ready for new users, I'll get in touch!"
redirect_to root_path and return
end
end
else
flash[:error] = service_route.capitalize + ' can not be used to sign-up on Quantified Awesome as no valid email address has been provided. Please use another authentication provider or use local sign-up. If you already have an account, please sign-in and add ' + service_route.capitalize + ' from your profile.'
redirect_to new_user_session_path and return
end
end
end

def destroy
authorize! :manage_account, current_account
# remove an authentication service linked to the current user
@service = current_account.services.find(params[:id])
@service.destroy

redirect_to services_path
end
end
8 changes: 8 additions & 0 deletions app/controllers/signups_controller.rb
@@ -0,0 +1,8 @@
class SignupsController < ApplicationController
respond_to :html, :json
def index
authorize! :manage, User
@list = Signup.order('created_at DESC')
respond_with @list
end
end
2 changes: 2 additions & 0 deletions app/helpers/services_helper.rb
@@ -0,0 +1,2 @@
module ServicesHelper
end
2 changes: 2 additions & 0 deletions app/helpers/signups_helper.rb
@@ -0,0 +1,2 @@
module SignupsHelper
end
4 changes: 4 additions & 0 deletions app/models/service.rb
@@ -0,0 +1,4 @@
class Service < ActiveRecord::Base
belongs_to :user
attr_accessible :provider, :uid, :uname, :uemail
end
1 change: 1 addition & 0 deletions app/models/user.rb
Expand Up @@ -20,6 +20,7 @@ class User < ActiveRecord::Base
has_many :tap_log_records
has_many :record_categories
has_many :records
has_many :services, :dependent => :destroy
has_one :time_tracker_log

validates :username, :exclusion => { :in => %w(admin superuser root www) }
Expand Down
7 changes: 6 additions & 1 deletion app/views/sessions/new.html.haml
Expand Up @@ -19,10 +19,15 @@
%label
= f.check_box :remember_me, :class => "checkbox"
Remember me
.clear-fix
.input
.box#services
= link_to image_tag('google_32.png', :size => "32x32", :alt => "Google"), '/auth/google', :class => 'service'
= link_to image_tag('facebook_32.png', :size => "32x32", :alt => "Facebook"), '/auth/facebook', :class => 'service'
.actions
%button.btn.primary{ :type => "submit" }
= I18n.t('app.user.login_submit')
= render :partial => "devise/shared/links"
= render "devise/shared/links"
.sign_up.span8
= form_tag sign_up_path do
%fieldset
Expand Down
10 changes: 10 additions & 0 deletions app/views/signups/index.html.haml
@@ -0,0 +1,10 @@
%table
%thead
%th Email
%th Date
%tbody
- @list.each do |s|
%tr
%td= mail_to s.email, s.email
%td= l s.created_at

6 changes: 6 additions & 0 deletions config/initializers/omniauth.rb
@@ -0,0 +1,6 @@
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, '297651176946994', '919210cdc875604ddee892f4a083b84c'
provider :twitter, '781510-F2ITvgEb4a8qG0aDKZo9oSCHOSZ2UPHD6thfjKkcX8', 'XIw7FXIt1EyRimxBaoSG7kShztyMeMwZ18ZZxMh5lM'
require 'openid/store/filesystem'
provider :open_id, :store => OpenID::Store::Filesystem.new('/tmp'), :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id', :require => 'omniauth-openid'
end
3 changes: 3 additions & 0 deletions config/routes.rb
@@ -1,4 +1,7 @@
Home::Application.routes.draw do
match '/auth/:service/callback' => 'services#create'
resources :services, :only => [:index, :create, :destroy]
match 'signups' => 'signups#index'
resources :records do
member do
post :clone
Expand Down
13 changes: 13 additions & 0 deletions db/migrate/20111226164500_create_services.rb
@@ -0,0 +1,13 @@
class CreateServices < ActiveRecord::Migration
def change
create_table :services do |t|
t.integer :user_id
t.string :provider
t.string :uid
t.string :uname
t.string :uemail

t.timestamps
end
end
end
14 changes: 13 additions & 1 deletion db/schema.rb
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended to check this file into your version control system.

ActiveRecord::Schema.define(:version => 20111225133526) do
ActiveRecord::Schema.define(:version => 20111226164500) do

create_table "clothing", :force => true do |t|
t.string "name"
Expand Down Expand Up @@ -263,6 +263,16 @@
add_index "records", ["record_category_id"], :name => "index_records_on_record_category_id"
add_index "records", ["timestamp"], :name => "index_records_on_timestamp"

create_table "services", :force => true do |t|
t.integer "user_id"
t.string "provider"
t.string "uid"
t.string "uname"
t.string "uemail"
t.datetime "created_at"
t.datetime "updated_at"
end

create_table "settings", :force => true do |t|
t.string "var", :null => false
t.text "value"
Expand Down Expand Up @@ -349,6 +359,8 @@
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
t.datetime "end_timestamp"
t.string "entry_type"
end

add_index "time_records", ["user_id"], :name => "index_time_records_on_user_id"
Expand Down
4 changes: 4 additions & 0 deletions public/stylesheets/mobile.css
@@ -0,0 +1,4 @@
/* line 1, ../../app/assets/stylesheets/mobile.sass */
.container {
width: auto;
}
Empty file.
Empty file.
5 changes: 5 additions & 0 deletions spec/controllers/services_controller_spec.rb
@@ -0,0 +1,5 @@
require 'spec_helper'

describe ServicesController do

end
5 changes: 5 additions & 0 deletions spec/controllers/signups_controller_spec.rb
@@ -0,0 +1,5 @@
require 'spec_helper'

describe SignupsController do

end

0 comments on commit 196d592

Please sign in to comment.