feat: Improved viewers popover (#2106)
* refactoring popover * feat: DocumentViews popover * i18n * fix: tab focus warnings * test: Add tests around users.info changes * snapshots
This commit is contained in:
@ -23,6 +23,7 @@ Object {
|
||||
"demote": true,
|
||||
"promote": true,
|
||||
"read": true,
|
||||
"readDetails": true,
|
||||
"suspend": true,
|
||||
"update": false,
|
||||
},
|
||||
@ -74,39 +75,7 @@ Object {
|
||||
"demote": true,
|
||||
"promote": true,
|
||||
"read": true,
|
||||
"suspend": true,
|
||||
"update": false,
|
||||
},
|
||||
"id": "46fde1d4-0050-428f-9f0b-0bf77f4bdf61",
|
||||
},
|
||||
],
|
||||
"status": 200,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`#users.demote should demote an admin to viewer 1`] = `
|
||||
Object {
|
||||
"data": Object {
|
||||
"avatarUrl": "https://tiley.herokuapp.com/avatar/111d68d06e2d317b5a59c2c6c5bad808/U.png",
|
||||
"createdAt": "2018-01-02T00:00:00.000Z",
|
||||
"email": "user1@example.com",
|
||||
"id": "46fde1d4-0050-428f-9f0b-0bf77f4bdf61",
|
||||
"isAdmin": false,
|
||||
"isSuspended": false,
|
||||
"isViewer": true,
|
||||
"language": "en_US",
|
||||
"lastActiveAt": null,
|
||||
"name": "User 1",
|
||||
},
|
||||
"ok": true,
|
||||
"policies": Array [
|
||||
Object {
|
||||
"abilities": Object {
|
||||
"activate": true,
|
||||
"delete": true,
|
||||
"demote": true,
|
||||
"promote": true,
|
||||
"read": true,
|
||||
"readDetails": true,
|
||||
"suspend": true,
|
||||
"update": false,
|
||||
},
|
||||
@ -140,6 +109,41 @@ Object {
|
||||
"demote": true,
|
||||
"promote": true,
|
||||
"read": true,
|
||||
"readDetails": true,
|
||||
"suspend": true,
|
||||
"update": false,
|
||||
},
|
||||
"id": "46fde1d4-0050-428f-9f0b-0bf77f4bdf61",
|
||||
},
|
||||
],
|
||||
"status": 200,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`#users.demote should demote an admin to viewer 1`] = `
|
||||
Object {
|
||||
"data": Object {
|
||||
"avatarUrl": "https://tiley.herokuapp.com/avatar/111d68d06e2d317b5a59c2c6c5bad808/U.png",
|
||||
"createdAt": "2018-01-02T00:00:00.000Z",
|
||||
"email": "user1@example.com",
|
||||
"id": "46fde1d4-0050-428f-9f0b-0bf77f4bdf61",
|
||||
"isAdmin": false,
|
||||
"isSuspended": false,
|
||||
"isViewer": true,
|
||||
"language": "en_US",
|
||||
"lastActiveAt": null,
|
||||
"name": "User 1",
|
||||
},
|
||||
"ok": true,
|
||||
"policies": Array [
|
||||
Object {
|
||||
"abilities": Object {
|
||||
"activate": true,
|
||||
"delete": true,
|
||||
"demote": true,
|
||||
"promote": true,
|
||||
"read": true,
|
||||
"readDetails": true,
|
||||
"suspend": true,
|
||||
"update": false,
|
||||
},
|
||||
@ -191,6 +195,7 @@ Object {
|
||||
"demote": true,
|
||||
"promote": false,
|
||||
"read": true,
|
||||
"readDetails": true,
|
||||
"suspend": true,
|
||||
"update": false,
|
||||
},
|
||||
@ -251,6 +256,7 @@ Object {
|
||||
"demote": false,
|
||||
"promote": false,
|
||||
"read": true,
|
||||
"readDetails": true,
|
||||
"suspend": true,
|
||||
"update": false,
|
||||
},
|
||||
|
@ -10,7 +10,7 @@ import { presentUser, presentPolicies } from "../presenters";
|
||||
import { Op } from "../sequelize";
|
||||
import pagination from "./middlewares/pagination";
|
||||
|
||||
const { authorize } = policy;
|
||||
const { can, authorize } = policy;
|
||||
const router = new Router();
|
||||
|
||||
router.post("users.list", auth(), pagination(), async (ctx) => {
|
||||
@ -23,10 +23,10 @@ router.post("users.list", auth(), pagination(), async (ctx) => {
|
||||
if (direction !== "ASC") direction = "DESC";
|
||||
ctx.assertSort(sort, User);
|
||||
|
||||
const user = ctx.state.user;
|
||||
const actor = ctx.state.user;
|
||||
|
||||
let where = {
|
||||
teamId: user.teamId,
|
||||
teamId: actor.teamId,
|
||||
};
|
||||
|
||||
if (!includeSuspended) {
|
||||
@ -56,10 +56,10 @@ router.post("users.list", auth(), pagination(), async (ctx) => {
|
||||
|
||||
ctx.body = {
|
||||
pagination: ctx.state.pagination,
|
||||
data: users.map((listUser) =>
|
||||
presentUser(listUser, { includeDetails: user.isAdmin })
|
||||
data: users.map((user) =>
|
||||
presentUser(user, { includeDetails: can(actor, "readDetails", user) })
|
||||
),
|
||||
policies: presentPolicies(user, users),
|
||||
policies: presentPolicies(actor, users),
|
||||
};
|
||||
});
|
||||
|
||||
@ -75,11 +75,17 @@ router.post("users.count", auth(), async (ctx) => {
|
||||
});
|
||||
|
||||
router.post("users.info", auth(), async (ctx) => {
|
||||
const { user } = ctx.state;
|
||||
const { id } = ctx.body;
|
||||
const actor = ctx.state.user;
|
||||
|
||||
const user = id ? await User.findByPk(id) : actor;
|
||||
authorize(actor, "read", user);
|
||||
|
||||
const includeDetails = can(actor, "readDetails", user);
|
||||
|
||||
ctx.body = {
|
||||
data: presentUser(user),
|
||||
policies: presentPolicies(user, [user]),
|
||||
data: presentUser(user, { includeDetails }),
|
||||
policies: presentPolicies(actor, [user]),
|
||||
};
|
||||
});
|
||||
|
||||
@ -128,8 +134,10 @@ router.post("users.promote", auth(), async (ctx) => {
|
||||
ip: ctx.request.ip,
|
||||
});
|
||||
|
||||
const includeDetails = can(actor, "readDetails", user);
|
||||
|
||||
ctx.body = {
|
||||
data: presentUser(user, { includeDetails: true }),
|
||||
data: presentUser(user, { includeDetails }),
|
||||
policies: presentPolicies(actor, [user]),
|
||||
};
|
||||
});
|
||||
@ -159,8 +167,10 @@ router.post("users.demote", auth(), async (ctx) => {
|
||||
ip: ctx.request.ip,
|
||||
});
|
||||
|
||||
const includeDetails = can(actor, "readDetails", user);
|
||||
|
||||
ctx.body = {
|
||||
data: presentUser(user, { includeDetails: true }),
|
||||
data: presentUser(user, { includeDetails }),
|
||||
policies: presentPolicies(actor, [user]),
|
||||
};
|
||||
});
|
||||
@ -179,8 +189,10 @@ router.post("users.suspend", auth(), async (ctx) => {
|
||||
ip: ctx.request.ip,
|
||||
});
|
||||
|
||||
const includeDetails = can(actor, "readDetails", user);
|
||||
|
||||
ctx.body = {
|
||||
data: presentUser(user, { includeDetails: true }),
|
||||
data: presentUser(user, { includeDetails }),
|
||||
policies: presentPolicies(actor, [user]),
|
||||
};
|
||||
});
|
||||
@ -205,8 +217,10 @@ router.post("users.activate", auth(), async (ctx) => {
|
||||
ip: ctx.request.ip,
|
||||
});
|
||||
|
||||
const includeDetails = can(actor, "readDetails", user);
|
||||
|
||||
ctx.body = {
|
||||
data: presentUser(user, { includeDetails: true }),
|
||||
data: presentUser(user, { includeDetails }),
|
||||
policies: presentPolicies(actor, [user]),
|
||||
};
|
||||
});
|
||||
|
@ -87,7 +87,7 @@ describe("#users.list", () => {
|
||||
});
|
||||
|
||||
describe("#users.info", () => {
|
||||
it("should return known user", async () => {
|
||||
it("should return current user with no id", async () => {
|
||||
const user = await buildUser();
|
||||
const res = await server.post("/api/users.info", {
|
||||
body: { token: user.getJwtToken() },
|
||||
@ -97,6 +97,33 @@ describe("#users.info", () => {
|
||||
expect(res.status).toEqual(200);
|
||||
expect(body.data.id).toEqual(user.id);
|
||||
expect(body.data.name).toEqual(user.name);
|
||||
expect(body.data.email).toEqual(user.email);
|
||||
});
|
||||
|
||||
it("should return user with permission", async () => {
|
||||
const user = await buildUser();
|
||||
const another = await buildUser({ teamId: user.teamId });
|
||||
const res = await server.post("/api/users.info", {
|
||||
body: { token: user.getJwtToken(), id: another.id },
|
||||
});
|
||||
const body = await res.json();
|
||||
|
||||
expect(res.status).toEqual(200);
|
||||
expect(body.data.id).toEqual(another.id);
|
||||
expect(body.data.name).toEqual(another.name);
|
||||
|
||||
// no emails of other users
|
||||
expect(body.data.email).toEqual(undefined);
|
||||
});
|
||||
|
||||
it("should now return user without permission", async () => {
|
||||
const user = await buildUser();
|
||||
const another = await buildUser();
|
||||
const res = await server.post("/api/users.info", {
|
||||
body: { token: user.getJwtToken(), id: another.id },
|
||||
});
|
||||
|
||||
expect(res.status).toEqual(403);
|
||||
});
|
||||
|
||||
it("should require authentication", async () => {
|
||||
|
Reference in New Issue
Block a user