diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index abb5b212a..2cd93c9aa 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -205,13 +205,17 @@ class UsersController < ApplicationController def password_reset expires_now() - @user = EmailToken.confirm(params[:token]) + if EmailToken.valid_token_format?(params[:token]) + @user = EmailToken.confirm(params[:token]) - if @user - session[params[:token]] = @user.id + if @user + session["password-#{params[:token]}"] = @user.id + else + user_id = session["password-#{params[:token]}"] + @user = User.find(user_id) if user_id + end else - user_id = session[params[:token]] - @user = User.find(user_id) if user_id + @invalid_token = true end if !@user diff --git a/app/models/email_token.rb b/app/models/email_token.rb index 66ac9112d..ff8494378 100644 --- a/app/models/email_token.rb +++ b/app/models/email_token.rb @@ -39,9 +39,12 @@ class EmailToken < ActiveRecord::Base SecureRandom.hex(EmailToken.token_length) end + def self.valid_token_format?(token) + return token.present? && token =~ /[a-f0-9]{#{token.length/2}}/i + end + def self.confirm(token) - return unless token.present? - return unless token.length/2 == EmailToken.token_length + return unless valid_token_format?(token) email_token = EmailToken.where("token = ? and expired = FALSE AND ((NOT confirmed AND created_at >= ?) OR (confirmed AND created_at >= ?))", token, EmailToken.valid_after, EmailToken.confirm_valid_after).includes(:user).first return if email_token.blank? diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 832789326..053eb2391 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -243,7 +243,7 @@ describe UsersController do end end - context 'invalid token' do + context 'missing token' do before do get :password_reset, token: SecureRandom.hex end @@ -251,9 +251,22 @@ describe UsersController do it 'disallows login' do flash[:error].should be_present session[:current_user_id].should be_blank + assigns[:invalid_token].should be_nil response.should be_success end + end + context 'invalid token' do + before do + get :password_reset, token: "evil_trout!" + end + + it 'disallows login' do + flash[:error].should be_present + session[:current_user_id].should be_blank + assigns[:invalid_token].should be_true + response.should be_success + end end context 'valid token' do @@ -269,18 +282,19 @@ describe UsersController do end context 'submit change' do + let(:token) { EmailToken.generate_token } before do - EmailToken.expects(:confirm).with('asdfasdf').returns(user) + EmailToken.expects(:confirm).with(token).returns(user) end it "logs in the user" do - put :password_reset, token: 'asdfasdf', password: 'newpassword' + put :password_reset, token: token, password: 'newpassword' session[:current_user_id].should be_present end it "doesn't log in the user when not approved" do SiteSetting.expects(:must_approve_users?).returns(true) - put :password_reset, token: 'asdfasdf', password: 'newpassword' + put :password_reset, token: token, password: 'newpassword' session[:current_user_id].should be_blank end end