user deletions: fix error when given incorrect password.

Use validations instead of raising an exception when the password is
incorrect so that the controller can display errors sensibly.

Also fix users being logged out even when the deletion attempt failed
due to an incorrect password.
This commit is contained in:
evazion
2020-04-03 23:36:27 -05:00
parent 53b761dfe9
commit 8134e92457
4 changed files with 36 additions and 18 deletions

View File

@@ -1,14 +1,23 @@
module Maintenance module Maintenance
module User module User
class DeletionsController < ApplicationController class DeletionsController < ApplicationController
respond_to :html, :json, :xml
def show def show
end end
def destroy def destroy
deletion = UserDeletion.new(CurrentUser.user, params.dig(:user, :password)) deletion = UserDeletion.new(CurrentUser.user, params.dig(:user, :password))
deletion.delete! deletion.delete!
session.delete(:user_id)
redirect_to(posts_path, :notice => "You are now logged out") if deletion.errors.none?
session.delete(:user_id)
flash[:notice] = "Your account has been deactivated"
respond_with(deletion, location: posts_path)
else
flash[:notice] = deletion.errors.full_messages.join("; ")
redirect_to maintenance_user_deletion_path
end
end end
end end
end end

View File

@@ -1,7 +1,8 @@
class UserDeletion class UserDeletion
class ValidationError < StandardError; end include ActiveModel::Validations
attr_reader :user, :password attr_reader :user, :password
validate :validate_deletion
def initialize(user, password) def initialize(user, password)
@user = user @user = user
@@ -9,13 +10,14 @@ class UserDeletion
end end
def delete! def delete!
validate return false if invalid?
clear_user_settings clear_user_settings
remove_favorites remove_favorites
clear_saved_searches clear_saved_searches
rename rename
reset_password reset_password
create_mod_action create_mod_action
user
end end
private private
@@ -56,13 +58,13 @@ class UserDeletion
request.save!(validate: false) # XXX don't validate so that the 1 name change per week rule doesn't interfere request.save!(validate: false) # XXX don't validate so that the 1 name change per week rule doesn't interfere
end end
def validate def validate_deletion
if !user.authenticate_password(password) if !user.authenticate_password(password)
raise ValidationError.new("Password is incorrect") errors[:base] << "Password is incorrect"
end end
if user.level >= User::Levels::ADMIN if user.level >= User::Levels::ADMIN
raise ValidationError.new("Admins cannot delete their account") errors[:base] << "Admins cannot delete their account"
end end
end end
end end

View File

@@ -16,9 +16,20 @@ module Maintenance
end end
context "#destroy" do context "#destroy" do
should "render" do should "delete the user when given the correct password" do
delete_auth maintenance_user_deletion_path, @user, params: {:password => "password"} delete_auth maintenance_user_deletion_path, @user, params: { user: { password: "password" }}
assert_redirected_to(posts_path) assert_redirected_to posts_path
assert_equal(true, @user.reload.is_deleted?)
assert_equal("Your account has been deactivated", flash[:notice])
assert_nil(session[:user_id])
end
should "not delete the user when given an incorrect password" do
delete_auth maintenance_user_deletion_path, @user, params: { user: { password: "hunter2" }}
assert_redirected_to maintenance_user_deletion_path
assert_equal(false, @user.reload.is_deleted?)
assert_equal("Password is incorrect", flash[:notice])
assert_equal(@user.id, session[:user_id])
end end
end end
end end

View File

@@ -6,10 +6,8 @@ class UserDeletionTest < ActiveSupport::TestCase
should "fail" do should "fail" do
@user = create(:user) @user = create(:user)
@deletion = UserDeletion.new(@user, "wrongpassword") @deletion = UserDeletion.new(@user, "wrongpassword")
@deletion.delete!
assert_raise(UserDeletion::ValidationError) do assert_includes(@deletion.errors[:base], "Password is incorrect")
@deletion.delete!
end
end end
end end
@@ -17,10 +15,8 @@ class UserDeletionTest < ActiveSupport::TestCase
should "fail" do should "fail" do
@user = create(:admin_user) @user = create(:admin_user)
@deletion = UserDeletion.new(@user, "password") @deletion = UserDeletion.new(@user, "password")
@deletion.delete!
assert_raise(UserDeletion::ValidationError) do assert_includes(@deletion.errors[:base], "Admins cannot delete their account")
@deletion.delete!
end
end end
end end
end end