add a way to delete posts and topics when deleting a user with UserDestroyer
This commit is contained in:
parent
a8df9778b5
commit
e25638dab0
|
@ -117,11 +117,15 @@ class Admin::UsersController < Admin::AdminController
|
|||
def destroy
|
||||
user = User.where(id: params[:id]).first
|
||||
guardian.ensure_can_delete_user!(user)
|
||||
if UserDestroyer.new(current_user).destroy(user)
|
||||
begin
|
||||
if UserDestroyer.new(current_user).destroy(user, params.slice(:delete_posts))
|
||||
render json: {deleted: true}
|
||||
else
|
||||
render json: {deleted: false, user: AdminDetailedUserSerializer.new(user, root: false).as_json}
|
||||
end
|
||||
rescue UserDestroyer::PostsExistError
|
||||
raise Discourse::InvalidAccess.new("User #{user.username} has #{user.post_count} posts, so can't be deleted.")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -150,8 +150,8 @@ class Guardian
|
|||
user && is_staff?
|
||||
end
|
||||
|
||||
def can_delete_user?(user_to_delete)
|
||||
can_administer?(user_to_delete) && user_to_delete.post_count <= 0
|
||||
def can_delete_user?(user)
|
||||
can_administer?(user)
|
||||
end
|
||||
|
||||
# Can we see who acted on a post in a particular way?
|
||||
|
|
|
@ -11,10 +11,16 @@ class UserDestroyer
|
|||
|
||||
# Returns false if the user failed to be deleted.
|
||||
# Returns a frozen instance of the User if the delete succeeded.
|
||||
def destroy(user)
|
||||
def destroy(user, opts={})
|
||||
raise Discourse::InvalidParameters.new('user is nil') unless user and user.is_a?(User)
|
||||
raise PostsExistError if user.post_count != 0
|
||||
raise PostsExistError if !opts[:delete_posts] && user.post_count != 0
|
||||
User.transaction do
|
||||
if opts[:delete_posts]
|
||||
user.posts.each do |post|
|
||||
PostDestroyer.new(@admin, post).destroy
|
||||
end
|
||||
raise PostsExistError if user.reload.post_count != 0
|
||||
end
|
||||
user.destroy.tap do |u|
|
||||
if u
|
||||
Post.with_deleted.where(user_id: user.id).update_all("nuked_user = true")
|
||||
|
|
|
@ -1008,9 +1008,9 @@ describe Guardian do
|
|||
end
|
||||
|
||||
context "for admins" do
|
||||
it "is false if user has posts" do
|
||||
Fabricate(:post, user: user)
|
||||
Guardian.new(admin).can_delete_user?(user).should be_false
|
||||
it "is true if user has posts" do # UserDestroyer is responsible for checking for posts
|
||||
user.stubs(:post_count).returns(1)
|
||||
Guardian.new(admin).can_delete_user?(user).should be_true
|
||||
end
|
||||
|
||||
it "is true if user has no posts" do
|
||||
|
|
|
@ -35,8 +35,6 @@ describe UserDestroyer do
|
|||
@user = Fabricate(:user)
|
||||
end
|
||||
|
||||
subject(:destroy) { UserDestroyer.new(@admin).destroy(@user) }
|
||||
|
||||
it 'raises an error when user is nil' do
|
||||
expect { UserDestroyer.new(@admin).destroy(nil) }.to raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
|
@ -45,32 +43,7 @@ describe UserDestroyer do
|
|||
expect { UserDestroyer.new(@admin).destroy('nothing') }.to raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
|
||||
context 'user has posts' do
|
||||
before do
|
||||
Fabricate(:post, user: @user)
|
||||
end
|
||||
|
||||
it 'should not delete the user' do
|
||||
expect { destroy rescue nil }.to_not change { User.count }
|
||||
end
|
||||
|
||||
it 'should raise an error' do
|
||||
expect { destroy }.to raise_error( UserDestroyer::PostsExistError )
|
||||
end
|
||||
|
||||
it 'should not log the action' do
|
||||
StaffActionLogger.any_instance.expects(:log_user_deletion).never
|
||||
destroy rescue nil
|
||||
end
|
||||
|
||||
it 'should not unregister the user at the discourse hub' do
|
||||
DiscourseHub.expects(:unregister_nickname).never
|
||||
destroy rescue nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'user has no posts' do
|
||||
context 'and destroy succeeds' do
|
||||
shared_examples "successfully destroy a user" do
|
||||
it 'should delete the user' do
|
||||
expect { destroy }.to change { User.count }.by(-1)
|
||||
end
|
||||
|
@ -97,6 +70,52 @@ describe UserDestroyer do
|
|||
DiscourseHub.expects(:unregister_nickname).never
|
||||
destroy
|
||||
end
|
||||
end
|
||||
|
||||
context 'user has posts' do
|
||||
let!(:post) { Fabricate(:post, user: @user) }
|
||||
|
||||
context "delete_posts is false" do
|
||||
subject(:destroy) { UserDestroyer.new(@admin).destroy(@user) }
|
||||
|
||||
it 'should not delete the user' do
|
||||
expect { destroy rescue nil }.to_not change { User.count }
|
||||
end
|
||||
|
||||
it 'should raise an error' do
|
||||
expect { destroy }.to raise_error( UserDestroyer::PostsExistError )
|
||||
end
|
||||
|
||||
it 'should not log the action' do
|
||||
StaffActionLogger.any_instance.expects(:log_user_deletion).never
|
||||
destroy rescue nil
|
||||
end
|
||||
|
||||
it 'should not unregister the user at the discourse hub' do
|
||||
DiscourseHub.expects(:unregister_nickname).never
|
||||
destroy rescue nil
|
||||
end
|
||||
end
|
||||
|
||||
context "delete_posts is true" do
|
||||
subject(:destroy) { UserDestroyer.new(@admin).destroy(@user, delete_posts: true) }
|
||||
|
||||
include_examples "successfully destroy a user"
|
||||
|
||||
it "deletes the posts" do
|
||||
destroy
|
||||
post.reload.deleted_at.should_not be_nil
|
||||
post.nuked_user.should be_true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'user has no posts' do
|
||||
context 'and destroy succeeds' do
|
||||
|
||||
subject(:destroy) { UserDestroyer.new(@admin).destroy(@user) }
|
||||
|
||||
include_examples "successfully destroy a user"
|
||||
|
||||
it "should mark the user's deleted posts as belonging to a nuked user" do
|
||||
post = Fabricate(:post, user: @user, deleted_at: 1.hour.ago)
|
||||
|
@ -106,6 +125,8 @@ describe UserDestroyer do
|
|||
end
|
||||
|
||||
context 'and destroy fails' do
|
||||
subject(:destroy) { UserDestroyer.new(@admin).destroy(@user) }
|
||||
|
||||
before do
|
||||
@user.stubs(:destroy).returns(false)
|
||||
end
|
||||
|
|
|
@ -218,6 +218,13 @@ describe Admin::UsersController do
|
|||
response.should be_forbidden
|
||||
end
|
||||
|
||||
it "doesn't return an error if the user has posts and delete_posts == true" do
|
||||
Fabricate(:post, user: @delete_me)
|
||||
UserDestroyer.any_instance.expects(:destroy).with(@delete_me, has_entry('delete_posts' => true)).returns(true)
|
||||
xhr :delete, :destroy, id: @delete_me.id, delete_posts: true
|
||||
response.should be_success
|
||||
end
|
||||
|
||||
it "deletes the user record" do
|
||||
UserDestroyer.any_instance.expects(:destroy).returns(true)
|
||||
xhr :delete, :destroy, id: @delete_me.id
|
||||
|
|
Loading…
Reference in New Issue