From d96c1058a258789fefed15dd2ddd7215711a62c4 Mon Sep 17 00:00:00 2001
From: Arpit Jalan <arpit@techapj.com>
Date: Wed, 21 Mar 2018 09:45:16 +0530
Subject: [PATCH] FEATURE: add staff action log for 'restore topic'

---
 .../javascripts/discourse/models/topic.js.es6 |  7 +++-
 app/controllers/topics_controller.rb          |  2 +-
 app/models/user_history.rb                    |  6 ++-
 app/services/staff_action_logger.rb           | 18 ++++-----
 config/locales/client.en.yml                  |  1 +
 lib/post_destroyer.rb                         |  7 +++-
 .../staff_action_logs_controller_spec.rb      |  2 +-
 spec/services/staff_action_logger_spec.rb     | 38 ++++++++++++++-----
 8 files changed, 54 insertions(+), 27 deletions(-)

diff --git a/app/assets/javascripts/discourse/models/topic.js.es6 b/app/assets/javascripts/discourse/models/topic.js.es6
index e72d0e4c302..7ca45bb0227 100644
--- a/app/assets/javascripts/discourse/models/topic.js.es6
+++ b/app/assets/javascripts/discourse/models/topic.js.es6
@@ -355,7 +355,7 @@ const Topic = RestModel.extend({
       'details.can_delete': false,
       'details.can_recover': true
     });
-    return ajax("/t/" + this.get('id'), {
+    return ajax(`/t/${this.get('id')}`, {
       data: { context: window.location.pathname },
       type: 'DELETE'
     });
@@ -369,7 +369,10 @@ const Topic = RestModel.extend({
       'details.can_delete': true,
       'details.can_recover': false
     });
-    return ajax("/t/" + this.get('id') + "/recover", { type: 'PUT' });
+    return ajax(`/t/${this.get('id')}/recover`, {
+      data: { context: window.location.pathname },
+      type: 'PUT'
+    });
   },
 
   // Update our attributes from a JSON result
diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb
index 1c77d492463..457dcaf7220 100644
--- a/app/controllers/topics_controller.rb
+++ b/app/controllers/topics_controller.rb
@@ -450,7 +450,7 @@ class TopicsController < ApplicationController
     guardian.ensure_can_recover_topic!(topic)
 
     first_post = topic.posts.with_deleted.order(:post_number).first
-    PostDestroyer.new(current_user, first_post).recover
+    PostDestroyer.new(current_user, first_post, context: params[:context]).recover
 
     render body: nil
   end
diff --git a/app/models/user_history.rb b/app/models/user_history.rb
index c0980568fd7..2f5391cde50 100644
--- a/app/models/user_history.rb
+++ b/app/models/user_history.rb
@@ -70,7 +70,8 @@ class UserHistory < ActiveRecord::Base
       check_personal_message: 51,
       disabled_second_factor: 52,
       post_edit: 53,
-      topic_published: 54
+      topic_published: 54,
+      recover_topic: 55
     )
   end
 
@@ -119,7 +120,8 @@ class UserHistory < ActiveRecord::Base
       :check_personal_message,
       :disabled_second_factor,
       :post_edit,
-      :topic_published
+      :topic_published,
+      :recover_topic
     ]
   end
 
diff --git a/app/services/staff_action_logger.rb b/app/services/staff_action_logger.rb
index 312817027cd..841083b8112 100644
--- a/app/services/staff_action_logger.rb
+++ b/app/services/staff_action_logger.rb
@@ -59,24 +59,24 @@ class StaffActionLogger
                                           details: details.join("\n")))
   end
 
-  def log_topic_deletion(deleted_topic, opts = {})
-    raise Discourse::InvalidParameters.new(:deleted_topic) unless deleted_topic && deleted_topic.is_a?(Topic)
+  def log_topic_delete_recover(topic, action = "delete_topic", opts = {})
+    raise Discourse::InvalidParameters.new(:topic) unless topic && topic.is_a?(Topic)
 
-    user = deleted_topic.user ? "#{deleted_topic.user.username} (#{deleted_topic.user.name})" : "(deleted user)"
+    user = topic.user ? "#{topic.user.username} (#{topic.user.name})" : "(deleted user)"
 
     details = [
-      "id: #{deleted_topic.id}",
-      "created_at: #{deleted_topic.created_at}",
+      "id: #{topic.id}",
+      "created_at: #{topic.created_at}",
       "user: #{user}",
-      "title: #{deleted_topic.title}"
+      "title: #{topic.title}"
     ]
 
-    if first_post = deleted_topic.ordered_posts.first
+    if first_post = topic.ordered_posts.with_deleted.first
       details << "raw: #{first_post.raw}"
     end
 
