FIX: Hide delete button to invite as user are unable to delete anyway (#21884)
Moderators are not allowed to delete invites that don't belong to them
This commit is contained in:
parent
6642958706
commit
d2ef490e9a
|
@ -184,24 +184,26 @@
|
|||
{{/if}}
|
||||
</td>
|
||||
|
||||
<td class="invite-actions">
|
||||
<DButton
|
||||
@class="btn-default"
|
||||
@icon="pencil-alt"
|
||||
@action={{action "editInvite" invite}}
|
||||
@title="user.invited.edit"
|
||||
/>
|
||||
<DButton
|
||||
@icon="trash-alt"
|
||||
@class="cancel"
|
||||
@action={{action "destroyInvite" invite}}
|
||||
@title={{if
|
||||
invite.destroyed
|
||||
"user.invited.removed"
|
||||
"user.invited.remove"
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
{{#if invite.can_delete_invite}}
|
||||
<td class="invite-actions">
|
||||
<DButton
|
||||
@class="btn-default"
|
||||
@icon="pencil-alt"
|
||||
@action={{action "editInvite" invite}}
|
||||
@title="user.invited.edit"
|
||||
/>
|
||||
<DButton
|
||||
@icon="trash-alt"
|
||||
@class="cancel"
|
||||
@action={{action "destroyInvite" invite}}
|
||||
@title={{if
|
||||
invite.destroyed
|
||||
"user.invited.removed"
|
||||
"user.invited.remove"
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
{{/if}}
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { click, fillIn, visit } from "@ember/test-helpers";
|
||||
import {
|
||||
acceptance,
|
||||
count,
|
||||
exists,
|
||||
fakeTime,
|
||||
loggedInUser,
|
||||
|
@ -57,15 +56,15 @@ acceptance("Invites - Create & Edit Invite Modal", function (needs) {
|
|||
await visit("/u/eviltrout/invited/pending");
|
||||
await click(".user-invite-buttons .btn:first-child");
|
||||
|
||||
assert.ok(!exists("tbody tr"), "does not show invite before saving");
|
||||
assert
|
||||
.dom("table.user-invite-list tbody tr")
|
||||
.exists({ count: 2 }, "is seeded with two rows");
|
||||
|
||||
await click(".btn-primary");
|
||||
|
||||
assert.strictEqual(
|
||||
count("tbody tr"),
|
||||
1,
|
||||
"adds invite to list after saving"
|
||||
);
|
||||
assert
|
||||
.dom("table.user-invite-list tbody tr")
|
||||
.exists({ count: 3 }, "gets added to the list");
|
||||
});
|
||||
|
||||
test("copying saves invite", async function (assert) {
|
||||
|
|
|
@ -224,7 +224,40 @@ export function applyDefaultHandlers(pretender) {
|
|||
|
||||
pretender.get("/u/eviltrout/invited.json", () => {
|
||||
return response({
|
||||
invites: [],
|
||||
invites: [
|
||||
{
|
||||
id: 8,
|
||||
invite_key: "hMFT8G1oKP",
|
||||
link: "http://localhost:3000/invites/hMFT8G1oKP",
|
||||
email: "steak@cat.com",
|
||||
domain: null,
|
||||
emailed: false,
|
||||
can_delete_invite: true,
|
||||
custom_message: null,
|
||||
created_at: "2023-06-01T04:47:13.195Z",
|
||||
updated_at: "2023-06-01T04:47:13.195Z",
|
||||
expires_at: "2023-08-30T04:47:00.000Z",
|
||||
expired: false,
|
||||
topics: [],
|
||||
groups: [],
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
invite_key: "hMFT8G1WHA",
|
||||
link: "http://localhost:3000/invites/hMFT8G1WHA",
|
||||
email: "tomtom@cat.com",
|
||||
domain: null,
|
||||
emailed: false,
|
||||
can_delete_invite: false,
|
||||
custom_message: null,
|
||||
created_at: "2023-06-01T04:47:13.195Z",
|
||||
updated_at: "2023-06-01T04:47:13.195Z",
|
||||
expires_at: "2023-08-30T04:47:00.000Z",
|
||||
expired: false,
|
||||
topics: [],
|
||||
groups: [],
|
||||
},
|
||||
],
|
||||
can_see_invite_details: true,
|
||||
counts: {
|
||||
pending: 0,
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import { visit } from "@ember/test-helpers";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import { test } from "qunit";
|
||||
|
||||
acceptance("User invites", function (needs) {
|
||||
needs.user();
|
||||
|
||||
test("hides delete button based on can_delete_invite", async function (assert) {
|
||||
await visit("/u/eviltrout/invited");
|
||||
|
||||
assert.dom("table.user-invite-list tbody tr").exists({ count: 2 });
|
||||
assert
|
||||
.dom("table.user-invite-list tbody tr:nth-child(1) button.cancel")
|
||||
.exists();
|
||||
assert
|
||||
.dom("table.user-invite-list tbody tr:nth-child(2) button.cancel")
|
||||
.doesNotExist();
|
||||
});
|
||||
});
|
|
@ -7,6 +7,7 @@ class InviteSerializer < ApplicationSerializer
|
|||
:email,
|
||||
:domain,
|
||||
:emailed,
|
||||
:can_delete_invite,
|
||||
:max_redemptions_allowed,
|
||||
:redemption_count,
|
||||
:custom_message,
|
||||
|
@ -30,6 +31,10 @@ class InviteSerializer < ApplicationSerializer
|
|||
object.emailed_status != Invite.emailed_status_types[:not_required]
|
||||
end
|
||||
|
||||
def can_delete_invite
|
||||
scope.is_admin? || object.invited_by_id == scope.current_user.id
|
||||
end
|
||||
|
||||
def include_custom_message?
|
||||
email.present?
|
||||
end
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe InviteSerializer do
|
||||
describe "#can_delete_invite" do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
fab!(:admin) { Fabricate(:admin) }
|
||||
fab!(:moderator) { Fabricate(:moderator) }
|
||||
fab!(:invite_from_user) { Fabricate(:invite, invited_by: user) }
|
||||
fab!(:invite_from_moderator) { Fabricate(:invite, invited_by: moderator) }
|
||||
|
||||
it "returns true for admin" do
|
||||
serializer = InviteSerializer.new(invite_from_user, scope: Guardian.new(admin), root: false)
|
||||
|
||||
expect(serializer.as_json[:can_delete_invite]).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false for moderator" do
|
||||
serializer =
|
||||
InviteSerializer.new(invite_from_user, scope: Guardian.new(moderator), root: false)
|
||||
|
||||
expect(serializer.as_json[:can_delete_invite]).to eq(false)
|
||||
end
|
||||
|
||||
it "returns true for inviter" do
|
||||
serializer = InviteSerializer.new(invite_from_user, scope: Guardian.new(user), root: false)
|
||||
|
||||
expect(serializer.as_json[:can_delete_invite]).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false for plain user" do
|
||||
serializer =
|
||||
InviteSerializer.new(invite_from_moderator, scope: Guardian.new(user), root: false)
|
||||
|
||||
expect(serializer.as_json[:can_delete_invite]).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue