FEATURE: Allow category moderators to set auto deletion topic timers (#19383)

Co-authored-by: Penar Musaraj <pmusaraj@gmail.com>
This commit is contained in:
Rafael dos Santos Silva 2022-12-08 17:14:43 -03:00 committed by GitHub
parent 86d49f4fb1
commit 9f3760cfd8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 102 additions and 3 deletions

View File

@ -47,7 +47,7 @@ export default Controller.extend(ModalFunctionality, {
}); });
} }
if (this.currentUser.staff) { if (this.model.details.can_delete) {
types.push({ types.push({
id: DELETE_STATUS_TYPE, id: DELETE_STATUS_TYPE,
name: I18n.t("topic.auto_delete.title"), name: I18n.t("topic.auto_delete.title"),
@ -59,7 +59,7 @@ export default Controller.extend(ModalFunctionality, {
name: I18n.t("topic.auto_bump.title"), name: I18n.t("topic.auto_bump.title"),
}); });
if (this.currentUser.staff) { if (this.model.details.can_delete) {
types.push({ types.push({
id: DELETE_REPLIES_TYPE, id: DELETE_REPLIES_TYPE,
name: I18n.t("topic.auto_delete_replies.title"), name: I18n.t("topic.auto_delete_replies.title"),

View File

@ -11,6 +11,8 @@ import { click, fillIn, visit } from "@ember/test-helpers";
import { test } from "qunit"; import { test } from "qunit";
import selectKit from "discourse/tests/helpers/select-kit-helper"; import selectKit from "discourse/tests/helpers/select-kit-helper";
import I18n from "I18n"; import I18n from "I18n";
import { cloneJSON } from "discourse-common/lib/object";
import topicFixtures from "discourse/tests/fixtures/topic";
acceptance("Topic - Edit timer", function (needs) { acceptance("Topic - Edit timer", function (needs) {
let clock = null; let clock = null;
@ -28,6 +30,10 @@ acceptance("Topic - Edit timer", function (needs) {
category_id: null, category_id: null,
}) })
); );
const topicResponse = cloneJSON(topicFixtures["/t/54077.json"]);
topicResponse.details.can_delete = false;
server.get("/t/54077.json", () => helper.response(topicResponse));
}); });
needs.hooks.beforeEach(() => { needs.hooks.beforeEach(() => {
@ -294,7 +300,7 @@ acceptance("Topic - Edit timer", function (needs) {
test("TL4 can't auto-delete", async function (assert) { test("TL4 can't auto-delete", async function (assert) {
updateCurrentUser({ moderator: false, admin: false, trust_level: 4 }); updateCurrentUser({ moderator: false, admin: false, trust_level: 4 });
await visit("/t/internationalization-localization"); await visit("/t/short-topic-with-two-posts/54077");
await click(".toggle-admin-menu"); await click(".toggle-admin-menu");
await click(".admin-topic-timer-update button"); await click(".admin-topic-timer-update button");
@ -305,6 +311,48 @@ acceptance("Topic - Edit timer", function (needs) {
assert.ok(!timerType.rowByValue("delete").exists()); assert.ok(!timerType.rowByValue("delete").exists());
}); });
test("Category Moderator can auto-delete replies", async function (assert) {
updateCurrentUser({ moderator: false, admin: false, trust_level: 4 });
await visit("/t/internationalization-localization");
await click(".toggle-admin-menu");
await click(".admin-topic-timer-update button");
const timerType = selectKit(".select-kit.timer-type");
await timerType.expand();
assert.ok(timerType.rowByValue("delete_replies").exists());
});
test("TL4 can't auto-delete replies", async function (assert) {
updateCurrentUser({ moderator: false, admin: false, trust_level: 4 });
await visit("/t/short-topic-with-two-posts/54077");
await click(".toggle-admin-menu");
await click(".admin-topic-timer-update button");
const timerType = selectKit(".select-kit.timer-type");
await timerType.expand();
assert.ok(!timerType.rowByValue("delete_replies").exists());
});
test("Category Moderator can auto-delete", async function (assert) {
updateCurrentUser({ moderator: false, admin: false, trust_level: 4 });
await visit("/t/internationalization-localization");
await click(".toggle-admin-menu");
await click(".admin-topic-timer-update button");
const timerType = selectKit(".select-kit.timer-type");
await timerType.expand();
assert.ok(timerType.rowByValue("delete").exists());
});
test("auto delete", async function (assert) { test("auto delete", async function (assert) {
updateCurrentUser({ moderator: true }); updateCurrentUser({ moderator: true });
const timerType = selectKit(".select-kit.timer-type"); const timerType = selectKit(".select-kit.timer-type");

View File

@ -497,6 +497,10 @@ class TopicsController < ApplicationController
topic = Topic.find_by(id: params[:topic_id]) topic = Topic.find_by(id: params[:topic_id])
guardian.ensure_can_moderate!(topic) guardian.ensure_can_moderate!(topic)
if TopicTimer.destructive_types.values.include?(status_type)
guardian.ensure_can_delete!(topic)
end
options = { options = {
by_user: current_user, by_user: current_user,
based_on_last_post: based_on_last_post based_on_last_post: based_on_last_post

View File

@ -98,6 +98,10 @@ class TopicTimer < ActiveRecord::Base
@_private_types ||= types.only(:reminder, :clear_slow_mode) @_private_types ||= types.only(:reminder, :clear_slow_mode)
end end
def self.destructive_types
@_destructive_types ||= types.only(:delete, :delete_replies)
end
def public_type? def public_type?
!!self.class.public_types[self.status_type] !!self.class.public_types[self.status_type]
end end

View File

@ -3999,6 +3999,9 @@ RSpec.describe TopicsController do
end end
context 'when logged in as a TL4 user' do context 'when logged in as a TL4 user' do
before do
SiteSetting.enable_category_group_moderation = true
end
it "raises an error if the user can't see the topic" do it "raises an error if the user can't see the topic" do
user.update!(trust_level: TrustLevel[4]) user.update!(trust_level: TrustLevel[4])
sign_in(user) sign_in(user)
@ -4013,6 +4016,46 @@ RSpec.describe TopicsController do
expect(response.status).to eq(403) expect(response.status).to eq(403)
expect(response.parsed_body["error_type"]).to eq('invalid_access') expect(response.parsed_body["error_type"]).to eq('invalid_access')
end end
it "allows a category moderator to create a delete timer" do
user.update!(trust_level: TrustLevel[4])
topic.category.update!(reviewable_by_group: user.groups.first)
sign_in(user)
post "/t/#{topic.id}/timer.json", params: {
time: 10,
status_type: 'delete'
}
expect(response.status).to eq(200)
end
it "raises an error setting a delete timer" do
user.update!(trust_level: TrustLevel[4])
sign_in(user)
post "/t/#{topic.id}/timer.json", params: {
time: 10,
status_type: 'delete'
}
expect(response.status).to eq(403)
expect(response.parsed_body["error_type"]).to eq('invalid_access')
end
it "raises an error setting delete_replies timer" do
user.update!(trust_level: TrustLevel[4])
sign_in(user)
post "/t/#{topic.id}/timer.json", params: {
time: 10,
status_type: 'delete_replies'
}
expect(response.status).to eq(403)
expect(response.parsed_body["error_type"]).to eq('invalid_access')
end
end end
end end