+ else
+ #The redirect from the OpenID provider reenters here again
+ #and we need to pass the parameters through to the
+ #open_id_authentication function
+ if params[:open_id_complete]
+ openid_verify('', true)
+ redirect_to :action => 'login'
+ return
+ end
+
+ @user = User.new(params[:user])
+
+ @user.visible = true
+ @user.data_public = true
+ @user.description = "" if @user.description.nil?
+ @user.creation_ip = request.remote_ip
+ @user.languages = request.user_preferred_languages
+
+ if @user.save
+ flash[:notice] = t 'user.new.flash create success message'
+ Notifier.deliver_signup_confirm(@user, @user.tokens.create(:referer => params[:referer]))
+ if (params[:user][:openid_url].length > 0)
+ begin
+ session[:new_usr_name] = @user.display_name
+ @norm_openid_url = OpenIdAuthentication.normalize_identifier(params[:user][:openid_url])
+ #TODO: error messages in the openid_verify aren't correctly returned yet
+ openid_verify(@norm_openid_url, true)
+ #Will have sent the redirect_to in the if open_id_complete section of this method
+ rescue
+ flash.now[:error] = t 'user.login.openid invalid'
+ end
+ else
+ redirect_to :action => 'login'
+ end
+ else
+ render :action => 'new'
+ end
+ end
+ end
+
+ def account
+ @title = t 'user.account.title'
+ @tokens = @user.oauth_tokens.find :all, :conditions => 'oauth_tokens.invalidated_at is null and oauth_tokens.authorized_at is not null'
+
+ #The redirect from the OpenID provider reenters here again
+ #and we need to pass the parameters through to the
+ #open_id_authentication function
+ if params[:open_id_complete]
+ openid_verify('', false)
+ return
+ end
+
+ if params[:user] and params[:user][:display_name] and params[:user][:description]
+ if params[:user][:email] != @user.email
+ @user.new_email = params[:user][:email]
+ end
+
+ @user.display_name = params[:user][:display_name]
+
+ if params[:user][:pass_crypt].length > 0 or params[:user][:pass_crypt_confirmation].length > 0
+ @user.pass_crypt = params[:user][:pass_crypt]
+ @user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
+ end
+ if (params[:user][:openid_url].length == 0)
+ #Clearing doesn't need OpenID validation, so we can set it here.
+ @user.openid_url = nil
+ end
+
+ @user.description = params[:user][:description]
+ @user.languages = params[:user][:languages].split(",")
+ @user.home_lat = params[:user][:home_lat]
+ @user.home_lon = params[:user][:home_lon]
+
+ if @user.save
+ set_locale
+
+ if params[:user][:email] == @user.new_email
+ flash.now[:notice] = t 'user.account.flash update success confirm needed'
+ Notifier.deliver_email_confirm(@user, @user.tokens.create)
+ else
+ flash.now[:notice] = t 'user.account.flash update success'
+ end
+ end
+
+ if (params[:user][:openid_url].length > 0)
+ begin
+ @norm_openid_url = OpenIdAuthentication.normalize_identifier(params[:user][:openid_url])
+ if (@norm_openid_url != @user.openid_url)
+ #If the OpenID has changed, we want to check that it is a valid OpenID and one
+ #the user has control over before saving the openID as a password equivalent for
+ #the user.
+ openid_verify(@norm_openid_url, false)
+ end
+ rescue
+ flash.now[:error] = t 'user.login.openid invalid'
+ end
+ end
+ end
+ end
+
+ def openid_specialcase_mapping(openid_url)
+ #Special case gmail.com, as it is pontentially a popular OpenID provider and unlike
+ #yahoo.com, where it works automatically, Google have hidden their OpenID endpoint
+ #somewhere obscure making it less userfriendly.
+ if (openid_url.match(/(.*)gmail.com(\/?)$/) or openid_url.match(/(.*)googlemail.com(\/?)$/) )
+ return 'https://www.google.com/accounts/o8/id'
+ end
+
+ return nil
+ end
+
+ def openid_verify(openid_url,account_create)
+ authenticate_with_open_id(openid_url) do |result, identity_url|
+ if result.successful?
+ #We need to use the openid url passed back from the OpenID provider
+ #rather than the one supplied by the user, as these can be different.
+ #e.g. one can simply enter yahoo.com in the login box, i.e. no user specific url
+ #only once it comes back from the OpenID provider do we know the unique address for
+ #the user.
+ @user = User.find_by_display_name(session[:new_usr_name]) unless @user
+ @user.openid_url = identity_url
+ if @user.save
+ flash.now[:notice] = t 'user.account.flash update success' unless account_create
+ end
+ else if result.missing?
+ mapped_id = openid_specialcase_mapping(openid_url)
+ if mapped_id
+ openid_verify(mapped_id, account_create)
+ else
+ flash.now[:error] = t 'user.login.openid missing provider'
+ end
+ else if result.invalid?
+ flash.now[:error] = t 'user.login.openid invalid'
+ else
+ flash.now[:error] = t 'user.login.auth failure'
+ end
+ end
+ end
+ end
+ end
+
+
+ def set_home
+ if params[:user][:home_lat] and params[:user][:home_lon]
+ @user.home_lat = params[:user][:home_lat].to_f
+ @user.home_lon = params[:user][:home_lon].to_f
+ if @user.save
+ flash[:notice] = t 'user.set_home.flash success'
+ redirect_to :controller => 'user', :action => 'account'
+ end
+ end
+ end
+
+ def go_public
+ @user.data_public = true
+ @user.save
+ flash[:notice] = t 'user.go_public.flash success'
+ redirect_to :controller => 'user', :action => 'account', :display_name => @user.display_name
+ end
+
+ def lost_password
+ @title = t 'user.lost_password.title'
+
+ if params[:user] and params[:user][:email]
+ user = User.find_by_email(params[:user][:email], :conditions => {:visible => true})
+
+ if user
+ token = user.tokens.create
+ Notifier.deliver_lost_password(user, token)
+ flash.now[:notice] = t 'user.lost_password.notice email on way'
+ else
+ flash.now[:error] = t 'user.lost_password.notice email cannot find'
+ end
+ end
+ end
+
+ def reset_password
+ @title = t 'user.reset_password.title'
+
+ if params[:token]
+ token = UserToken.find_by_token(params[:token])
+
+ if token
+ @user = token.user
+
+ if params[:user]
+ @user.pass_crypt = params[:user][:pass_crypt]
+ @user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
+ @user.active = true
+ @user.email_valid = true
+
+ if @user.save
+ token.destroy
+ flash[:notice] = t 'user.reset_password.flash changed'
+ redirect_to :action => 'login'
+ end
+ end
+ else
+ flash[:error] = t 'user.reset_password.flash token bad'
+ redirect_to :action => 'lost_password'
+ end