From 21a44428f49d6d1d70655ed6d240964594e5d75c Mon Sep 17 00:00:00 2001 From: Apoorv Mishra Date: Thu, 16 Mar 2023 12:31:56 +0530 Subject: [PATCH] Filter groups given a member (#5034) * feat: filter groups given a member * Revert "feat: filter groups given a member" This reverts commit 7dac8bb38de1fdaf661c636c5d1b13e4112fd8fd. * fix: make it work via db query --- server/models/Group.ts | 25 +++++++++++ server/routes/api/groups/groups.test.ts | 56 +++++++++++++++++++++++++ server/routes/api/groups/groups.ts | 4 +- server/routes/api/groups/schema.ts | 3 ++ 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/server/models/Group.ts b/server/models/Group.ts index 1f6d8c0fd..80343e81a 100644 --- a/server/models/Group.ts +++ b/server/models/Group.ts @@ -9,6 +9,7 @@ import { BelongsToMany, DefaultScope, DataType, + Scopes, } from "sequelize-typescript"; import CollectionGroup from "./CollectionGroup"; import GroupUser from "./GroupUser"; @@ -27,6 +28,23 @@ import NotContainsUrl from "./validators/NotContainsUrl"; }, ], })) +@Scopes(() => ({ + withMember: (memberId: string) => ({ + include: [ + { + association: "groupMemberships", + required: true, + }, + { + association: "members", + required: true, + where: { + userId: memberId, + }, + }, + ], + }), +})) @Table({ tableName: "groups", modelName: "group", @@ -76,9 +94,16 @@ class Group extends ParanoidModel { }); } + static filterByMember(memberId: string | undefined) { + return memberId + ? this.scope({ method: ["withMember", memberId] }) + : this.scope("defaultScope"); + } + // associations @HasMany(() => GroupUser, "groupId") + @HasMany(() => GroupUser, { as: "members", foreignKey: "groupId" }) groupMemberships: GroupUser[]; @HasMany(() => CollectionGroup, "groupId") diff --git a/server/routes/api/groups/groups.test.ts b/server/routes/api/groups/groups.test.ts index d45018660..61d150f87 100644 --- a/server/routes/api/groups/groups.test.ts +++ b/server/routes/api/groups/groups.test.ts @@ -192,6 +192,62 @@ describe("#groups.list", () => { expect(body.policies.length).toEqual(1); expect(body.policies[0].abilities.read).toEqual(true); }); + + it("should return groups only to which a given user has been added", async () => { + const user = await buildUser(); + const anotherUser = await buildUser({ + teamId: user.teamId, + }); + const group = await buildGroup({ + teamId: user.teamId, + }); + const anotherGroup = await buildGroup({ + teamId: user.teamId, + }); + await group.$add("user", user, { + through: { + createdById: user.id, + }, + }); + await group.$add("user", anotherUser, { + through: { + createdById: user.id, + }, + }); + const res = await server.post("/api/groups.list", { + body: { + token: user.getJwtToken(), + }, + }); + const anotherRes = await server.post("/api/groups.list", { + body: { + userId: user.id, + token: user.getJwtToken(), + }, + }); + const body = await res.json(); + const anotherBody = await anotherRes.json(); + expect(res.status).toEqual(200); + expect(anotherRes.status).toEqual(200); + expect(body.data["groups"].length).toEqual(2); + expect(body.data["groups"][0].id).toEqual(anotherGroup.id); + expect(body.data["groups"][1].id).toEqual(group.id); + expect(body.data["groupMemberships"].length).toEqual(2); + expect(anotherBody.data["groups"].length).toEqual(1); + expect(anotherBody.data["groups"][0].id).toEqual(group.id); + expect(anotherBody.data["groupMemberships"].length).toEqual(2); + expect(body.data["groupMemberships"][0].groupId).toEqual(group.id); + expect(body.data["groupMemberships"][1].groupId).toEqual(group.id); + expect(body.data["groupMemberships"][0].user.id).toEqual(user.id); + expect(body.data["groupMemberships"][1].user.id).toEqual(anotherUser.id); + expect(anotherBody.data["groupMemberships"][0].groupId).toEqual(group.id); + expect(anotherBody.data["groupMemberships"][1].groupId).toEqual(group.id); + expect(anotherBody.data["groupMemberships"][0].user.id).toEqual(user.id); + expect(anotherBody.data["groupMemberships"][1].user.id).toEqual( + anotherUser.id + ); + expect(body.policies.length).toEqual(2); + }); }); describe("#groups.info", () => { diff --git a/server/routes/api/groups/groups.ts b/server/routes/api/groups/groups.ts index 7debd6f24..7bfb13bb3 100644 --- a/server/routes/api/groups/groups.ts +++ b/server/routes/api/groups/groups.ts @@ -23,10 +23,10 @@ router.post( pagination(), validate(T.GroupsListSchema), async (ctx: APIContext) => { - const { direction, sort } = ctx.input.body; + const { direction, sort, userId } = ctx.input.body; const { user } = ctx.state.auth; - const groups = await Group.findAll({ + const groups = await Group.filterByMember(userId).findAll({ where: { teamId: user.teamId, }, diff --git a/server/routes/api/groups/schema.ts b/server/routes/api/groups/schema.ts index d79667873..cfa65cda0 100644 --- a/server/routes/api/groups/schema.ts +++ b/server/routes/api/groups/schema.ts @@ -21,6 +21,9 @@ export const GroupsListSchema = z.object({ message: "Invalid sort parameter", }) .default("updatedAt"), + + /** Only list groups where this user is a member */ + userId: z.string().uuid().optional(), }), });