diff --git a/server/routes/api/users/schema.ts b/server/routes/api/users/schema.ts index b4db432e4..290f82db4 100644 --- a/server/routes/api/users/schema.ts +++ b/server/routes/api/users/schema.ts @@ -25,6 +25,8 @@ export const UsersListSchema = z.object({ ids: z.array(z.string().uuid()).optional(), + emails: z.array(z.string().email()).optional(), + query: z.string().optional(), filter: z diff --git a/server/routes/api/users/users.test.ts b/server/routes/api/users/users.test.ts index 8859f463e..53b54e23f 100644 --- a/server/routes/api/users/users.test.ts +++ b/server/routes/api/users/users.test.ts @@ -150,6 +150,23 @@ describe("#users.list", () => { expect(body.data[0].id).toEqual(user.id); }); + it("should allow filtering by email", async () => { + const team = await buildTeam(); + const admin = await buildAdmin({ teamId: team.id }); + const user = await buildUser({ teamId: team.id }); + + const res = await server.post("/api/users.list", { + body: { + token: admin.getJwtToken(), + emails: [user.email], + }, + }); + const body = await res.json(); + expect(res.status).toEqual(200); + expect(body.data.length).toEqual(1); + expect(body.data[0].id).toEqual(user.id); + }); + it("should require admin for detailed info", async () => { const team = await buildTeam(); await buildAdmin({ teamId: team.id }); diff --git a/server/routes/api/users/users.ts b/server/routes/api/users/users.ts index c020b8444..70187eb40 100644 --- a/server/routes/api/users/users.ts +++ b/server/routes/api/users/users.ts @@ -35,7 +35,7 @@ router.post( pagination(), validate(T.UsersListSchema), async (ctx: APIContext) => { - const { sort, direction, query, filter, ids } = ctx.input.body; + const { sort, direction, query, filter, ids, emails } = ctx.input.body; const actor = ctx.state.auth.user; let where: WhereOptions = { @@ -129,6 +129,13 @@ router.post( }; } + if (emails) { + where = { + ...where, + email: emails, + }; + } + const [users, total] = await Promise.all([ User.findAll({ where,