From 13c2ac5cdb7e5beddf80b90b0357b9961e12033f Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Sun, 14 Aug 2016 18:30:13 +0100 Subject: [PATCH] Reorder auth_success handlers Only treat auth_success as a possible login attempt if we're not in the middle of validating a new user, or a change to a user. Also validate the uniqueness of external auth credentials at the rails level rather than just at the database level, and make sure any errors are properly reported. Fixes #1265 --- app/controllers/user_controller.rb | 52 +++++++++++++++++------------- app/models/user.rb | 2 ++ 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index e5515f727..c8abb4d85 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -131,6 +131,10 @@ class UserController < ApplicationController session[:new_user_settings] = params redirect_to auth_url(params[:user][:auth_provider], params[:user][:auth_uid]) end + elsif errors = session.delete(:user_errors) + errors.each do |attribute, error| + @user.errors.add(attribute, error) + end end end @@ -501,31 +505,14 @@ class UserController < ApplicationController email_verified = false end - user = User.find_by_auth_provider_and_auth_uid(provider, uid) - - if user.nil? && provider == "google" - openid_url = auth_info[:extra][:id_info]["openid_id"] - user = User.find_by_auth_provider_and_auth_uid("openid", openid_url) if openid_url - user.update(:auth_provider => provider, :auth_uid => uid) if user - end - - if user - case user.status - when "pending" then - unconfirmed_login(user) - when "active", "confirmed" then - successful_login(user, env["omniauth.params"]["referer"]) - when "suspended" then - failed_login t("user.login.account is suspended", :webmaster => "mailto:#{SUPPORT_EMAIL}") - else - failed_login t("user.login.auth failure") - end - elsif settings = session.delete(:new_user_settings) + if settings = session.delete(:new_user_settings) @user.auth_provider = provider @user.auth_uid = uid update_user(@user, settings) + session[:user_errors] = @user.errors.as_json + redirect_to :action => "account", :display_name => @user.display_name elsif session[:new_user] session[:new_user].auth_provider = provider @@ -537,8 +524,29 @@ class UserController < ApplicationController redirect_to :action => "terms" else - redirect_to :action => "new", :nickname => name, :email => email, - :auth_provider => provider, :auth_uid => uid + user = User.find_by_auth_provider_and_auth_uid(provider, uid) + + if user.nil? && provider == "google" + openid_url = auth_info[:extra][:id_info]["openid_id"] + user = User.find_by_auth_provider_and_auth_uid("openid", openid_url) if openid_url + user.update(:auth_provider => provider, :auth_uid => uid) if user + end + + if user + case user.status + when "pending" then + unconfirmed_login(user) + when "active", "confirmed" then + successful_login(user, env["omniauth.params"]["referer"]) + when "suspended" then + failed_login t("user.login.account is suspended", :webmaster => "mailto:#{SUPPORT_EMAIL}") + else + failed_login t("user.login.auth failure") + end + else + redirect_to :action => "new", :nickname => name, :email => email, + :auth_provider => provider, :auth_uid => uid + end end end diff --git a/app/models/user.rb b/app/models/user.rb index e255dc216..a550b9f05 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -52,6 +52,8 @@ class User < ActiveRecord::Base validates :home_zoom, :allow_nil => true, :numericality => { :only_integer => true } validates :preferred_editor, :inclusion => Editors::ALL_EDITORS, :allow_nil => true validates :image, :attachment_content_type => { :content_type => %r{\Aimage/.*\Z} } + validates :auth_uid, :unless => proc { |u| u.auth_provider.nil? }, + :uniqueness => { :scope => :auth_provider } validates_email_format_of :email, :if => proc { |u| u.email_changed? } validates_email_format_of :new_email, :allow_blank => true, :if => proc { |u| u.new_email_changed? } -- 2.39.5