diff --git a/app/assets/javascripts/discourse/models/post.js.es6 b/app/assets/javascripts/discourse/models/post.js.es6 index 9202d581e05..ac60a212461 100644 --- a/app/assets/javascripts/discourse/models/post.js.es6 +++ b/app/assets/javascripts/discourse/models/post.js.es6 @@ -210,8 +210,12 @@ const Post = RestModel.extend({ can_recover: true }); } else { + const key = + this.get("post_number") === 1 + ? "topic.deleted_by_author" + : "post.deleted_by_author"; promise = cookAsync( - I18n.t("post.deleted_by_author", { + I18n.t(key, { count: Discourse.SiteSettings.delete_removed_posts_after }) ).then(cooked => { diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index e784eb8cb9c..720664bc3ac 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -2208,6 +2208,10 @@ en: one: You have selected 1 post. other: "You have selected {{count}} 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: quote_reply: "Quote" edit_reason: "Reason: " diff --git a/lib/guardian/post_guardian.rb b/lib/guardian/post_guardian.rb index f70d7661202..545a7d28c51 100644 --- a/lib/guardian/post_guardian.rb +++ b/lib/guardian/post_guardian.rb @@ -168,7 +168,7 @@ module PostGuardian # Deleting Methods def can_delete_post?(post) - can_see_post?(post) + return false if !can_see_post?(post) # Can't delete the first post return false if post.is_first_post? diff --git a/lib/guardian/topic_guardian.rb b/lib/guardian/topic_guardian.rb index d11c877ff59..e58b158955b 100644 --- a/lib/guardian/topic_guardian.rb +++ b/lib/guardian/topic_guardian.rb @@ -86,13 +86,17 @@ module TopicGuardian # Recovery Method 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 def can_delete_topic?(topic) !topic.trashed? && - is_staff? && - !(topic.is_category_topic?) && + (is_staff? || (topic.posts_count <= 1 && topic.created_at && topic.created_at > 24.hours.ago)) && + !topic.is_category_topic? && !Discourse.static_doc_topic_ids.include?(topic.id) end diff --git a/lib/post_destroyer.rb b/lib/post_destroyer.rb index 3c6ea4a5650..10e44f23fdf 100644 --- a/lib/post_destroyer.rb +++ b/lib/post_destroyer.rb @@ -167,8 +167,9 @@ class PostDestroyer I18n.with_locale(SiteSetting.default_locale) do # 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, - { 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 ) diff --git a/spec/components/guardian_spec.rb b/spec/components/guardian_spec.rb index b91bfe33b32..48d033402fa 100644 --- a/spec/components/guardian_spec.rb +++ b/spec/components/guardian_spec.rb @@ -1774,8 +1774,14 @@ describe Guardian do expect(Guardian.new(Fabricate(:user)).can_delete?(post)).to be_falsey end - it "returns false when it's the OP, even as a moderator" do - post.update_attribute :post_number, 1 + it "returns true when it's the OP" do + 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 end diff --git a/spec/components/post_destroyer_spec.rb b/spec/components/post_destroyer_spec.rb index e6758fa6032..115d5d2e777 100644 --- a/spec/components/post_destroyer_spec.rb +++ b/spec/components/post_destroyer_spec.rb @@ -283,7 +283,7 @@ describe PostDestroyer do expect(post2.deleted_at).to be_blank expect(post2.deleted_by).to be_blank 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(called).to eq(1) 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 SiteSetting.delete_removed_posts_after = 0 + post.update!(post_number: 2) + PostDestroyer.new(post.user, post, delete_removed_posts_after: 1).destroy post.reload diff --git a/spec/requests/topics_controller_spec.rb b/spec/requests/topics_controller_spec.rb index ad9910ee425..36b4748d853 100644 --- a/spec/requests/topics_controller_spec.rb +++ b/spec/requests/topics_controller_spec.rb @@ -833,7 +833,7 @@ RSpec.describe TopicsController do describe 'when logged in' do let(:user) { Fabricate(:user) } 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) } describe 'without access' do