diff --git a/app/assets/javascripts/discourse/models/action_summary.js b/app/assets/javascripts/discourse/models/action_summary.js
index ffcc19011..80517ae14 100644
--- a/app/assets/javascripts/discourse/models/action_summary.js
+++ b/app/assets/javascripts/discourse/models/action_summary.js
@@ -22,17 +22,22 @@ Discourse.ActionSummary = Discourse.Model.extend({
     }
   }.property('count', 'acted', 'actionType'),
 
-  canAlsoAction: function() {
-    if (this.get('hidden')) return false;
-    return this.get('can_act');
-  }.property('can_act', 'hidden'),
+  canAlsoAction: Em.computed.and('can_act', 'actionType.notCustomFlag'),
+  usersCollapsed: Em.computed.not('usersExpanded'),
+  usersExpanded: Em.computed.gt('users.length', 0),
 
   // Remove it
   removeAction: function() {
-    this.set('acted', false);
-    this.set('count', this.get('count') - 1);
-    this.set('can_act', true);
-    return this.set('can_undo', false);
+    this.setProperties({
+      acted: false,
+      count: this.get('count') - 1,
+      can_act: true,
+      can_undo: false
+    });
+
+    if (this.get('usersExpanded')) {
+      this.get('users').removeObject(Discourse.User.current());
+    }
   },
 
   // Perform this action
