🔒️ Limit max participants in a poll (#1450)

This commit is contained in:
Luke Vella 2024-12-01 18:41:24 +00:00 committed by GitHub
parent 9b606bdbdc
commit 387e83922d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -8,6 +8,8 @@ import { createToken } from "@/utils/session";
import { publicProcedure, rateLimitMiddleware, router } from "../../trpc"; import { publicProcedure, rateLimitMiddleware, router } from "../../trpc";
import type { DisableNotificationsPayload } from "../../types"; import type { DisableNotificationsPayload } from "../../types";
const MAX_PARTICIPANTS = 1000;
export const participants = router({ export const participants = router({
list: publicProcedure list: publicProcedure
.input( .input(
@ -73,19 +75,21 @@ export const participants = router({
.mutation(async ({ ctx, input: { pollId, votes, name, email } }) => { .mutation(async ({ ctx, input: { pollId, votes, name, email } }) => {
const { user } = ctx; const { user } = ctx;
const poll = await prisma.poll.findUnique({ const participant = await prisma.$transaction(async (prisma) => {
where: { id: pollId }, const participantCount = await prisma.participant.count({
select: { where: {
id: true, pollId,
title: true, deleted: false,
}, },
}); });
if (!poll) { if (participantCount >= MAX_PARTICIPANTS) {
throw new TRPCError({ code: "BAD_REQUEST", message: "Poll not found" }); throw new TRPCError({
code: "BAD_REQUEST",
message: `This poll has reached its maximum limit of ${MAX_PARTICIPANTS} participants`,
});
} }
const participant = await prisma.$transaction(async (prisma) => {
const participant = await prisma.participant.create({ const participant = await prisma.participant.create({
data: { data: {
pollId: pollId, pollId: pollId,
@ -94,6 +98,14 @@ export const participants = router({
userId: user.id, userId: user.id,
locale: user.locale ?? undefined, locale: user.locale ?? undefined,
}, },
include: {
poll: {
select: {
id: true,
title: true,
},
},
},
}); });
await prisma.vote.createMany({ await prisma.vote.createMany({
@ -121,9 +133,9 @@ export const participants = router({
.queueTemplate("NewParticipantConfirmationEmail", { .queueTemplate("NewParticipantConfirmationEmail", {
to: email, to: email,
props: { props: {
title: poll.title, title: participant.poll.title,
editSubmissionUrl: absoluteUrl( editSubmissionUrl: absoluteUrl(
`/invite/${poll.id}?token=${token}`, `/invite/${participant.poll.id}?token=${token}`,
), ),
}, },
}); });
@ -155,11 +167,11 @@ export const participants = router({
to: email, to: email,
props: { props: {
participantName: participant.name, participantName: participant.name,
pollUrl: absoluteUrl(`/poll/${poll.id}`), pollUrl: absoluteUrl(`/poll/${participant.poll.id}`),
disableNotificationsUrl: absoluteUrl( disableNotificationsUrl: absoluteUrl(
`/auth/disable-notifications?token=${token}`, `/auth/disable-notifications?token=${token}`,
), ),
title: poll.title, title: participant.poll.title,
}, },
}); });
} }