In a private plugin, we need to show an error message containing HTML when the Grant Admin action fails. This change introduces a new flag (`html_message: true`) that when used will allow the dialog to render the HTML tags in the error message correctly.
302 lines
8.3 KiB
JavaScript
302 lines
8.3 KiB
JavaScript
import {
|
|
acceptance,
|
|
exists,
|
|
query,
|
|
} from "discourse/tests/helpers/qunit-helpers";
|
|
import { click, currentURL, fillIn, visit } from "@ember/test-helpers";
|
|
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
|
import { test } from "qunit";
|
|
import I18n from "I18n";
|
|
import { SECOND_FACTOR_METHODS } from "discourse/models/user";
|
|
|
|
const { TOTP, BACKUP_CODE, SECURITY_KEY } = SECOND_FACTOR_METHODS;
|
|
let deleteAndBlock = null;
|
|
|
|
acceptance("Admin - User Index", function (needs) {
|
|
needs.user();
|
|
needs.pretender((server, helper) => {
|
|
server.get("/groups/search.json", () => {
|
|
return helper.response([
|
|
{
|
|
id: 42,
|
|
automatic: false,
|
|
name: "Macdonald",
|
|
user_count: 0,
|
|
alias_level: 99,
|
|
visible: true,
|
|
automatic_membership_email_domains: "",
|
|
primary_group: false,
|
|
title: null,
|
|
grant_trust_level: null,
|
|
has_messages: false,
|
|
flair_url: null,
|
|
flair_bg_color: null,
|
|
flair_color: null,
|
|
bio_raw: null,
|
|
bio_cooked: null,
|
|
public_admission: false,
|
|
allow_membership_requests: true,
|
|
membership_request_template: "Please add me",
|
|
full_name: null,
|
|
},
|
|
]);
|
|
});
|
|
|
|
server.put("/users/sam/preferences/username", () => {
|
|
return helper.response({ id: 2, username: "new-sam" });
|
|
});
|
|
|
|
server.get("/admin/users/3.json", () => {
|
|
return helper.response({
|
|
id: 3,
|
|
username: "user1",
|
|
name: null,
|
|
avatar_template: "/letter_avatar_proxy/v4/letter/b/f0a364/{size}.png",
|
|
active: true,
|
|
admin: false,
|
|
moderator: false,
|
|
can_grant_admin: true,
|
|
can_revoke_admin: false,
|
|
can_grant_moderation: true,
|
|
can_revoke_moderation: false,
|
|
});
|
|
});
|
|
|
|
server.put("/admin/users/3/grant_admin", () => {
|
|
return helper.response({
|
|
success: "OK",
|
|
email_confirmation_required: true,
|
|
});
|
|
});
|
|
|
|
server.get("/admin/users/4.json", () => {
|
|
return helper.response({
|
|
id: 4,
|
|
username: "user2",
|
|
name: null,
|
|
avatar_template: "/letter_avatar_proxy/v4/letter/b/f0a364/{size}.png",
|
|
active: true,
|
|
admin: false,
|
|
moderator: false,
|
|
can_grant_admin: true,
|
|
can_revoke_admin: false,
|
|
can_grant_moderation: true,
|
|
can_revoke_moderation: false,
|
|
});
|
|
});
|
|
|
|
server.put("/admin/users/4/grant_admin", () => {
|
|
return helper.response(403, {
|
|
second_factor_challenge_nonce: "some-nonce",
|
|
});
|
|
});
|
|
|
|
server.get("/session/2fa.json", () => {
|
|
return helper.response(200, {
|
|
totp_enabled: true,
|
|
backup_enabled: true,
|
|
security_keys_enabled: true,
|
|
allowed_methods: [TOTP, BACKUP_CODE, SECURITY_KEY],
|
|
});
|
|
});
|
|
|
|
server.get("/admin/users/5.json", () => {
|
|
return helper.response({
|
|
id: 5,
|
|
username: "user5",
|
|
name: null,
|
|
avatar_template: "/letter_avatar_proxy/v4/letter/b/f0a364/{size}.png",
|
|
active: true,
|
|
can_be_deleted: true,
|
|
post_count: 0,
|
|
});
|
|
});
|
|
|
|
server.delete("/admin/users/5.json", (request) => {
|
|
const data = helper.parsePostData(request.requestBody);
|
|
|
|
if (data.block_email || data.block_ip || data.block_urls) {
|
|
deleteAndBlock = true;
|
|
} else {
|
|
deleteAndBlock = false;
|
|
}
|
|
|
|
return helper.response({});
|
|
});
|
|
|
|
server.get("/admin/users/6.json", () => {
|
|
return helper.response({
|
|
id: 6,
|
|
username: "user6",
|
|
name: null,
|
|
avatar_template: "/letter_avatar_proxy/v4/letter/b/f0a364/{size}.png",
|
|
active: true,
|
|
admin: false,
|
|
moderator: false,
|
|
can_grant_admin: true,
|
|
can_revoke_admin: false,
|
|
});
|
|
});
|
|
|
|
server.put("/admin/users/6/grant_admin", () => {
|
|
return helper.response(403, {
|
|
error: "A message with <strong>bold</strong> text.",
|
|
html_message: true,
|
|
});
|
|
});
|
|
});
|
|
|
|
needs.hooks.beforeEach(() => {
|
|
deleteAndBlock = null;
|
|
});
|
|
|
|
test("can edit username", async function (assert) {
|
|
await visit("/admin/users/2/sam");
|
|
|
|
assert.strictEqual(
|
|
query(".display-row.username .value").innerText.trim(),
|
|
"sam"
|
|
);
|
|
|
|
// Trying cancel.
|
|
await click(".display-row.username button");
|
|
await fillIn(".display-row.username .value input", "new-sam");
|
|
await click(".display-row.username a");
|
|
assert.strictEqual(
|
|
query(".display-row.username .value").innerText.trim(),
|
|
"sam"
|
|
);
|
|
|
|
// Doing edit.
|
|
await click(".display-row.username button");
|
|
await fillIn(".display-row.username .value input", "new-sam");
|
|
await click(".display-row.username button");
|
|
assert.strictEqual(
|
|
query(".display-row.username .value").innerText.trim(),
|
|
"new-sam"
|
|
);
|
|
});
|
|
|
|
test("shows the number of post edits", async function (assert) {
|
|
await visit("/admin/users/1/eviltrout");
|
|
|
|
assert.strictEqual(query(".post-edits-count .value").innerText.trim(), "6");
|
|
|
|
assert.ok(
|
|
exists(".post-edits-count .controls .btn.btn-icon"),
|
|
"View edits button exists"
|
|
);
|
|
});
|
|
|
|
test("a link to view post edits report exists", async function (assert) {
|
|
await visit("/admin/users/1/eviltrout");
|
|
|
|
let filter = encodeURIComponent('{"editor":"eviltrout"}');
|
|
|
|
await click(".post-edits-count .controls .btn.btn-icon");
|
|
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/admin/reports/post_edits?filters=${filter}`,
|
|
"it redirects to the right admin report"
|
|
);
|
|
});
|
|
|
|
test("hides the 'view Edits' button if the count is zero", async function (assert) {
|
|
await visit("/admin/users/2/sam");
|
|
|
|
assert.ok(
|
|
!exists(".post-edits-count .controls .btn.btn-icon"),
|
|
"View Edits button not present"
|
|
);
|
|
});
|
|
|
|
test("will clear unsaved groups when switching user", async function (assert) {
|
|
await visit("/admin/users/2/sam");
|
|
|
|
assert.strictEqual(
|
|
query(".display-row.username .value").innerText.trim(),
|
|
"sam",
|
|
"the name should be correct"
|
|
);
|
|
|
|
const groupChooser = selectKit(".group-chooser");
|
|
await groupChooser.expand();
|
|
await groupChooser.selectRowByValue(42);
|
|
assert.strictEqual(
|
|
groupChooser.header().value(),
|
|
"42",
|
|
"group should be set"
|
|
);
|
|
|
|
await visit("/admin/users/1/eviltrout");
|
|
|
|
assert.strictEqual(
|
|
query(".display-row.username .value").innerText.trim(),
|
|
"eviltrout",
|
|
"the name should be correct"
|
|
);
|
|
|
|
assert.ok(
|
|
!exists('.group-chooser span[title="Macdonald"]'),
|
|
"group should not be set"
|
|
);
|
|
});
|
|
|
|
test("grant admin - shows the confirmation dialog", async function (assert) {
|
|
await visit("/admin/users/3/user1");
|
|
await click(".grant-admin");
|
|
assert.ok(exists(".dialog-content"));
|
|
assert.strictEqual(
|
|
I18n.t("admin.user.grant_admin_confirm"),
|
|
query(".dialog-body").textContent.trim()
|
|
);
|
|
|
|
await click(".dialog-footer .btn-primary");
|
|
});
|
|
|
|
test("grant admin - optionally allows HTML to be shown in the confirmation dialog", async function (assert) {
|
|
await visit("/admin/users/6/user6");
|
|
await click(".grant-admin");
|
|
assert.ok(exists(".dialog-content"));
|
|
|
|
assert.ok(
|
|
exists(".dialog-content .dialog-body strong"),
|
|
"HTML is rendered in the dialog"
|
|
);
|
|
});
|
|
|
|
test("grant admin - redirects to the 2fa page", async function (assert) {
|
|
await visit("/admin/users/4/user2");
|
|
await click(".grant-admin");
|
|
assert.equal(
|
|
currentURL(),
|
|
"/session/2fa?nonce=some-nonce",
|
|
"user is redirected to the 2FA page"
|
|
);
|
|
});
|
|
|
|
test("delete user - delete without blocking works as expected", async function (assert) {
|
|
await visit("/admin/users/5/user5");
|
|
await click(".btn-user-delete");
|
|
|
|
assert.equal(
|
|
query("#dialog-title").textContent,
|
|
I18n.t("admin.user.delete_confirm_title"),
|
|
"dialog has a title"
|
|
);
|
|
|
|
await click(".dialog-footer .btn-primary");
|
|
|
|
assert.notOk(deleteAndBlock, "user does not get blocked");
|
|
});
|
|
|
|
test("delete user - delete and block works as expected", async function (assert) {
|
|
await visit("/admin/users/5/user5");
|
|
await click(".btn-user-delete");
|
|
await click(".dialog-footer .btn-danger");
|
|
|
|
assert.ok(deleteAndBlock, "user does not get blocked");
|
|
});
|
|
});
|