Openstatus
www.openstatus.dev
1import { z } from "zod";
2
3import { Events } from "@openstatus/analytics";
4import { and, eq } from "@openstatus/db";
5import {
6 selectUserSchema,
7 usersToWorkspaces,
8 workspaceRole,
9} from "@openstatus/db/src/schema";
10
11import { TRPCError } from "@trpc/server";
12import { createTRPCRouter, protectedProcedure } from "../trpc";
13
14export const memberRouter = createTRPCRouter({
15 list: protectedProcedure.query(async (opts) => {
16 const result = await opts.ctx.db.query.usersToWorkspaces.findMany({
17 where: eq(usersToWorkspaces.workspaceId, opts.ctx.workspace.id),
18 with: {
19 user: true,
20 },
21 });
22
23 return z
24 .object({
25 role: z.enum(workspaceRole),
26 createdAt: z.coerce.date(),
27 user: selectUserSchema,
28 })
29 .array()
30 .parse(result);
31 }),
32
33 delete: protectedProcedure
34 .meta({ track: Events.RemoveUser })
35 .input(z.object({ id: z.number() }))
36 .mutation(async (opts) => {
37 const currentUser = await opts.ctx.db.query.usersToWorkspaces.findFirst({
38 where: and(
39 eq(usersToWorkspaces.userId, opts.ctx.user.id),
40 eq(usersToWorkspaces.workspaceId, opts.ctx.workspace.id),
41 ),
42 });
43
44 if (!currentUser) throw new Error("No user to workspace found");
45
46 if (!["owner"].includes(currentUser.role)) {
47 throw new TRPCError({
48 code: "PRECONDITION_FAILED",
49 message: "Not authorized to remove user from workspace",
50 });
51 }
52
53 if (opts.input.id === opts.ctx.user.id) {
54 throw new TRPCError({
55 code: "PRECONDITION_FAILED",
56 message: "Cannot remove yourself from workspace",
57 });
58 }
59
60 await opts.ctx.db
61 .delete(usersToWorkspaces)
62 .where(
63 and(
64 eq(usersToWorkspaces.workspaceId, opts.ctx.workspace.id),
65 eq(usersToWorkspaces.userId, opts.input.id),
66 ),
67 );
68 }),
69});