All files / apps/web/src/handlers/peers unlink.ts

100% Statements 15/15
100% Branches 6/6
100% Functions 4/4
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78            6x                       4x 4x       4x     4x                     4x 1x         3x 1x         2x 2x 1x                         1x 1x         1x              
import { TRPCError } from "@trpc/server";
import { z } from "zod";
 
import { authProcedure } from "~web/handlers/trpc";
import { peerIdSchema } from "~web/handlers/validation";
 
export const procedure = authProcedure
	.meta({
		title: "Unlink peer",
		description:
			"Disconnects a peer owned by the current  user from its connected  user, and vice versa.",
	})
	.input(
		z.strictObject({
			id: peerIdSchema,
		}),
	)
	.mutation(async ({ input, ctx }) => {
		const { database } = ctx;
		const peer = await database
			.selectFrom("peers as peersMine")
			.where("peersMine.id", "=", input.id)
			.leftJoin("users", (qb) =>
				qb.onRef("users.id", "=", "peersMine.connectedUserId"),
			)
			.leftJoin("peers as peersTheir", (qb) =>
				qb
					.on("peersTheir.connectedUserId", "=", ctx.auth.userId)
					.onRef("peersTheir.ownerUserId", "=", "users.id"),
			)
			.select([
				"peersMine.ownerUserId",
				"users.id as connectedUserId",
				"peersTheir.id as theirPeerId",
			])
			.limit(1)
			.executeTakeFirst();
		if (!peer) {
			throw new TRPCError({
				code: "NOT_FOUND",
				message: `No peer found by id "${input.id}".`,
			});
		}
		if (peer.ownerUserId !== ctx.auth.userId) {
			throw new TRPCError({
				code: "FORBIDDEN",
				message: `Peer "${input.id}" is not owned by "${ctx.auth.email}".`,
			});
		}
		const { connectedUserId } = peer;
		if (!connectedUserId) {
			throw new TRPCError({
				code: "NOT_FOUND",
				message: `Peer "${input.id}" doesn't have  user connected to it.`,
			});
		}
		/* c8 ignore start */
		if (!peer.theirPeerId) {
			throw new TRPCError({
				code: "INTERNAL_SERVER_ERROR",
				message: `Peer "${input.id}" doesn't have a counterparty to unlink from.`,
			});
		}
		/* c8 ignore stop */
		await database.transaction().execute(async (tx) => {
			await tx
				.updateTable("peers")
				.set({ connectedUserId: null })
				.where("id", "=", input.id)
				.executeTakeFirst();
			await tx
				.updateTable("peers")
				.set({ connectedUserId: null })
				.where("id", "=", peer.theirPeerId)
				.executeTakeFirst();
		});
	});