mirror of
https://github.com/discourse/discourse.git
synced 2025-03-20 04:45:35 +08:00
FEATURE: Add a messages view for all official warnings of a user (#12659)
Moderators are allowed to see the warnings list, with an access warning. https://meta.discourse.org/t/why-arent-warnings-easily-accessible-like-suspensions-are/164043
This commit is contained in:
parent
7d8483f698
commit
c780ae9d25
@ -5,6 +5,7 @@ import I18n from "I18n";
|
|||||||
import Topic from "discourse/models/topic";
|
import Topic from "discourse/models/topic";
|
||||||
import bootbox from "bootbox";
|
import bootbox from "bootbox";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
import { VIEW_NAME_WARNINGS } from "discourse/routes/user-private-messages-warnings";
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
userTopicsList: controller("user-topics-list"),
|
userTopicsList: controller("user-topics-list"),
|
||||||
@ -27,6 +28,11 @@ export default Controller.extend({
|
|||||||
return bulkSelectEnabled && selected && selected.length > 0;
|
return bulkSelectEnabled && selected && selected.length > 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@discourseComputed("viewingSelf", "pmView", "currentUser.admin")
|
||||||
|
showWarningsWarning(viewingSelf, pmView, isAdmin) {
|
||||||
|
return pmView === VIEW_NAME_WARNINGS && !viewingSelf && !isAdmin;
|
||||||
|
},
|
||||||
|
|
||||||
bulkOperation(operation) {
|
bulkOperation(operation) {
|
||||||
const selected = this.selected;
|
const selected = this.selected;
|
||||||
let params = { type: operation };
|
let params = { type: operation };
|
||||||
|
@ -149,6 +149,7 @@ export default function () {
|
|||||||
function () {
|
function () {
|
||||||
this.route("sent");
|
this.route("sent");
|
||||||
this.route("archive");
|
this.route("archive");
|
||||||
|
this.route("warnings");
|
||||||
this.route("group", { path: "group/:name" });
|
this.route("group", { path: "group/:name" });
|
||||||
this.route("groupArchive", { path: "group/:name/archive" });
|
this.route("groupArchive", { path: "group/:name/archive" });
|
||||||
this.route("tags");
|
this.route("tags");
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
import createPMRoute from "discourse/routes/build-private-messages-route";
|
||||||
|
|
||||||
|
export const VIEW_NAME_WARNINGS = "warnings";
|
||||||
|
|
||||||
|
export default createPMRoute(
|
||||||
|
VIEW_NAME_WARNINGS,
|
||||||
|
"private-messages-warnings",
|
||||||
|
null /* no message bus notifications */
|
||||||
|
);
|
@ -38,7 +38,11 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if model.warnings_received_count}}
|
{{#if model.warnings_received_count}}
|
||||||
<div><span class="warnings-received">{{model.warnings_received_count}}</span>{{i18n "user.staff_counters.warnings_received"}}</div>
|
<div>
|
||||||
|
{{#link-to "userPrivateMessages.warnings" model}}
|
||||||
|
<span class="warnings-received">{{model.warnings_received_count}}</span>{{i18n "user.staff_counters.warnings_received"}}
|
||||||
|
{{/link-to}}
|
||||||
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -87,5 +87,8 @@
|
|||||||
}}
|
}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
{{#if showWarningsWarning}}
|
||||||
|
<div class="alert alert-info">{{html-safe (i18n "admin.user.warnings_list_warning")}}</div>
|
||||||
|
{{/if}}
|
||||||
{{outlet}}
|
{{outlet}}
|
||||||
</section>
|
</section>
|
||||||
|
@ -121,3 +121,18 @@ acceptance(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
acceptance("User Routes - Moderator viewing warnings", function (needs) {
|
||||||
|
needs.user({
|
||||||
|
username: "notEviltrout",
|
||||||
|
moderator: true,
|
||||||
|
staff: true,
|
||||||
|
admin: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Messages - Warnings", async function (assert) {
|
||||||
|
await visit("/u/eviltrout/messages/warnings");
|
||||||
|
assert.ok($("body.user-messages-page").length, "has the body class");
|
||||||
|
assert.ok($("div.alert-info").length, "has the permissions alert");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -210,6 +210,10 @@ export function applyDefaultHandlers(pretender) {
|
|||||||
return response(fixturesByUrl["/topics/private-messages/eviltrout.json"]);
|
return response(fixturesByUrl["/topics/private-messages/eviltrout.json"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pretender.get("/topics/private-messages-warnings/eviltrout.json", () => {
|
||||||
|
return response(fixturesByUrl["/topics/private-messages/eviltrout.json"]);
|
||||||
|
});
|
||||||
|
|
||||||
pretender.get("/topics/feature_stats.json", () => {
|
pretender.get("/topics/feature_stats.json", () => {
|
||||||
return response({
|
return response({
|
||||||
pinned_in_category_count: 0,
|
pinned_in_category_count: 0,
|
||||||
|
@ -168,7 +168,12 @@ class ListController < ApplicationController
|
|||||||
|
|
||||||
def message_route(action)
|
def message_route(action)
|
||||||
target_user = fetch_user_from_params({ include_inactive: current_user.try(:staff?) }, [:user_stat, :user_option])
|
target_user = fetch_user_from_params({ include_inactive: current_user.try(:staff?) }, [:user_stat, :user_option])
|
||||||
|
case action
|
||||||
|
when :private_messages_warnings
|
||||||
|
guardian.ensure_can_see_warnings!(target_user)
|
||||||
|
else
|
||||||
guardian.ensure_can_see_private_messages!(target_user.id)
|
guardian.ensure_can_see_private_messages!(target_user.id)
|
||||||
|
end
|
||||||
list_opts = build_topic_list_options
|
list_opts = build_topic_list_options
|
||||||
list = generate_list_for(action.to_s, target_user, list_opts)
|
list = generate_list_for(action.to_s, target_user, list_opts)
|
||||||
url_prefix = "topics"
|
url_prefix = "topics"
|
||||||
@ -185,6 +190,7 @@ class ListController < ApplicationController
|
|||||||
private_messages_group
|
private_messages_group
|
||||||
private_messages_group_archive
|
private_messages_group_archive
|
||||||
private_messages_tag
|
private_messages_tag
|
||||||
|
private_messages_warnings
|
||||||
}.each do |action|
|
}.each do |action|
|
||||||
generate_message_route(action)
|
generate_message_route(action)
|
||||||
end
|
end
|
||||||
|
@ -1177,6 +1177,7 @@ en:
|
|||||||
failed_to_move: "Failed to move selected messages (perhaps your network is down)"
|
failed_to_move: "Failed to move selected messages (perhaps your network is down)"
|
||||||
select_all: "Select All"
|
select_all: "Select All"
|
||||||
tags: "Tags"
|
tags: "Tags"
|
||||||
|
warnings: "Official Warnings"
|
||||||
|
|
||||||
preferences_nav:
|
preferences_nav:
|
||||||
account: "Account"
|
account: "Account"
|
||||||
@ -4912,6 +4913,8 @@ en:
|
|||||||
flags_given_count: Flags Given
|
flags_given_count: Flags Given
|
||||||
flags_received_count: Flags Received
|
flags_received_count: Flags Received
|
||||||
warnings_received_count: Warnings Received
|
warnings_received_count: Warnings Received
|
||||||
|
warnings_list_warning: |
|
||||||
|
As a moderator, you may not be able to view all of these topics. If necessary, ask an admin or the issuing moderator to give <b>@moderators</b> access to the message.
|
||||||
flags_given_received_count: "Flags Given / Received"
|
flags_given_received_count: "Flags Given / Received"
|
||||||
approve: "Approve"
|
approve: "Approve"
|
||||||
approved_by: "approved by"
|
approved_by: "approved by"
|
||||||
|
@ -762,6 +762,7 @@ Discourse::Application.routes.draw do
|
|||||||
get "private-messages-archive/:username" => "list#private_messages_archive", as: "topics_private_messages_archive", defaults: { format: :json }
|
get "private-messages-archive/:username" => "list#private_messages_archive", as: "topics_private_messages_archive", defaults: { format: :json }
|
||||||
get "private-messages-unread/:username" => "list#private_messages_unread", as: "topics_private_messages_unread", defaults: { format: :json }
|
get "private-messages-unread/:username" => "list#private_messages_unread", as: "topics_private_messages_unread", defaults: { format: :json }
|
||||||
get "private-messages-tags/:username/:tag_id.json" => "list#private_messages_tag", as: "topics_private_messages_tag", defaults: { format: :json }
|
get "private-messages-tags/:username/:tag_id.json" => "list#private_messages_tag", as: "topics_private_messages_tag", defaults: { format: :json }
|
||||||
|
get "private-messages-warnings/:username" => "list#private_messages_warnings", as: "topics_private_messages_warnings", defaults: { format: :json }
|
||||||
get "groups/:group_name" => "list#group_topics", as: "group_topics", group_name: RouteFormat.username
|
get "groups/:group_name" => "list#group_topics", as: "group_topics", group_name: RouteFormat.username
|
||||||
|
|
||||||
scope "/private-messages-group/:username", group_name: RouteFormat.username do
|
scope "/private-messages-group/:username", group_name: RouteFormat.username do
|
||||||
|
@ -84,6 +84,10 @@ module UserGuardian
|
|||||||
can_merge_user?(source_user) && !target_user.nil?
|
can_merge_user?(source_user) && !target_user.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def can_see_warnings?(user)
|
||||||
|
user && (is_me?(user) || is_staff?)
|
||||||
|
end
|
||||||
|
|
||||||
def can_reset_bounce_score?(user)
|
def can_reset_bounce_score?(user)
|
||||||
user && is_staff?
|
user && is_staff?
|
||||||
end
|
end
|
||||||
|
@ -365,6 +365,14 @@ class TopicQuery
|
|||||||
create_list(:private_messages, {}, list)
|
create_list(:private_messages, {}, list)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def list_private_messages_warnings(user)
|
||||||
|
list = private_messages_for(user, :user)
|
||||||
|
list = list.where('topics.subtype = ?', TopicSubtype.moderator_warning)
|
||||||
|
# Exclude official warnings that the user created, instead of received
|
||||||
|
list = list.where('topics.user_id <> ?', user.id)
|
||||||
|
create_list(:private_messages, {}, list)
|
||||||
|
end
|
||||||
|
|
||||||
def list_category_topic_ids(category)
|
def list_category_topic_ids(category)
|
||||||
query = default_results(category: category.id)
|
query = default_results(category: category.id)
|
||||||
pinned_ids = query.where('topics.pinned_at IS NOT NULL AND topics.category_id = ?', category.id).limit(nil).order('pinned_at DESC').pluck(:id)
|
pinned_ids = query.where('topics.pinned_at IS NOT NULL AND topics.category_id = ?', category.id).limit(nil).order('pinned_at DESC').pluck(:id)
|
||||||
|
@ -703,6 +703,58 @@ RSpec.describe ListController do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#private_messages_warnings" do
|
||||||
|
let(:target_user) { Fabricate(:user) }
|
||||||
|
let(:admin) { Fabricate(:admin) }
|
||||||
|
let(:moderator1) { Fabricate(:moderator) }
|
||||||
|
let(:moderator2) { Fabricate(:moderator) }
|
||||||
|
|
||||||
|
let(:create_args) do
|
||||||
|
{ title: 'you need a warning buddy!',
|
||||||
|
raw: "you did something bad and I'm telling you about it!",
|
||||||
|
is_warning: true,
|
||||||
|
target_usernames: target_user.username,
|
||||||
|
archetype: Archetype.private_message }
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:warning_post) do
|
||||||
|
creator = PostCreator.new(moderator1, create_args)
|
||||||
|
creator.create
|
||||||
|
end
|
||||||
|
let(:warning_topic) { warning_post.topic }
|
||||||
|
|
||||||
|
before do
|
||||||
|
warning_topic
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns 403 error for unrelated users" do
|
||||||
|
sign_in(Fabricate(:user))
|
||||||
|
get "/topics/private-messages-warnings/#{target_user.username}.json"
|
||||||
|
expect(response.status).to eq(403)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "shows the warning to moderators and admins" do
|
||||||
|
[moderator1, moderator2, admin].each do |viewer|
|
||||||
|
sign_in(viewer)
|
||||||
|
get "/topics/private-messages-warnings/#{target_user.username}.json"
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
json = response.parsed_body
|
||||||
|
expect(json["topic_list"]["topics"].size).to eq(1)
|
||||||
|
expect(json["topic_list"]["topics"][0]["id"]).to eq(warning_topic.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not show the warning as applying to the authoring moderator" do
|
||||||
|
sign_in(admin)
|
||||||
|
get "/topics/private-messages-warnings/#{moderator1.username}.json"
|
||||||
|
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
json = response.parsed_body
|
||||||
|
expect(json["topic_list"]["topics"].size).to eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'read' do
|
describe 'read' do
|
||||||
it 'raises an error when not logged in' do
|
it 'raises an error when not logged in' do
|
||||||
get "/read"
|
get "/read"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user