@@ -42,10 +47,12 @@ Discourse.ActionSummary = Discourse.Model.extend({
     var action = this.get('actionType.name_key');
 
     // Mark it as acted
-    this.set('acted', true);
-    this.set('count', this.get('count') + 1);
-    this.set('can_act', false);
-    this.set('can_undo', true);
+    this.setProperties({
+      acted: true,
+      count: this.get('count') + 1,
+      can_act: false,
+      can_undo: true
+    });
 
     if(action === 'notify_moderators' || action === 'notify_user') {
       this.set('can_undo',false);
@@ -53,8 +60,8 @@ Discourse.ActionSummary = Discourse.Model.extend({
     }
 
     // Add ourselves to the users who liked it if present
-    if (this.present('users')) {
-      this.users.pushObject(Discourse.User.current());
+    if (this.get('usersExpanded')) {
+      this.get('users').addObject(Discourse.User.current());
     }
 
     // Create our post action
@@ -113,7 +120,11 @@ Discourse.ActionSummary = Discourse.Model.extend({
       var users = Em.A();
       actionSummary.set('users', users);
       _.each(result,function(user) {
-        users.pushObject(Discourse.User.create(user));
+        if (user.id === Discourse.User.current('id')) {
+          users.pushObject(Discourse.User.current());
+        } else {
+          users.pushObject(Discourse.User.create(user));
+        }
       });
     });
   }
diff --git a/app/assets/javascripts/discourse/models/post.js b/app/assets/javascripts/discourse/models/post.js
index 551ad65a1..7ef7de00d 100644
--- a/app/assets/javascripts/discourse/models/post.js
+++ b/app/assets/javascripts/discourse/models/post.js
@@ -186,6 +186,11 @@ Discourse.Post = Discourse.Model.extend({
   },
 
   recover: function() {
+    this.setProperties({
+      deleted_at: null,
+      deleted_by: null
+    });
+
     return Discourse.ajax("/posts/" + (this.get('id')) + "/recover", { type: 'PUT', cache: false });
   },
 
diff --git a/app/assets/javascripts/discourse/models/post_action_type.js b/app/assets/javascripts/discourse/models/post_action_type.js
index c3583967b..b941ae25b 100644
--- a/app/assets/javascripts/discourse/models/post_action_type.js
+++ b/app/assets/javascripts/discourse/models/post_action_type.js
@@ -6,7 +6,9 @@
   @namespace Discourse
   @module Discourse
 **/
-Discourse.PostActionType = Discourse.Model.extend({});
+Discourse.PostActionType = Discourse.Model.extend({
+  notCustomFlag: Em.computed.not('is_custom_flag')
+});
 
 Discourse.PostActionType.reopenClass({
   MAX_MESSAGE_LENGTH: 500
diff --git a/app/assets/javascripts/discourse/templates/post.js.handlebars b/app/assets/javascripts/discourse/templates/post.js.handlebars
index 57323e820..405002912 100644
--- a/app/assets/javascripts/discourse/templates/post.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/post.js.handlebars
@@ -55,6 +55,13 @@
       </div>
       {{view Discourse.RepliesView contentBinding="replies" postViewBinding="view"}}
       {{view Discourse.ActionsHistoryView contentBinding="actionsHistory"}}
+
+      {{#if deleted_by}}
+        <div class='post-actions'>
+          {{i18n post.deleted_by}} {{avatar deleted_by imageSize="tiny"}}
+        </div>
+      {{/if}}
+
       {{view Discourse.TopicSummaryView postBinding="this"}}
     </div>
 
diff --git a/app/assets/javascripts/discourse/views/actions_history_view.js b/app/assets/javascripts/discourse/views/actions_history_view.js
index 8ca6aee17..04ffcae7a 100644
--- a/app/assets/javascripts/discourse/views/actions_history_view.js
+++ b/app/assets/javascripts/discourse/views/actions_history_view.js
@@ -10,24 +10,27 @@
 Discourse.ActionsHistoryView = Discourse.View.extend({
   tagName: 'section',
   classNameBindings: [':post-actions', 'hidden'],
-
   hidden: Em.computed.empty('content'),
-
-  shouldRerender: Discourse.View.renderIfChanged('content.@each', 'content.users.@each'),
+  shouldRerender: Discourse.View.renderIfChanged('content.@each', 'content.users.length'),
 
   // This was creating way too many bound ifs and subviews in the handlebars version.
   render: function(buffer) {
     if (!this.present('content')) return;
 
-    return this.get('content').forEach(function(c) {
-      var actionString, iconsHtml;
+    this.get('content').forEach(function(c) {
       buffer.push("<div class='post-action'>");
 
+      var renderActionIf = function(property, dataAttribute, text) {
+        if (!c.get(property)) { return; }
+        buffer.push(" <a href='#' data-" + dataAttribute + "='" + c.get('id') + "'>" + text + "</a>.");
+      };
+
       // TODO multi line expansion for flags
-      var postUrl;
-      if (c.get('users')) {
-        iconsHtml = "";
+      var iconsHtml = "";
+      if (c.get('usersExpanded')) {
+        var postUrl;
         c.get('users').forEach(function(u) {
+          console.log(u);
           iconsHtml += "<a href=\"" + Discourse.getURL("/users/") + (u.get('username_lower')) + "\">";
           if (u.post_url) {
             postUrl = postUrl || u.post_url;
@@ -42,44 +45,35 @@ Discourse.ActionsHistoryView = Discourse.View.extend({
         });
 
         var key = 'post.actions.people.' + c.get('actionType.name_key');
-        if(postUrl) {
-          key = key + "_with_url";
-        }
+        if (postUrl) { key = key + "_with_url"; }
+
         buffer.push(" " + I18n.t(key, { icons: iconsHtml, postUrl: postUrl}) + ".");
-      } else {
-        buffer.push("<a href='#' data-who-acted='" + (c.get('id')) + "'>" + (c.get('description')) + "</a>.");
-      }
-
-      if (c.get('can_act') && !c.get('actionType.is_custom_flag')) {
-        actionString = I18n.t("post.actions.it_too." + c.get('actionType.name_key'));
-        buffer.push(" <a href='#' data-act='" + (c.get('id')) + "'>" + actionString + "</a>.");
-      }
-
-      if (c.get('can_undo')) {
-        actionString = I18n.t("post.actions.undo." + c.get('actionType.name_key') );
-        buffer.push(" <a href='#' data-undo='" + (c.get('id')) + "'>" + actionString + "</a>.");
-      }
-
-      if (c.get('can_clear_flags')) {
-        buffer.push(" <a href='#' data-clear-flags='" + (c.get('id')) + "'>" + (I18n.t("post.actions.clear_flags", { count: c.count })) + "</a>.");
       }
+      renderActionIf('usersCollapsed', 'who-acted', c.get('description'));
+      renderActionIf('canAlsoAction', 'act', I18n.t("post.actions.it_too." + c.get('actionType.name_key')));
+      renderActionIf('can_undo', 'undo', I18n.t("post.actions.undo." + c.get('actionType.name_key')));
+      renderActionIf('can_clear_flags', 'clear-flags', I18n.t("post.actions.clear_flags", { count: c.count }));
 
       buffer.push("</div>");
     });
   },
 
+  actionTypeById: function(actionTypeId) {
+    return this.get('content').findProperty('id', actionTypeId);
+  },
+
   click: function(e) {
-    var $target, actionTypeId;
-    $target = $(e.target);
+    var $target = $(e.target),
+        actionTypeId;
 
     if (actionTypeId = $target.data('clear-flags')) {
-      this.get('controller').clearFlags(this.content.findProperty('id', actionTypeId));
+      this.get('controller').clearFlags(this.actionTypeById(actionTypeId));
       return false;
     }
 
     // User wants to know who actioned it
     if (actionTypeId = $target.data('who-acted')) {
-      this.get('controller').whoActed(this.content.findProperty('id', actionTypeId));
+      this.get('controller').whoActed(this.actionTypeById(actionTypeId));
       return false;
     }
 
diff --git a/app/serializers/post_serializer.rb b/app/serializers/post_serializer.rb
index c6da600ca..05a6277cc 100644
--- a/app/serializers/post_serializer.rb
+++ b/app/serializers/post_serializer.rb
@@ -118,6 +118,14 @@ class PostSerializer < BasicPostSerializer
     true
   end
 
+  def deleted_by
+    BasicUserSerializer.new(object.deleted_by, root: false).as_json
+  end
+
+  def include_deleted_by?
+    object.deleted_by.present?
+  end
+
   # Summary of the actions taken on this post
   def actions_summary
     result = []
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 54a351247..f8cdc7cac 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -732,6 +732,7 @@ en:
       continue_discussion: "Continuing the discussion from {{postLink}}:"
       follow_quote: "go to the quoted post"
       deleted_by_author: "(post removed by author)"
+      deleted_by: "deleted by"
       expand_collapse: "expand/collapse"
 
       has_replies:
diff --git a/test/javascripts/models/post_test.js b/test/javascripts/models/post_test.js
index cf19235f5..0320e6715 100644
--- a/test/javascripts/models/post_test.js
+++ b/test/javascripts/models/post_test.js
@@ -64,6 +64,11 @@ test('destroy by staff', function() {
   present(post.get('deleted_at'), "it has a `deleted_at` field.");
   equal(post.get('deleted_by'), user, "it has the user in the `deleted_by` field");
   ok(Discourse.ajax.calledOnce, "it made an AJAX call");
+
+  post.recover();
+  blank(post.get('deleted_at'), "it clears `deleted_at` when recovering");
+  blank(post.get('deleted_by'), "it clears `deleted_by` when recovering");
+
 });
 
 test('destroy by non-staff', function() {