Skip to content

Commit 589eb3e

Browse files
committed
refactor(auth): replace any-cast authenticate fallback with typed app.authenticate decorator in cards, event, and nfc routes (closes #594)
1 parent c36d35b commit 589eb3e

3 files changed

Lines changed: 29 additions & 64 deletions

File tree

apps/backend/src/routes/cards.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,9 @@ function hasErrorCode(
6262
}
6363

6464
export async function cardRoutes(app: FastifyInstance): Promise<void> {
65-
app.addHook('preHandler', async (request, reply) => {
66-
const server = request.server;
67-
if (typeof server?.authenticate === 'function') { await server.authenticate(request, reply); return }
68-
if (typeof app.authenticate === 'function') { await app.authenticate(request, reply); return }
69-
try { await request.jwtVerify() } catch (_e) { reply.status(401).send({ error: 'Unauthorized' }) }
70-
});
71-
65+
7266
// ─── List Cards ───
73-
app.get('/', async (request: FastifyRequest, reply: FastifyReply): Promise<CardResponse[] | void> => {
67+
app.get('/', {preHandler: [(req, reply) => app.authenticate(req, reply)] },async (request: FastifyRequest, reply: FastifyReply): Promise<CardResponse[] | void> => {
7468
const userId = request.user.id;
7569
try {
7670
return await cardService.listCards(app, userId)
@@ -80,7 +74,7 @@ export async function cardRoutes(app: FastifyInstance): Promise<void> {
8074
});
8175

8276
// ─── Creates Card ───
83-
app.post('/', async (request: FastifyRequest<{ Body: CreateCardBody }>, reply: FastifyReply): Promise<Card | void> => {
77+
app.post<{ Body: CreateCardBody }>('/', { preHandler: [(req, reply) => app.authenticate(req, reply)]}, async (request, reply): Promise<Card | void> => {
8478
const userId = request.user.id;
8579
const parsed = createCardSchema.safeParse(request.body);
8680

@@ -99,7 +93,7 @@ export async function cardRoutes(app: FastifyInstance): Promise<void> {
9993

10094
// ─── Update Card ───
10195

102-
app.put('/:id', async (request: FastifyRequest<{ Params: CardParams; Body: UpdateCardBody }>, reply: FastifyReply): Promise<CardResponse> => {
96+
app.put<{ Params: CardParams; Body: UpdateCardBody }>('/:id', {preHandler: [(req, reply) => app.authenticate(req, reply)] }, async (request, reply): Promise<CardResponse> => {
10397
const userId = request.user.id;
10498
const { id } = request.params;
10599

@@ -117,7 +111,7 @@ export async function cardRoutes(app: FastifyInstance): Promise<void> {
117111

118112
// ─── Delete Card ───
119113

120-
app.delete('/:id', async (request: FastifyRequest<{ Params: CardParams }>, reply: FastifyReply): Promise<void> => {
114+
app.delete<{ Params: CardParams }>('/:id', { preHandler: [(req, reply) => app.authenticate(req, reply)]}, async (request, reply): Promise<void> => {
121115
const userId = request.user.id;
122116
const { id } = request.params;
123117

@@ -139,7 +133,7 @@ export async function cardRoutes(app: FastifyInstance): Promise<void> {
139133
});
140134

141135
// ─── Set Default Card ───
142-
app.put('/:id/default', async (request: FastifyRequest<{ Params: CardParams }>, reply: FastifyReply): Promise<object | void> => {
136+
app.put<{ Params: CardParams }>('/:id/default', {preHandler: [(req, reply) => app.authenticate(req, reply)]}, async (request, reply): Promise<object | void> => {
143137
const userId = request.user.id;
144138
const { id } = request.params;
145139

apps/backend/src/routes/event.ts

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
2-
import { createEventSchema, joinEventSchema} from '../validations/event.validation.js';
3-
41
import {generateUniqueSlug} from '../utils/slug.js'
2+
import { createEventSchema} from '../validations/event.validation.js';
3+
4+
import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
55

66

77
type EventDetails = {
@@ -58,30 +58,17 @@ type EventWithAttendees = {
5858
}
5959

6060
export async function eventRoutes(app:FastifyInstance) {
61-
app.post('/', { preHandler: [async (request, reply) => {
62-
const server = request.server as any;
63-
if (typeof server?.authenticate === 'function') { await server.authenticate(request, reply); return }
64-
if (typeof (app as any).authenticate === 'function') { await (app as any).authenticate(request, reply); return }
65-
try { await request.jwtVerify() } catch (e) { reply.status(401).send({ error: 'Unauthorized' }) }
66-
}] }, async (request: FastifyRequest<{
67-
Body: {
68-
name: string,
69-
description?: string,
70-
startDate: string,
71-
location: string,
72-
endDate: string,
73-
isPublic?: boolean
74-
}}>, reply: FastifyReply) => {
75-
const userId = (request.user as any).id;
61+
app.post<{Body: { name: string; description?: string; startDate: string; location: string; endDate: string; isPublic?: boolean; }}>('/', { preHandler: [(req, reply) => app.authenticate(req, reply)] }, async (request, reply) => {
62+
const userId = request.user.id;
7663
const parsed = createEventSchema.safeParse(request.body);
7764
if(!parsed.success){
7865
return reply.status(400).send({error: 'Bad request'})
7966
}
8067

8168
const {name, description, startDate, endDate, isPublic ,location} = parsed.data
8269

83-
let finalSlug = await generateUniqueSlug(name, async(slug) => {
84-
const existing = await app.prisma.event.findUnique({where: {slug : slug}})
70+
const finalSlug = await generateUniqueSlug(name, async(slug) => {
71+
const existing = await app.prisma.event.findUnique({where: {slug}})
8572

8673
return !!existing
8774
})
@@ -95,7 +82,7 @@ export async function eventRoutes(app:FastifyInstance) {
9582
name,
9683
description,
9784
slug: finalSlug,
98-
location: location,
85+
location,
9986
startDate: startDateObj,
10087
endDate: endDateObj,
10188
isPublic: isPublic ?? true,
@@ -104,7 +91,7 @@ export async function eventRoutes(app:FastifyInstance) {
10491
})
10592

10693
return reply.status(201).send(newEvent);
107-
} catch (error) {
94+
} catch (_error) {
10895
app.log.error('Failed to create event');
10996
return reply.status(500).send({error: 'Failed to create event'})
11097
}
@@ -153,8 +140,8 @@ export async function eventRoutes(app:FastifyInstance) {
153140
return response;
154141
})
155142

156-
app.post('/:slug/join', { preHandler: [async (request, reply) => { const server = request.server as any; if (typeof server?.authenticate === 'function') { await server.authenticate(request, reply); return } if (typeof (app as any).authenticate === 'function') { await (app as any).authenticate(request, reply); return } try { await request.jwtVerify() } catch (e) { reply.status(401).send({ error: 'Unauthorized' }) } }] }, async(request: FastifyRequest<{Params: {slug: string}}>, reply: FastifyReply) => {
157-
const userId = (request.user as any).id;
143+
app.post<{ Params: { slug: string } }>('/:slug/join', {preHandler: [(req, reply) => app.authenticate(req, reply)]}, async(request, reply) => {
144+
const userId = request.user.id;
158145
const paramsSlug = request.params.slug;
159146

160147
const event = await app.prisma.event.findUnique({
@@ -171,7 +158,7 @@ export async function eventRoutes(app:FastifyInstance) {
171158
await app.prisma.eventAttendee.create({
172159
data: {
173160
eventId: event.id,
174-
userId: userId,
161+
userId,
175162
joinedAt: new Date()
176163
}
177164
})
@@ -186,9 +173,9 @@ export async function eventRoutes(app:FastifyInstance) {
186173
}
187174

188175
})
176+
app.delete<{Params: {slug: string}}>('/:slug/leave',{preHandler: [(req, reply) => app.authenticate(req, reply)]}, async(request, reply) => {
189177

190-
app.delete('/:slug/leave', { preHandler: [async (request, reply) => { const server = request.server as any; if (typeof server?.authenticate === 'function') { await server.authenticate(request, reply); return } if (typeof (app as any).authenticate === 'function') { await (app as any).authenticate(request, reply); return } try { await request.jwtVerify() } catch (e) { reply.status(401).send({ error: 'Unauthorized' }) } }] }, async(request: FastifyRequest<{Params: {slug: string}}>, reply: FastifyReply) => {
191-
const userId = (request.user as any).id;
178+
const userId = request.user.id;
192179
const paramsSlug = request.params.slug;
193180

194181
const event = await app.prisma.event.findUnique({
@@ -205,7 +192,7 @@ export async function eventRoutes(app:FastifyInstance) {
205192
await app.prisma.eventAttendee.delete({
206193
where: {
207194
userId_eventId: {
208-
userId: userId,
195+
userId,
209196
eventId: event.id
210197
}
211198
}

apps/backend/src/routes/nfc.ts

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
21
import { z } from 'zod';
32

3+
import type { FastifyInstance} from 'fastify';
4+
45
type NfcPayloadResponse = {
56
type: 'URI';
67
payload: string;
@@ -11,32 +12,15 @@ const nfcQuerySchema = z.object({
1112
});
1213

1314
export async function nfcRoutes(app: FastifyInstance) {
14-
app.addHook('preHandler', async (request, reply) => {
15-
const server = request.server as any;
16-
if (typeof server?.authenticate === 'function') {
17-
await server.authenticate(request, reply);
18-
return;
19-
}
20-
if (typeof (app as any).authenticate === 'function') {
21-
await (app as any).authenticate(request, reply);
22-
return;
23-
}
24-
try {
25-
await request.jwtVerify();
26-
} catch (e) {
27-
reply.status(401).send({ error: 'Unauthorized' });
28-
}
29-
});
15+
3016

3117
// GET /api/nfc/payload — returns NDEF URI payload for user's default DevCard URL
3218
// GET /api/nfc/payload?card=<cardId> — returns payload for a specific card
33-
app.get(
34-
'/payload',
35-
async (
36-
request: FastifyRequest<{ Querystring: { card?: string } }>,
37-
reply: FastifyReply
38-
) => {
39-
const userId = (request.user as any).id;
19+
app.get<{ Querystring: { card?: string } }>(
20+
'/payload',
21+
{ preHandler: [(req, reply) => app.authenticate(req, reply)] },
22+
async (request, reply) => {
23+
const userId = request.user.id;
4024

4125
// Validate query params with Zod
4226
const parseResult = nfcQuerySchema.safeParse(request.query);

0 commit comments

Comments
 (0)