From 61ea8c6f7224c98cdbadecdf9d1267c9037c12da Mon Sep 17 00:00:00 2001
From: Kane York <rikingcoding@gmail.com>
Date: Wed, 15 Jul 2015 15:22:01 -0700
Subject: [PATCH] FIX: Allow to change ownership on deleted users' posts

---
 .../discourse/controllers/change-owner.js.es6 |  7 ++++---
 app/models/post.rb                            |  2 +-
 app/services/post_owner_changer.rb            |  6 ++++++
 config/locales/server.en.yml                  |  1 +
 lib/post_revisor.rb                           |  2 +-
 spec/controllers/topics_controller_spec.rb    | 19 +++++++++++++++++++
 6 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/app/assets/javascripts/discourse/controllers/change-owner.js.es6 b/app/assets/javascripts/discourse/controllers/change-owner.js.es6
index 2ba32b23f..1e11a1ccf 100644
--- a/app/assets/javascripts/discourse/controllers/change-owner.js.es6
+++ b/app/assets/javascripts/discourse/controllers/change-owner.js.es6
@@ -1,14 +1,15 @@
 import Presence from 'discourse/mixins/presence';
 import SelectedPostsCount from 'discourse/mixins/selected-posts-count';
 import ModalFunctionality from 'discourse/mixins/modal-functionality';
-import ObjectController from 'discourse/controllers/object';
 
 // Modal related to changing the ownership of posts
-export default ObjectController.extend(Presence, SelectedPostsCount, ModalFunctionality, {
+export default Ember.Controller.extend(Presence, SelectedPostsCount, ModalFunctionality, {
   needs: ['topic'],
 
   topicController: Em.computed.alias('controllers.topic'),
   selectedPosts: Em.computed.alias('topicController.selectedPosts'),
+  saving: false,
+  new_user: null,
 
   buttonDisabled: function() {
     if (this.get('saving')) return true;
@@ -38,7 +39,7 @@ export default ObjectController.extend(Presence, SelectedPostsCount, ModalFuncti
             username: this.get('new_user')
           };
 
-      Discourse.Topic.changeOwners(this.get('id'), saveOpts).then(function(result) {
+      Discourse.Topic.changeOwners(this.get('topicController.model.id'), saveOpts).then(function(result) {
         // success
         self.send('closeModal');
         self.get('topicController').send('toggleMultiSelect');
diff --git a/app/models/post.rb b/app/models/post.rb
index 22fbea3ec..7a0a98dca 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -400,7 +400,7 @@ class Post < ActiveRecord::Base
     return if user_id == new_user.id
 
     edit_reason = I18n.t('change_owner.post_revision_text',
-      old_user: self.user.username_lower,
+      old_user: (self.user.username_lower rescue nil) || I18n.t('change_owner.deleted_user'),
       new_user: new_user.username_lower
     )
 
diff --git a/app/services/post_owner_changer.rb b/app/services/post_owner_changer.rb
index 5ee2a47b6..bf8868591 100644
--- a/app/services/post_owner_changer.rb
+++ b/app/services/post_owner_changer.rb
@@ -14,6 +14,12 @@ class PostOwnerChanger
       @post_ids.each do |post_id|
         post = Post.with_deleted.find(post_id)
         @topic.user = @new_owner if post.is_first_post?
+
+        if post.user == nil
+          post.recover!
+          @topic.recover! if post.is_first_post?
+        end
+        post.topic = @topic
         post.set_owner(@new_owner, @acting_user)
       end
 
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index f267c054d..90b93ddce 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -1248,6 +1248,7 @@ en:
 
   change_owner:
     post_revision_text: "Ownership transferred from %{old_user} to %{new_user}"
+    deleted_user: "a deleted user"
 
   emoji:
     errors:
diff --git a/lib/post_revisor.rb b/lib/post_revisor.rb
index 48f9c9714..b19583820 100644
--- a/lib/post_revisor.rb
+++ b/lib/post_revisor.rb
@@ -202,7 +202,7 @@ class PostRevisor
   USER_ACTIONS_TO_REMOVE ||= [UserAction::REPLY, UserAction::RESPONSE]
 
   def update_post
-    if @fields.has_key?("user_id") && @fields["user_id"] != @post.user_id
+    if @fields.has_key?("user_id") && @fields["user_id"] != @post.user_id && @post.user_id != nil
       prev_owner = User.find(@post.user_id)
       new_owner = User.find(@fields["user_id"])
 
diff --git a/spec/controllers/topics_controller_spec.rb b/spec/controllers/topics_controller_spec.rb
index 7516ce32f..ae5c0523e 100644
--- a/spec/controllers/topics_controller_spec.rb
+++ b/spec/controllers/topics_controller_spec.rb
@@ -242,6 +242,25 @@ describe TopicsController do
         expect(p1.user).not_to eq(nil)
         expect(p1.user).to eq(p2.user)
       end
+
+      it "works with deleted users" do
+        deleted_user = Fabricate(:user)
+        t2 = Fabricate(:topic, user: deleted_user)
+        p3 = Fabricate(:post, topic_id: t2.id, user: deleted_user)
+        deleted_user.save
+        t2.save
+        p3.save
+
+        UserDestroyer.new(editor).destroy(deleted_user, { delete_posts: true, context: 'test', delete_as_spammer: true })
+
+        xhr :post, :change_post_owners, topic_id: t2.id, username: user_a.username_lower, post_ids: [p3.id]
+        expect(response).to be_success
+        t2.reload
+        p3.reload
+        expect(t2.deleted_at).to be_nil
+        expect(p3.deleted_at).to be_nil
+        expect(p3.user).to eq(user_a)
+      end
     end
   end