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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | 6x 9x 9x 9x 9x 9x 9x 9x 6x 2x 6x 5x 3x 2x 6x 9x 9x 9x 9x 9x 9x 4x 5x 6x | import { TRPCError } from "@trpc/server";
import { z } from "zod";
import type { PeerId, UserId } from "~db/ids";
import { queueCallFactory } from "~web/handlers/batch";
import type { AuthorizedContext } from "~web/handlers/context";
import { getParticipantsReceipts } from "~web/handlers/receipts/utils";
import { authProcedure } from "~web/handlers/trpc";
import { peerIdSchema } from "~web/handlers/validation";
// We allow user fetch foreign peers
// In case they share the same receipt (as participant or as payer)
const fetchPeers = async (ctx: AuthorizedContext, ids: PeerId[]) =>
ctx.database
.with("mergedReceipts", (qc) =>
getParticipantsReceipts(qc, ctx.auth.userId)
.groupBy("receipts.id")
.select("receipts.id"),
)
.with("mergedParticipants", (qc) =>
qc
.selectFrom("receiptParticipants")
.innerJoin("mergedReceipts", (qb) =>
qb.onRef("receiptParticipants.receiptId", "=", "mergedReceipts.id"),
)
.groupBy("receiptParticipants.peerId")
.select("receiptParticipants.peerId"),
)
.selectFrom("peers as peersTheir")
.where("peersTheir.id", "in", ids)
.innerJoin("mergedParticipants", (qb) =>
qb.onRef("peersTheir.id", "=", "mergedParticipants.peerId"),
)
.leftJoin("users", (qb) =>
qb.onRef("peersTheir.connectedUserId", "=", "users.id"),
)
.leftJoin("peers as peersMine", (qb) =>
qb
.onRef("peersMine.connectedUserId", "=", "peersTheir.connectedUserId")
.on("peersMine.ownerUserId", "=", ctx.auth.userId),
)
.select([
"peersMine.id as mineId",
"peersMine.name as mineName",
"peersMine.publicName as minePublicName",
"users.id as userId",
"users.email",
"users.avatarUrl",
"peersTheir.id as theirId",
"peersTheir.name as theirName",
"peersTheir.publicName as theirPublicName",
"peersTheir.ownerUserId",
])
.groupBy([
"peersMine.id",
"peersMine.name",
"peersMine.publicName",
"users.id",
"users.email",
"users.avatarUrl",
"peersTheir.id",
"peersTheir.name",
"peersTheir.publicName",
"peersTheir.ownerUserId",
])
.execute();
// Excessive function is needed to properly infer return types
const getForeignPeer = (
peer: Awaited<ReturnType<typeof fetchPeers>>[number],
) => ({
remoteId: peer.theirId,
name: peer.theirPublicName || peer.theirName,
});
const mapPeer = (peer: Awaited<ReturnType<typeof fetchPeers>>[number]) => {
if (peer.mineId && peer.mineName && peer.email && peer.userId) {
return {
id: peer.mineId,
name: peer.mineName,
publicName:
peer.minePublicName === null ? undefined : peer.minePublicName,
connectedUser: {
id: peer.userId,
email: peer.email,
avatarUrl: peer.avatarUrl || undefined,
} as
| {
id: UserId;
email: string;
avatarUrl?: string;
}
| undefined,
};
}
return getForeignPeer(peer);
};
const queuePeer = queueCallFactory<
AuthorizedContext,
{ id: PeerId },
ReturnType<typeof mapPeer>
>((ctx) => async (inputs) => {
const peers = await fetchPeers(
ctx,
inputs.map(({ id }) => id),
);
return inputs.map((input) => {
const matchedPeer = peers.find((peer) => peer.theirId === input.id);
if (!matchedPeer) {
return new TRPCError({
code: "NOT_FOUND",
message: `No peer found by id "${input.id}" or you don't have access to it.`,
});
}
return mapPeer(matchedPeer);
});
});
export const procedure = authProcedure
.meta({
title: "Get foreign peer",
description:
"Returns a peer by id owned by another user, provided they share a receipt with the current user.",
})
.input(z.strictObject({ id: peerIdSchema }))
.query(queuePeer);
|