Add site setting delete_removed_posts_after to configure after how many hour posts that were deleted by their authors will be deleted

This commit is contained in:
Neil Lalonde 2013-08-02 13:35:42 -04:00
parent ef82b66e95
commit 9db0ac16a9
8 changed files with 49 additions and 7 deletions

View File

@ -235,7 +235,7 @@ Discourse.Post = Discourse.Model.extend({
}); });
} else { } else {
this.setProperties({ this.setProperties({
cooked: Discourse.Markdown.cook(I18n.t("post.deleted_by_author")), cooked: Discourse.Markdown.cook(I18n.t("post.deleted_by_author", {count: Discourse.SiteSettings.delete_removed_posts_after})),
can_delete: false, can_delete: false,
version: this.get('version') + 1, version: this.get('version') + 1,
can_recover: true, can_recover: true,

View File

@ -87,6 +87,7 @@ class SiteSetting < ActiveRecord::Base
setting(:apple_touch_icon_url, '/assets/default-apple-touch-icon.png') setting(:apple_touch_icon_url, '/assets/default-apple-touch-icon.png')
setting(:ninja_edit_window, 5.minutes.to_i) setting(:ninja_edit_window, 5.minutes.to_i)
client_setting(:delete_removed_posts_after, 24) # hours
setting(:post_undo_action_window_mins, 10) setting(:post_undo_action_window_mins, 10)
setting(:system_username, '') setting(:system_username, '')
setting(:max_mentions_per_post, 10) setting(:max_mentions_per_post, 10)

View File

@ -34,6 +34,6 @@ module Clockwork
every(1.day, 'version_check') every(1.day, 'version_check')
every(1.minute, 'clockwork_heartbeat') every(1.minute, 'clockwork_heartbeat')
every(1.minute, 'poll_mailbox') every(1.minute, 'poll_mailbox')
every(2.hours, 'destroy_old_deletion_stubs') every(30.minutes, 'destroy_old_deletion_stubs')
end end

View File

@ -750,7 +750,9 @@ en:
reply_as_new_topic: "Reply as new Topic" reply_as_new_topic: "Reply as new Topic"
continue_discussion: "Continuing the discussion from {{postLink}}:" continue_discussion: "Continuing the discussion from {{postLink}}:"
follow_quote: "go to the quoted post" follow_quote: "go to the quoted post"
deleted_by_author: "(post withdrawn by author, will be automatically deleted in 24 hours unless flagged)" deleted_by_author:
one: "(post withdrawn by author, will be automatically deleted in %{count} hour unless flagged)"
other: "(post withdrawn by author, will be automatically deleted in %{count} hours unless flagged)"
deleted_by: "deleted by" deleted_by: "deleted by"
expand_collapse: "expand/collapse" expand_collapse: "expand/collapse"

View File

@ -468,6 +468,7 @@ en:
queue_jobs: "DEVELOPER ONLY! WARNING! By default, queue jobs in sidekiq. If disabled, your site will be broken." queue_jobs: "DEVELOPER ONLY! WARNING! By default, queue jobs in sidekiq. If disabled, your site will be broken."
crawl_images: "Enable retrieving images from third party sources to insert width and height dimensions" crawl_images: "Enable retrieving images from third party sources to insert width and height dimensions"
ninja_edit_window: "Number of seconds after posting where edits do not create a new version" ninja_edit_window: "Number of seconds after posting where edits do not create a new version"
delete_removed_posts_after: "Number of hours after which a post that was removed by its author will be deleted."
max_image_width: "Maximum allowed width of images in a post" max_image_width: "Maximum allowed width of images in a post"
category_featured_topics: "Number of topics displayed per category in the /categories page" category_featured_topics: "Number of topics displayed per category in the /categories page"
add_rel_nofollow_to_user_content: "Add rel nofollow to all submitted user content, except for internal links (including parent domains) changing this requires you update all your baked markdown with: \"rake posts:rebake\"" add_rel_nofollow_to_user_content: "Add rel nofollow to all submitted user content, except for internal links (including parent domains) changing this requires you update all your baked markdown with: \"rake posts:rebake\""

View File

@ -12,7 +12,7 @@ class PostDestroyer
WHERE t.deleted_at IS NOT NULL AND WHERE t.deleted_at IS NOT NULL AND
t.id = posts.topic_id t.id = posts.topic_id
)") )")
.where("updated_at < ? AND post_number > 1", 1.day.ago) .where("updated_at < ? AND post_number > 1", SiteSetting.delete_removed_posts_after.hours.ago)
.where("NOT EXISTS ( .where("NOT EXISTS (
SELECT 1 SELECT 1
FROM post_actions pa FROM post_actions pa
@ -104,7 +104,7 @@ class PostDestroyer
# When a user 'deletes' their own post. We just change the text. # When a user 'deletes' their own post. We just change the text.
def user_destroyed def user_destroyed
Post.transaction do Post.transaction do
@post.revise(@user, I18n.t('js.post.deleted_by_author'), force_new_version: true) @post.revise(@user, I18n.t('js.post.deleted_by_author', count: SiteSetting.delete_removed_posts_after), force_new_version: true)
@post.update_column(:user_deleted, true) @post.update_column(:user_deleted, true)
@post.update_flagged_posts_count @post.update_flagged_posts_count
@post.topic_links.each(&:destroy) @post.topic_links.each(&:destroy)

View File

@ -13,6 +13,7 @@ describe PostDestroyer do
describe 'destroy_old_stubs' do describe 'destroy_old_stubs' do
it 'destroys stubs for deleted by user posts' do it 'destroys stubs for deleted by user posts' do
SiteSetting.stubs(:delete_removed_posts_after).returns(24)
Fabricate(:admin) Fabricate(:admin)
topic = post.topic topic = post.topic
reply1 = create_post(topic: topic) reply1 = create_post(topic: topic)
@ -53,6 +54,42 @@ describe PostDestroyer do
reply1.deleted_at.should == nil reply1.deleted_at.should == nil
end end
it 'uses the delete_removed_posts_after site setting' do
Fabricate(:admin)
topic = post.topic
reply1 = create_post(topic: topic)
reply2 = create_post(topic: topic)
PostDestroyer.new(reply1.user, reply1).destroy
PostDestroyer.new(reply2.user, reply2).destroy
SiteSetting.stubs(:delete_removed_posts_after).returns(1)
reply2.update_column(:updated_at, 70.minutes.ago)
PostDestroyer.destroy_stubs
reply1.reload
reply2.reload
reply1.deleted_at.should == nil
reply2.deleted_at.should_not == nil
SiteSetting.stubs(:delete_removed_posts_after).returns(72)
reply1.update_column(:updated_at, 2.days.ago)
PostDestroyer.destroy_stubs
reply1.reload.deleted_at.should == nil
SiteSetting.stubs(:delete_removed_posts_after).returns(47)
PostDestroyer.destroy_stubs
reply1.reload.deleted_at.should_not == nil
end
end end
describe 'basic destroying' do describe 'basic destroying' do
@ -65,10 +102,11 @@ describe PostDestroyer do
end end
it "doesn't delete the post" do it "doesn't delete the post" do
SiteSetting.stubs(:delete_removed_posts_after).returns(24)
post.deleted_at.should be_blank post.deleted_at.should be_blank
post.deleted_by.should be_blank post.deleted_by.should be_blank
post.user_deleted.should be_true post.user_deleted.should be_true
post.raw.should == I18n.t('js.post.deleted_by_author') post.raw.should == I18n.t('js.post.deleted_by_author', {count: 24})
post.version.should == 2 post.version.should == 2
# lets try to recover # lets try to recover

View File

@ -1,3 +1,3 @@
/*jshint maxlen:10000000 */ /*jshint maxlen:10000000 */
Discourse.SiteSettingsOriginal = {"title":"Discourse Meta","logo_url":"/assets/logo.png","logo_small_url":"/assets/logo-single.png","traditional_markdown_linebreaks":false,"top_menu":"latest|new|unread|read|favorited|categories","post_menu":"like|edit|flag|delete|share|bookmark|reply","share_links":"twitter|facebook|google+|email","track_external_right_clicks":false,"must_approve_users":false,"ga_tracking_code":"UA-33736483-2","ga_domain_name":"","enable_long_polling":true,"polling_interval":3000,"anon_polling_interval":30000,"min_post_length":20,"max_post_length":16000,"min_topic_title_length":15,"max_topic_title_length":255,"min_private_message_title_length":2,"allow_uncategorized_topics":true,"min_search_term_length":3,"flush_timings_secs":5,"suppress_reply_directly_below":true,"email_domains_blacklist":"mailinator.com","email_domains_whitelist":null,"version_checks":true,"min_title_similar_length":10,"min_body_similar_length":15,"category_colors":"BF1E2E|F1592A|F7941D|9EB83B|3AB54A|12A89D|25AAE2|0E76BD|652D90|92278F|ED207B|8C6238|231F20|808281|B3B5B4|283890","max_upload_size_kb":1024,"category_featured_topics":6,"favicon_url":"/assets/favicon.ico","dynamic_favicon":false,"uncategorized_name":"uncategorized","uncategorized_color":"AB9364","uncategorized_text_color":"FFFFFF","invite_only":false,"login_required":false,"enable_local_logins":true,"enable_local_account_create":true,"enable_google_logins":true,"enable_yahoo_logins":true,"enable_twitter_logins":true,"enable_facebook_logins":true,"enable_cas_logins":false,"enable_github_logins":true,"enable_persona_logins":true,"educate_until_posts":2,"topic_views_heat_low":1000,"topic_views_heat_medium":2000,"topic_views_heat_high":5000,"min_private_message_post_length":5,"faq_url":"","tos_url":"","privacy_policy_url":"","authorized_extensions":".jpg|.jpeg|.png|.gif|.txt","relative_date_duration":14}; Discourse.SiteSettingsOriginal = {"title":"Discourse Meta","logo_url":"/assets/logo.png","logo_small_url":"/assets/logo-single.png","traditional_markdown_linebreaks":false,"top_menu":"latest|new|unread|read|favorited|categories","post_menu":"like|edit|flag|delete|share|bookmark|reply","share_links":"twitter|facebook|google+|email","track_external_right_clicks":false,"must_approve_users":false,"ga_tracking_code":"UA-33736483-2","ga_domain_name":"","enable_long_polling":true,"polling_interval":3000,"anon_polling_interval":30000,"min_post_length":20,"max_post_length":16000,"min_topic_title_length":15,"max_topic_title_length":255,"min_private_message_title_length":2,"allow_uncategorized_topics":true,"min_search_term_length":3,"flush_timings_secs":5,"suppress_reply_directly_below":true,"email_domains_blacklist":"mailinator.com","email_domains_whitelist":null,"version_checks":true,"min_title_similar_length":10,"min_body_similar_length":15,"category_colors":"BF1E2E|F1592A|F7941D|9EB83B|3AB54A|12A89D|25AAE2|0E76BD|652D90|92278F|ED207B|8C6238|231F20|808281|B3B5B4|283890","max_upload_size_kb":1024,"category_featured_topics":6,"favicon_url":"/assets/favicon.ico","dynamic_favicon":false,"uncategorized_name":"uncategorized","uncategorized_color":"AB9364","uncategorized_text_color":"FFFFFF","invite_only":false,"login_required":false,"enable_local_logins":true,"enable_local_account_create":true,"enable_google_logins":true,"enable_yahoo_logins":true,"enable_twitter_logins":true,"enable_facebook_logins":true,"enable_cas_logins":false,"enable_github_logins":true,"enable_persona_logins":true,"educate_until_posts":2,"topic_views_heat_low":1000,"topic_views_heat_medium":2000,"topic_views_heat_high":5000,"min_private_message_post_length":5,"faq_url":"","tos_url":"","privacy_policy_url":"","authorized_extensions":".jpg|.jpeg|.png|.gif|.txt","relative_date_duration":14,"delete_removed_posts_after":24};
Discourse.SiteSettings = jQuery.extend(true, {}, Discourse.SiteSettingsOriginal); Discourse.SiteSettings = jQuery.extend(true, {}, Discourse.SiteSettingsOriginal);