diff --git a/src/server/routers/file.ts b/src/server/routers/file.ts index a97d7e8..2075873 100644 --- a/src/server/routers/file.ts +++ b/src/server/routers/file.ts @@ -517,32 +517,25 @@ export const fileRouter = router({ }) ) .mutation(async ({ ctx, input }) => { - const isAdminOrObserver = ['SUPER_ADMIN', 'PROGRAM_ADMIN', 'OBSERVER', 'AWARD_MASTER'].includes(ctx.user.role) + // Replace is a write operation on the team's submission. Only admins + // and the team itself (submitter or team member) may replace files — + // jurors and mentors are read-only on project files even though they + // can see them. Observers/Award masters are also read-only. + const isAdmin = ctx.user.role === 'SUPER_ADMIN' || ctx.user.role === 'PROGRAM_ADMIN' - if (!isAdminOrObserver) { - // Check user has access to the project (assigned or team member) - const [assignment, mentorAssignment, teamMembership] = await Promise.all([ - ctx.prisma.assignment.findFirst({ - where: { userId: ctx.user.id, projectId: input.projectId }, - select: { id: true }, - }), - ctx.prisma.mentorAssignment.findFirst({ - where: { mentorId: ctx.user.id, projectId: input.projectId }, - select: { id: true }, - }), - ctx.prisma.project.findFirst({ - where: { - id: input.projectId, - OR: [ - { submittedByUserId: ctx.user.id }, - { teamMembers: { some: { userId: ctx.user.id } } }, - ], - }, - select: { id: true }, - }), - ]) + if (!isAdmin) { + const teamMembership = await ctx.prisma.project.findFirst({ + where: { + id: input.projectId, + OR: [ + { submittedByUserId: ctx.user.id }, + { teamMembers: { some: { userId: ctx.user.id } } }, + ], + }, + select: { id: true }, + }) - if (!assignment && !mentorAssignment && !teamMembership) { + if (!teamMembership) { throw new TRPCError({ code: 'FORBIDDEN', message: 'You do not have access to replace files for this project',