FEATURE: the ability to permanently destroy the private message (#11115)
PostDestroyer should accept the option to permanently destroy post from the database. In addition, when the first post is destroyed it destroys the whole topic. Currently, that feature is limited to private messages and creator of the post. It will be used by discourse-encrypt to explode encrypted private messages.
This commit is contained in:
parent
27e94f2f98
commit
586c8efbd8
|
@ -1424,6 +1424,12 @@ export default Controller.extend(bufferedProperty("model"), {
|
|||
.then(() => refresh({ id: data.id }));
|
||||
break;
|
||||
}
|
||||
case "destroyed": {
|
||||
postStream
|
||||
.triggerDestroyedPost(data.id)
|
||||
.then(() => refresh({ id: data.id }));
|
||||
break;
|
||||
}
|
||||
case "recovered": {
|
||||
postStream
|
||||
.triggerRecoveredPost(data.id)
|
||||
|
|
|
@ -737,6 +737,12 @@ export default RestModel.extend({
|
|||
return Promise.resolve();
|
||||
},
|
||||
|
||||
triggerDestroyedPost(postId) {
|
||||
const existing = this._identityMap[postId];
|
||||
this.removePosts([existing]);
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
triggerChangedPost(postId, updatedAt, opts) {
|
||||
opts = opts || {};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import PreloadStore from "discourse/lib/preload-store";
|
|||
import Category from "discourse/models/category";
|
||||
import User from "discourse/models/user";
|
||||
import { deepEqual } from "discourse-common/lib/object";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
|
||||
function isNew(topic) {
|
||||
return (
|
||||
|
@ -148,6 +149,17 @@ const TopicTrackingState = EmberObject.extend({
|
|||
}
|
||||
tracker.incrementMessageCount();
|
||||
});
|
||||
|
||||
this.messageBus.subscribe("/destroy", (msg) => {
|
||||
tracker.incrementMessageCount();
|
||||
const currentRoute = DiscourseURL.router.currentRoute.parent;
|
||||
if (
|
||||
currentRoute.name === "topic" &&
|
||||
parseInt(currentRoute.params.id, 10) === msg.topic_id
|
||||
) {
|
||||
DiscourseURL.redirectTo("/");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
mutedTopics() {
|
||||
|
|
|
@ -171,6 +171,17 @@ class TopicTrackingState
|
|||
MessageBus.publish("/delete", message.as_json, group_ids: group_ids)
|
||||
end
|
||||
|
||||
def self.publish_destroy(topic)
|
||||
group_ids = topic.category && topic.category.secure_group_ids
|
||||
|
||||
message = {
|
||||
topic_id: topic.id,
|
||||
message_type: "destroy"
|
||||
}
|
||||
|
||||
MessageBus.publish("/destroy", message.as_json, group_ids: group_ids)
|
||||
end
|
||||
|
||||
def self.publish_read(topic_id, last_read_post_number, user_id, notification_level = nil)
|
||||
highest_post_number = DB.query_single("SELECT highest_post_number FROM topics WHERE id = ?", topic_id).first
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ class PostDestroyer
|
|||
|
||||
delete_removed_posts_after = @opts[:delete_removed_posts_after] || SiteSetting.delete_removed_posts_after
|
||||
|
||||
if delete_removed_posts_after < 1 || post_is_reviewable? || Guardian.new(@user).can_moderate_topic?(topic)
|
||||
if delete_removed_posts_after < 1 || post_is_reviewable? || Guardian.new(@user).can_moderate_topic?(topic) || permanent?
|
||||
perform_delete
|
||||
elsif @user.id == @post.user_id
|
||||
mark_for_deletion(delete_removed_posts_after)
|
||||
|
@ -140,9 +140,10 @@ class PostDestroyer
|
|||
|
||||
# When a post is properly deleted. Well, it's still soft deleted, but it will no longer
|
||||
# show up in the topic
|
||||
# Permanent option allows to hard delete.
|
||||
def perform_delete
|
||||
Post.transaction do
|
||||
@post.trash!(@user)
|
||||
permanent? ? @post.destroy! : @post.trash!(@user)
|
||||
if @post.topic
|
||||
make_previous_post_the_last_one
|
||||
mark_topic_changed
|
||||
|
@ -162,7 +163,9 @@ class PostDestroyer
|
|||
end
|
||||
end
|
||||
|
||||
@post.topic.trash!(@user) if @post.topic && @post.is_first_post?
|
||||
if @post.topic && @post.is_first_post?
|
||||
permanent? ? @post.topic.destroy! : @post.topic.trash!(@user)
|
||||
end
|
||||
update_associated_category_latest_topic
|
||||
update_user_counts
|
||||
TopicUser.update_post_action_cache(post_id: @post.id)
|
||||
|
@ -178,8 +181,12 @@ class PostDestroyer
|
|||
|
||||
update_imap_sync(@post, true) if @post.topic&.deleted_at
|
||||
feature_users_in_the_topic if @post.topic
|
||||
@post.publish_change_to_clients! :deleted if @post.topic
|
||||
TopicTrackingState.publish_delete(@post.topic) if @post.topic && @post.post_number == 1
|
||||
@post.publish_change_to_clients!(permanent? ? :destroyed : :deleted) if @post.topic
|
||||
TopicTrackingState.send(permanent? ? :publish_destroy : :publish_delete, @post.topic) if @post.topic && @post.post_number == 1
|
||||
end
|
||||
|
||||
def permanent?
|
||||
@opts[:permanent] && @user == @post.user && @post.topic.private_message?
|
||||
end
|
||||
|
||||
# When a user 'deletes' their own post. We just change the text.
|
||||
|
|
|
@ -174,6 +174,7 @@ module SvgSprite
|
|||
"star",
|
||||
"step-backward",
|
||||
"step-forward",
|
||||
"stopwatch",
|
||||
"stream",
|
||||
"sync-alt",
|
||||
"sync",
|
||||
|
|
|
@ -961,4 +961,27 @@ describe PostDestroyer do
|
|||
expect(user.user_profile.reload.featured_topic).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe "permanent destroy" do
|
||||
fab!(:private_message_topic) { Fabricate(:private_message_topic) }
|
||||
fab!(:private_post) { Fabricate(:private_message_post, topic: private_message_topic) }
|
||||
fab!(:reply) { Fabricate(:private_message_post, topic: private_message_topic) }
|
||||
it "destroys the post and topic if deleting first post" do
|
||||
PostDestroyer.new(reply.user, reply, permanent: true).destroy
|
||||
expect { reply.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
expect(private_message_topic.reload.persisted?).to be true
|
||||
|
||||
PostDestroyer.new(private_post.user, private_post, permanent: true).destroy
|
||||
expect { private_post.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
expect { private_message_topic.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
|
||||
it 'soft delete if not creator of post or not private message' do
|
||||
PostDestroyer.new(moderator, reply, permanent: true).destroy
|
||||
expect(reply.deleted_at).not_to eq(nil)
|
||||
|
||||
PostDestroyer.new(post.user, post, permanent: true).destroy
|
||||
expect(post.user_deleted).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue