FEATURE: Let users delete their own topics. (#7267)
This commit is contained in:
parent
4a3daacb1b
commit
31053f30de
|
@ -210,8 +210,12 @@ const Post = RestModel.extend({
|
||||||
can_recover: true
|
can_recover: true
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
const key =
|
||||||
|
this.get("post_number") === 1
|
||||||
|
? "topic.deleted_by_author"
|
||||||
|
: "post.deleted_by_author";
|
||||||
promise = cookAsync(
|
promise = cookAsync(
|
||||||
I18n.t("post.deleted_by_author", {
|
I18n.t(key, {
|
||||||
count: Discourse.SiteSettings.delete_removed_posts_after
|
count: Discourse.SiteSettings.delete_removed_posts_after
|
||||||
})
|
})
|
||||||
).then(cooked => {
|
).then(cooked => {
|
||||||
|
|
|
@ -2208,6 +2208,10 @@ en:
|
||||||
one: You have selected <b>1</b> post.
|
one: You have selected <b>1</b> post.
|
||||||
other: "You have selected <b>{{count}}</b> posts."
|
other: "You have selected <b>{{count}}</b> posts."
|
||||||
|
|
||||||
|
deleted_by_author:
|
||||||
|
one: "(topic withdrawn by author, will be automatically deleted in %{count} hour unless flagged)"
|
||||||
|
other: "(topic withdrawn by author, will be automatically deleted in %{count} hours unless flagged)"
|
||||||
|
|
||||||
post:
|
post:
|
||||||
quote_reply: "Quote"
|
quote_reply: "Quote"
|
||||||
edit_reason: "Reason: "
|
edit_reason: "Reason: "
|
||||||
|
|
|
@ -168,7 +168,7 @@ module PostGuardian
|
||||||
|
|
||||||
# Deleting Methods
|
# Deleting Methods
|
||||||
def can_delete_post?(post)
|
def can_delete_post?(post)
|
||||||
can_see_post?(post)
|
return false if !can_see_post?(post)
|
||||||
|
|
||||||
# Can't delete the first post
|
# Can't delete the first post
|
||||||
return false if post.is_first_post?
|
return false if post.is_first_post?
|
||||||
|
|
|
@ -86,13 +86,17 @@ module TopicGuardian
|
||||||
|
|
||||||
# Recovery Method
|
# Recovery Method
|
||||||
def can_recover_topic?(topic)
|
def can_recover_topic?(topic)
|
||||||
topic && topic.deleted_at && topic.user && is_staff?
|
if is_staff?
|
||||||
|
!!(topic && topic.deleted_at && topic.user)
|
||||||
|
else
|
||||||
|
topic && can_recover_post?(topic.ordered_posts.first)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_delete_topic?(topic)
|
def can_delete_topic?(topic)
|
||||||
!topic.trashed? &&
|
!topic.trashed? &&
|
||||||
is_staff? &&
|
(is_staff? || (topic.posts_count <= 1 && topic.created_at && topic.created_at > 24.hours.ago)) &&
|
||||||
!(topic.is_category_topic?) &&
|
!topic.is_category_topic? &&
|
||||||
!Discourse.static_doc_topic_ids.include?(topic.id)
|
!Discourse.static_doc_topic_ids.include?(topic.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -167,8 +167,9 @@ class PostDestroyer
|
||||||
I18n.with_locale(SiteSetting.default_locale) do
|
I18n.with_locale(SiteSetting.default_locale) do
|
||||||
|
|
||||||
# don't call revise from within transaction, high risk of deadlock
|
# don't call revise from within transaction, high risk of deadlock
|
||||||
|
key = @post.is_first_post? ? 'js.topic.deleted_by_author' : 'js.post.deleted_by_author'
|
||||||
@post.revise(@user,
|
@post.revise(@user,
|
||||||
{ raw: I18n.t('js.post.deleted_by_author', count: delete_removed_posts_after) },
|
{ raw: I18n.t(key, count: delete_removed_posts_after) },
|
||||||
force_new_version: true
|
force_new_version: true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1774,8 +1774,14 @@ describe Guardian do
|
||||||
expect(Guardian.new(Fabricate(:user)).can_delete?(post)).to be_falsey
|
expect(Guardian.new(Fabricate(:user)).can_delete?(post)).to be_falsey
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns false when it's the OP, even as a moderator" do
|
it "returns true when it's the OP" do
|
||||||
post.update_attribute :post_number, 1
|
post.update!(post_number: 1)
|
||||||
|
expect(Guardian.new(moderator).can_delete?(post)).to be_falsey
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false when it's the OP, even as a moderator if there are at least two posts" do
|
||||||
|
post.update!(post_number: 1)
|
||||||
|
Fabricate(:post, topic: post.topic)
|
||||||
expect(Guardian.new(moderator).can_delete?(post)).to be_falsey
|
expect(Guardian.new(moderator).can_delete?(post)).to be_falsey
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -283,7 +283,7 @@ describe PostDestroyer do
|
||||||
expect(post2.deleted_at).to be_blank
|
expect(post2.deleted_at).to be_blank
|
||||||
expect(post2.deleted_by).to be_blank
|
expect(post2.deleted_by).to be_blank
|
||||||
expect(post2.user_deleted).to eq(true)
|
expect(post2.user_deleted).to eq(true)
|
||||||
expect(post2.raw).to eq(I18n.t('js.post.deleted_by_author', count: 24))
|
expect(post2.raw).to eq(I18n.t('js.topic.deleted_by_author', count: 24))
|
||||||
expect(post2.version).to eq(2)
|
expect(post2.version).to eq(2)
|
||||||
expect(called).to eq(1)
|
expect(called).to eq(1)
|
||||||
expect(user_stat.reload.post_count).to eq(0)
|
expect(user_stat.reload.post_count).to eq(0)
|
||||||
|
@ -338,6 +338,8 @@ describe PostDestroyer do
|
||||||
it "accepts a delete_removed_posts_after option" do
|
it "accepts a delete_removed_posts_after option" do
|
||||||
SiteSetting.delete_removed_posts_after = 0
|
SiteSetting.delete_removed_posts_after = 0
|
||||||
|
|
||||||
|
post.update!(post_number: 2)
|
||||||
|
|
||||||
PostDestroyer.new(post.user, post, delete_removed_posts_after: 1).destroy
|
PostDestroyer.new(post.user, post, delete_removed_posts_after: 1).destroy
|
||||||
|
|
||||||
post.reload
|
post.reload
|
||||||
|
|
|
@ -833,7 +833,7 @@ RSpec.describe TopicsController do
|
||||||
describe 'when logged in' do
|
describe 'when logged in' do
|
||||||
let(:user) { Fabricate(:user) }
|
let(:user) { Fabricate(:user) }
|
||||||
let(:moderator) { Fabricate(:moderator) }
|
let(:moderator) { Fabricate(:moderator) }
|
||||||
let(:topic) { Fabricate(:topic, user: user) }
|
let(:topic) { Fabricate(:topic, user: user, created_at: 48.hours.ago) }
|
||||||
let!(:post) { Fabricate(:post, topic: topic, user: user, post_number: 1) }
|
let!(:post) { Fabricate(:post, topic: topic, user: user, post_number: 1) }
|
||||||
|
|
||||||
describe 'without access' do
|
describe 'without access' do
|
||||||
|
|
Loading…
Reference in New Issue