|
| 1 | +import { z } from 'zod' |
| 2 | +import { defineProtectedMutateProcedure } from '../../types/defineProcedure.js' |
| 3 | +import prisma from '../../prisma.js' |
| 4 | +import logActivity from '../../util/activity.js' |
| 5 | +import { TRPCError } from '@trpc/server' |
| 6 | +import { sendMail } from '../../util/mail.js' |
| 7 | + |
| 8 | +export const requestGliederungAdminDecideProcedure = defineProtectedMutateProcedure({ |
| 9 | + key: 'requestGliederungAdminDecide', |
| 10 | + roleIds: ['ADMIN', 'GLIEDERUNG_ADMIN'], |
| 11 | + inputSchema: z.strictObject({ |
| 12 | + token: z.string().uuid().optional(), |
| 13 | + requestId: z.number().int(), |
| 14 | + decision: z.boolean(), |
| 15 | + }), |
| 16 | + handler: async ({ ctx, input: { token, requestId, decision } }) => { |
| 17 | + if (ctx.account?.role === 'GLIEDERUNG_ADMIN' && token === undefined) { |
| 18 | + throw new TRPCError({ |
| 19 | + code: 'BAD_REQUEST', |
| 20 | + message: 'token is required', |
| 21 | + }) |
| 22 | + } |
| 23 | + |
| 24 | + const request = await prisma.gliederungToAccount.findUnique({ |
| 25 | + where: { |
| 26 | + id: requestId, |
| 27 | + confirmByGliederungToken: ctx.account?.role === 'ADMIN' ? undefined : token, |
| 28 | + }, |
| 29 | + select: { |
| 30 | + id: true, |
| 31 | + accountId: true, |
| 32 | + account: { |
| 33 | + select: { |
| 34 | + email: true, |
| 35 | + }, |
| 36 | + }, |
| 37 | + gliederung: { |
| 38 | + select: { |
| 39 | + name: true, |
| 40 | + }, |
| 41 | + }, |
| 42 | + }, |
| 43 | + }) |
| 44 | + if (request === null) { |
| 45 | + throw new TRPCError({ |
| 46 | + code: 'NOT_FOUND', |
| 47 | + }) |
| 48 | + } |
| 49 | + |
| 50 | + if (!decision) { |
| 51 | + await prisma.gliederungToAccount.delete({ |
| 52 | + where: { |
| 53 | + id: requestId, |
| 54 | + }, |
| 55 | + }) |
| 56 | + |
| 57 | + await logActivity({ |
| 58 | + type: 'DELETE', |
| 59 | + subjectType: 'gliederungtoaccount', |
| 60 | + subjectId: `${request.id}`, |
| 61 | + description: `Eine Zugriffsanfrage auf die Gliederung ${request.gliederung.name} wurde abgelehnt.`, |
| 62 | + causerId: ctx.accountId, |
| 63 | + }) |
| 64 | + } else { |
| 65 | + await prisma.$transaction(async (tx) => { |
| 66 | + const { accountId } = await tx.gliederungToAccount.update({ |
| 67 | + where: { |
| 68 | + id: requestId, |
| 69 | + }, |
| 70 | + data: { |
| 71 | + confirmByGliederungToken: null, |
| 72 | + confirmedByGliederung: true, |
| 73 | + }, |
| 74 | + select: { |
| 75 | + accountId: true, |
| 76 | + }, |
| 77 | + }) |
| 78 | + await tx.account.update({ |
| 79 | + where: { |
| 80 | + id: accountId, |
| 81 | + }, |
| 82 | + data: { |
| 83 | + role: 'GLIEDERUNG_ADMIN', |
| 84 | + }, |
| 85 | + }) |
| 86 | + }) |
| 87 | + |
| 88 | + await logActivity({ |
| 89 | + type: 'UPDATE', |
| 90 | + subjectType: 'account', |
| 91 | + subjectId: request.accountId, |
| 92 | + description: `Account ${request.account.email} ist jetzt Gliederungsadmin der Gliederung ${request.gliederung.name}`, |
| 93 | + causerId: ctx.accountId, |
| 94 | + }) |
| 95 | + } |
| 96 | + |
| 97 | + await sendMail({ |
| 98 | + to: request.account.email, |
| 99 | + categories: ['access', 'gliederung'], |
| 100 | + template: 'gliederung-access-request-decision', |
| 101 | + subject: `Zugriffsanfrage auf deine Gliederung ${decision ? 'bestätigt' : 'abgelehnt'}`, |
| 102 | + variables: { |
| 103 | + hostname: 'brahmsee.digital', |
| 104 | + gliederung: request.gliederung.name, |
| 105 | + name: `${ctx.account?.person.firstname} ${ctx.account?.person.lastname}`, |
| 106 | + veranstaltung: 'Zugriffsanfrage', |
| 107 | + decision, |
| 108 | + }, |
| 109 | + }) |
| 110 | + |
| 111 | + return decision |
| 112 | + }, |
| 113 | +}) |
0 commit comments