-    UserHistory.create(params(opts).merge(action: UserHistory.actions[:delete_topic],
-                                          topic_id: deleted_topic.id,
+    UserHistory.create(params(opts).merge(action: UserHistory.actions[action.to_sym],
+                                          topic_id: topic.id,
                                           details: details.join("\n")))
   end
 
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index a265219e367..909a5524bff 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -3298,6 +3298,7 @@ en:
             revoke_badge: "revoke badge"
             check_email: "check email"
             delete_topic: "delete topic"
+            recover_topic: "un-delete topic"
             delete_post: "delete post"
             impersonate: "impersonate"
             anonymize_user: "anonymize user"
diff --git a/lib/post_destroyer.rb b/lib/post_destroyer.rb
index 6727211b9ef..986a65a694a 100644
--- a/lib/post_destroyer.rb
+++ b/lib/post_destroyer.rb
@@ -69,7 +69,10 @@ class PostDestroyer
     topic.update_statistics
     recover_user_actions
     DiscourseEvent.trigger(:post_recovered, @post, @opts, @user)
-    DiscourseEvent.trigger(:topic_recovered, topic, @user) if @post.is_first_post?
+    if @post.is_first_post?
+      DiscourseEvent.trigger(:topic_recovered, topic, @user)
+      StaffActionLogger.new(@user).log_topic_delete_recover(topic, "recover_topic", @opts.slice(:context)) if @user.id != @post.user_id
+    end
   end
 
   def staff_recovered
@@ -115,7 +118,7 @@ class PostDestroyer
       remove_associated_replies
       remove_associated_notifications
       if @post.topic && @post.is_first_post?
-        StaffActionLogger.new(@user).log_topic_deletion(@post.topic, @opts.slice(:context)) if @user.id != @post.user_id
+        StaffActionLogger.new(@user).log_topic_delete_recover(@post.topic, "delete_topic", @opts.slice(:context)) if @user.id != @post.user_id
         @post.topic.trash!(@user)
       elsif @user.id != @post.user_id
         StaffActionLogger.new(@user).log_post_deletion(@post, @opts.slice(:context))
diff --git a/spec/controllers/admin/staff_action_logs_controller_spec.rb b/spec/controllers/admin/staff_action_logs_controller_spec.rb
index d1e302bd1f7..3da6dfa1587 100644
--- a/spec/controllers/admin/staff_action_logs_controller_spec.rb
+++ b/spec/controllers/admin/staff_action_logs_controller_spec.rb
@@ -12,7 +12,7 @@ describe Admin::StaffActionLogsController do
     it 'generates logs' do
 
       topic = Fabricate(:topic)
-      _record = StaffActionLogger.new(Discourse.system_user).log_topic_deletion(topic)
+      _record = StaffActionLogger.new(Discourse.system_user).log_topic_delete_recover(topic, "delete_topic")
 
       get :index, params: { action_id: UserHistory.actions[:delete_topic] }, format: :json
 
diff --git a/spec/services/staff_action_logger_spec.rb b/spec/services/staff_action_logger_spec.rb
index 7d8535fe3c5..e48ff711bb1 100644
--- a/spec/services/staff_action_logger_spec.rb
+++ b/spec/services/staff_action_logger_spec.rb
@@ -72,21 +72,39 @@ describe StaffActionLogger do
     end
   end
 
-  describe 'log_topic_deletion' do
-    let(:deleted_topic) { Fabricate(:topic) }
+  describe 'log_topic_delete_recover' do
+    let(:topic) { Fabricate(:topic) }
 
-    subject(:log_topic_deletion) { described_class.new(admin).log_topic_deletion(deleted_topic) }
+    context "when deleting topic" do
+      subject(:log_topic_delete_recover) { described_class.new(admin).log_topic_delete_recover(topic) }
 
-    it 'raises an error when topic is nil' do
-      expect { logger.log_topic_deletion(nil) }.to raise_error(Discourse::InvalidParameters)
+      it 'raises an error when topic is nil' do
+        expect { logger.log_topic_delete_recover(nil) }.to raise_error(Discourse::InvalidParameters)
+      end
+
+      it 'raises an error when topic is not a Topic' do
+        expect { logger.log_topic_delete_recover(1) }.to raise_error(Discourse::InvalidParameters)
+      end
+
+      it 'creates a new UserHistory record' do
+        expect { log_topic_delete_recover }.to change { UserHistory.count }.by(1)
+      end
     end
 
-    it 'raises an error when topic is not a Topic' do
-      expect { logger.log_topic_deletion(1) }.to raise_error(Discourse::InvalidParameters)
-    end
+    context "when recovering topic" do
+      subject(:log_topic_delete_recover) { described_class.new(admin).log_topic_delete_recover(topic, "recover_topic") }
 
-    it 'creates a new UserHistory record' do
-      expect { log_topic_deletion }.to change { UserHistory.count }.by(1)
+      it 'raises an error when topic is nil' do
+        expect { logger.log_topic_delete_recover(nil, "recover_topic") }.to raise_error(Discourse::InvalidParameters)
+      end
+
+      it 'raises an error when topic is not a Topic' do
+        expect { logger.log_topic_delete_recover(1, "recover_topic") }.to raise_error(Discourse::InvalidParameters)
+      end
+
+      it 'creates a new UserHistory record' do
+        expect { log_topic_delete_recover }.to change { UserHistory.count }.by(1)
+      end
     end
   end