2013-02-05 14:16:51 -05:00
require 'openid'
require 'openid/extensions/sreg'
require 'openid/extensions/ax'
require 'openid/store/filesystem'
require_dependency 'email'
class UserOpenIdsController < ApplicationController
2013-02-07 16:45:24 +01:00
layout false
2013-02-05 14:16:51 -05:00
# need to be able to call this
2013-02-07 16:45:24 +01:00
skip_before_filter :check_xhr
# must be done, cause we may trigger a POST
2013-02-05 14:16:51 -05:00
skip_before_filter :verify_authenticity_token , :only = > :complete
def frame
if params [ :provider ] == 'google'
params [ :user_open_id ] = { url : " https://www.google.com/accounts/o8/id " }
end
if params [ :provider ] == 'yahoo'
params [ :user_open_id ] = { url : " https://me.yahoo.com " }
end
create
end
def destroy
2013-02-07 16:45:24 +01:00
@open_id = UserOpenId . find ( params [ :id ] )
2013-02-05 14:16:51 -05:00
if @open_id . user . id == current_user . id
2013-02-07 16:45:24 +01:00
@open_id . destroy
2013-02-05 14:16:51 -05:00
end
redirect_to current_user
end
def new
@open_id = UserOpenId . new
end
def create
url = params [ :user_open_id ]
2013-02-07 16:45:24 +01:00
begin
# validations
@open_id = UserOpenId . new ( url )
2013-02-05 14:16:51 -05:00
open_id_request = openid_consumer . begin @open_id . url
2013-02-07 16:45:24 +01:00
return_to , realm = [ 'complete' , 'index' ] . map { | a | url_for :action = > a , :only_path = > false }
add_ax_request ( open_id_request )
add_sreg_request ( open_id_request )
2013-02-05 14:16:51 -05:00
2013-02-07 16:45:24 +01:00
# immediate mode is not required
2013-02-05 14:16:51 -05:00
if open_id_request . send_redirect? ( realm , return_to , false )
redirect_to open_id_request . redirect_url ( realm , return_to , false )
2013-02-07 16:45:24 +01:00
else
2013-02-05 14:16:51 -05:00
logger . warn ( " send_redirect? returned false " )
render :text , open_id_request . html_markup ( realm , return_to , false , { 'id' = > 'openid_form' } )
end
rescue = > e
2013-02-07 16:45:24 +01:00
flash [ :error ] = " There seems to be something wrong with your open id url "
logger . warn ( " failed to load contact open id: " + e . to_s )
2013-02-05 14:16:51 -05:00
render :text = > 'Something went wrong, we have been notified, try again soon'
end
end
def complete
current_url = url_for ( :action = > 'complete' , :only_path = > false )
parameters = params . reject { | k , v | request . path_parameters [ k ] } . reject { | k , v | k == 'action' || k == 'controller' }
open_id_response = openid_consumer . complete ( parameters , current_url )
2013-02-07 16:45:24 +01:00
2013-02-05 14:16:51 -05:00
case open_id_response . status
when OpenID :: Consumer :: SUCCESS
2013-02-07 16:45:24 +01:00
data = { }
2013-02-05 14:16:51 -05:00
if params [ :did_sreg ]
2013-02-07 16:45:24 +01:00
data = get_sreg_response ( open_id_response )
2013-02-05 14:16:51 -05:00
end
if params [ :did_ax ]
info = get_ax_response ( open_id_response )
data . merge! ( info )
end
trusted = open_id_response . endpoint . server_url =~ / ^https: \/ \/ www.google.com \/ / ||
2013-02-07 16:45:24 +01:00
open_id_response . endpoint . server_url =~ / ^https: \/ \/ me.yahoo.com \/ /
2013-02-05 14:16:51 -05:00
email = data [ :email ]
2013-02-07 16:45:24 +01:00
user_open_id = UserOpenId . where ( url : open_id_response . display_identifier ) . first
2013-02-05 14:16:51 -05:00
if trusted && user_open_id . nil? && user = User . where ( email : email ) . first
# we trust so do an email lookup
user_open_id = UserOpenId . create ( url : open_id_response . display_identifier , user_id : user . id , email : email , active : true )
end
2013-02-07 16:45:24 +01:00
2013-02-05 14:16:51 -05:00
authenticated = ! user_open_id . nil?
if authenticated
2013-02-07 16:45:24 +01:00
user = user_open_id . user
2013-02-05 14:16:51 -05:00
# If we have to approve users
if SiteSetting . must_approve_users? and ! user . approved?
@data = { awaiting_approval : true }
else
log_on_user ( user )
@data = { authenticated : true }
end
2013-02-07 16:45:24 +01:00
else
2013-02-05 14:16:51 -05:00
@data = {
email : email ,
2013-02-07 16:45:24 +01:00
name : User . suggest_name ( email ) ,
2013-02-05 14:16:51 -05:00
username : User . suggest_username ( email ) ,
email_valid : trusted ,
auth_provider : " Google "
}
session [ :authentication ] = {
email : @data [ :email ] ,
email_valid : @data [ :email_valid ] ,
openid_url : open_id_response . display_identifier
2013-02-07 16:45:24 +01:00
}
2013-02-05 14:16:51 -05:00
end
2013-02-07 16:45:24 +01:00
else
# note there are lots of failure reasons, we treat them all as failures
2013-02-05 14:16:51 -05:00
logger . warn ( " Verification #{ open_id_response . display_identifier || " " } " \
" failed: #{ open_id_response . status . to_s } " )
logger . warn ( open_id_response . message )
2013-02-07 16:45:24 +01:00
flash [ :error ] = " Sorry, I seem to be having trouble confirming your open id account, please try again! "
render :text = > " Apologies, something went wrong ... try again soon "
end
2013-02-05 14:16:51 -05:00
end
2013-02-07 16:45:24 +01:00
protected
2013-02-05 14:16:51 -05:00
2013-02-07 16:45:24 +01:00
def persist_session
2013-02-05 14:16:51 -05:00
if s = UserSession . find
s . remember_me = true
s . save
end
end
def openid_consumer
2013-02-07 16:45:24 +01:00
@openid_consumer || = OpenID :: Consumer . new ( session ,
2013-02-05 14:16:51 -05:00
OpenID :: Store :: Filesystem . new ( " #{ Rails . root } /tmp/openid " ) )
end
def get_sreg_response ( open_id_response )
2013-02-07 16:45:24 +01:00
data = { }
2013-02-05 14:16:51 -05:00
sreg_resp = OpenID :: SReg :: Response . from_success_response ( open_id_response )
unless sreg_resp . empty?
data [ :email ] = sreg_resp . data [ 'email' ]
2013-02-07 16:45:24 +01:00
data [ :nickname ] = sreg_resp . data [ 'nickname' ]
2013-02-05 14:16:51 -05:00
end
data
end
def get_ax_response ( open_id_response )
data = { }
ax_resp = OpenID :: AX :: FetchResponse . from_success_response ( open_id_response )
if ax_resp && ! ax_resp . data . empty?
2013-02-07 16:45:24 +01:00
data [ :email ] = ax_resp . data [ 'http://schema.openid.net/contact/email' ] [ 0 ]
2013-02-05 14:16:51 -05:00
end
2013-02-07 16:45:24 +01:00
data
2013-02-05 14:16:51 -05:00
end
2013-02-07 16:45:24 +01:00
def add_sreg_request ( open_id_request )
2013-02-05 14:16:51 -05:00
sreg_request = OpenID :: SReg :: Request . new
sreg_request . request_fields ( [ 'email' ] , true )
2013-02-07 16:45:24 +01:00
# optional
2013-02-05 14:16:51 -05:00
sreg_request . request_fields ( [ 'dob' , 'fullname' , 'nickname' ] , false )
open_id_request . add_extension ( sreg_request )
open_id_request . return_to_args [ 'did_sreg' ] = 'y'
end
def add_ax_request ( open_id_request )
2013-02-07 16:45:24 +01:00
ax_request = OpenID :: AX :: FetchRequest . new
requested_attrs = [
2013-02-05 14:16:51 -05:00
[ 'namePerson' , 'fullname' ] ,
[ 'namePerson/friendly' , 'nickname' ] ,
[ 'contact/email' , 'email' , true ] ,
[ 'contact/web/default' , 'web_default' ] ,
[ 'birthDate' , 'dob' ] ,
2013-02-07 16:45:24 +01:00
[ 'contact/country/home' , 'country' ]
2013-02-05 14:16:51 -05:00
]
requested_attrs . each { | a | ax_request . add ( OpenID :: AX :: AttrInfo . new ( " http://schema.openid.net/ #{ a [ 0 ] } " , a [ 1 ] , a [ 2 ] || false ) ) }
open_id_request . add_extension ( ax_request )
open_id_request . return_to_args [ 'did_ax' ] = 'y'
end
end