fix: Add ability to choose user permission level when inviting (#2473)
* Select user role while sending invite * Add tests to check for role * Update app/scenes/Invite.js Co-authored-by: Tom Moor <tom.moor@gmail.com> * Use select * Use inviteUser policy * Remove unnecessary code * Normalize rank/role Fix text sizing of select input, fix alignment on users invite form * Move component to root * cleanup Co-authored-by: Tom Moor <tom.moor@gmail.com>
This commit is contained in:
@@ -181,7 +181,7 @@ router.post("users.demote", auth(), async (ctx) => {
|
||||
const actor = ctx.state.user;
|
||||
ctx.assertPresent(userId, "id is required");
|
||||
|
||||
to = to === "Viewer" ? "Viewer" : "Member";
|
||||
to = to === "viewer" ? "viewer" : "member";
|
||||
|
||||
const user = await User.findByPk(userId);
|
||||
|
||||
@@ -262,7 +262,7 @@ router.post("users.invite", auth(), async (ctx) => {
|
||||
|
||||
const { user } = ctx.state;
|
||||
const team = await Team.findByPk(user.teamId);
|
||||
authorize(user, "invite", team);
|
||||
authorize(user, "inviteUser", team);
|
||||
|
||||
const response = await userInviter({ user, invites, ip: ctx.request.ip });
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ describe("#users.invite", () => {
|
||||
const res = await server.post("/api/users.invite", {
|
||||
body: {
|
||||
token: user.getJwtToken(),
|
||||
invites: [{ email: "test@example.com", name: "Test", guest: false }],
|
||||
invites: [{ email: "test@example.com", name: "Test", role: "member" }],
|
||||
},
|
||||
});
|
||||
const body = await res.json();
|
||||
@@ -168,27 +168,74 @@ describe("#users.invite", () => {
|
||||
});
|
||||
|
||||
it("should require invites to be an array", async () => {
|
||||
const user = await buildUser();
|
||||
const admin = await buildAdmin();
|
||||
const res = await server.post("/api/users.invite", {
|
||||
body: {
|
||||
token: user.getJwtToken(),
|
||||
invites: { email: "test@example.com", name: "Test", guest: false },
|
||||
token: admin.getJwtToken(),
|
||||
invites: { email: "test@example.com", name: "Test", role: "member" },
|
||||
},
|
||||
});
|
||||
expect(res.status).toEqual(400);
|
||||
});
|
||||
|
||||
it("should require admin", async () => {
|
||||
const user = await buildUser();
|
||||
const admin = await buildUser();
|
||||
const res = await server.post("/api/users.invite", {
|
||||
body: {
|
||||
token: user.getJwtToken(),
|
||||
invites: [{ email: "test@example.com", name: "Test", guest: false }],
|
||||
token: admin.getJwtToken(),
|
||||
invites: [{ email: "test@example.com", name: "Test", role: "member" }],
|
||||
},
|
||||
});
|
||||
expect(res.status).toEqual(403);
|
||||
});
|
||||
|
||||
it("should invite user as an admin", async () => {
|
||||
const admin = await buildAdmin();
|
||||
const res = await server.post("/api/users.invite", {
|
||||
body: {
|
||||
token: admin.getJwtToken(),
|
||||
invites: [{ email: "test@example.com", name: "Test", role: "admin" }],
|
||||
},
|
||||
});
|
||||
const body = await res.json();
|
||||
expect(res.status).toEqual(200);
|
||||
expect(body.data.sent.length).toEqual(1);
|
||||
expect(body.data.users[0].isAdmin).toBeTruthy();
|
||||
expect(body.data.users[0].isViewer).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should invite user as a viewer", async () => {
|
||||
const admin = await buildAdmin();
|
||||
const res = await server.post("/api/users.invite", {
|
||||
body: {
|
||||
token: admin.getJwtToken(),
|
||||
invites: [{ email: "test@example.com", name: "Test", role: "viewer" }],
|
||||
},
|
||||
});
|
||||
const body = await res.json();
|
||||
expect(res.status).toEqual(200);
|
||||
expect(body.data.sent.length).toEqual(1);
|
||||
expect(body.data.users[0].isViewer).toBeTruthy();
|
||||
expect(body.data.users[0].isAdmin).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should invite user as a member if role is any arbitary value", async () => {
|
||||
const admin = await buildAdmin();
|
||||
const res = await server.post("/api/users.invite", {
|
||||
body: {
|
||||
token: admin.getJwtToken(),
|
||||
invites: [
|
||||
{ email: "test@example.com", name: "Test", role: "arbitary" },
|
||||
],
|
||||
},
|
||||
});
|
||||
const body = await res.json();
|
||||
expect(res.status).toEqual(200);
|
||||
expect(body.data.sent.length).toEqual(1);
|
||||
expect(body.data.users[0].isViewer).toBeFalsy();
|
||||
expect(body.data.users[0].isAdmin).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should require authentication", async () => {
|
||||
const res = await server.post("/api/users.invite");
|
||||
expect(res.status).toEqual(401);
|
||||
@@ -325,7 +372,7 @@ describe("#users.demote", () => {
|
||||
body: {
|
||||
token: admin.getJwtToken(),
|
||||
id: user.id,
|
||||
to: "Viewer",
|
||||
to: "viewer",
|
||||
},
|
||||
});
|
||||
const body = await res.json();
|
||||
@@ -342,7 +389,7 @@ describe("#users.demote", () => {
|
||||
body: {
|
||||
token: admin.getJwtToken(),
|
||||
id: user.id,
|
||||
to: "Member",
|
||||
to: "member",
|
||||
},
|
||||
});
|
||||
const body = await res.json();
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
// @flow
|
||||
import { uniqBy } from "lodash";
|
||||
import type { Role } from "shared/types";
|
||||
import mailer from "../mailer";
|
||||
import { User, Event, Team } from "../models";
|
||||
|
||||
type Invite = { name: string, email: string };
|
||||
type Invite = {
|
||||
name: string,
|
||||
email: string,
|
||||
role: Role,
|
||||
};
|
||||
|
||||
export default async function userInviter({
|
||||
user,
|
||||
@@ -52,6 +57,8 @@ export default async function userInviter({
|
||||
name: invite.name,
|
||||
email: invite.email,
|
||||
service: null,
|
||||
isAdmin: invite.role === "admin",
|
||||
isViewer: invite.role === "viewer",
|
||||
});
|
||||
users.push(newUser);
|
||||
|
||||
@@ -62,6 +69,7 @@ export default async function userInviter({
|
||||
data: {
|
||||
email: invite.email,
|
||||
name: invite.name,
|
||||
role: invite.role,
|
||||
},
|
||||
ip,
|
||||
});
|
||||
|
||||
@@ -298,7 +298,7 @@ User.getCounts = async function (teamId: string) {
|
||||
|
||||
User.prototype.demote = async function (
|
||||
teamId: string,
|
||||
to: "Member" | "Viewer"
|
||||
to: "member" | "viewer"
|
||||
) {
|
||||
const res = await User.findAndCountAll({
|
||||
where: {
|
||||
@@ -312,9 +312,9 @@ User.prototype.demote = async function (
|
||||
});
|
||||
|
||||
if (res.count >= 1) {
|
||||
if (to === "Member") {
|
||||
if (to === "member") {
|
||||
return this.update({ isAdmin: false, isViewer: false });
|
||||
} else if (to === "Viewer") {
|
||||
} else if (to === "viewer") {
|
||||
return this.update({ isAdmin: false, isViewer: true });
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user