Files
portfolio/api/src/lib/tus.ts

107 lines
2.8 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import type { Server } from '@tus/server'
import type { FastifyReply, FastifyRequest } from 'fastify'
import { isProduction } from '@redwoodjs/api/dist/logger'
import { ValidationError } from '@redwoodjs/graphql-server'
import { decryptAndValidateSession, validateSessionCookie } from 'src/lib/auth'
import { setCorsHeaders } from 'src/lib/cors'
import { db } from 'src/lib/db'
interface User {
id: number
username: string
email: string
hashedPassword: string
salt: string
resetToken: string | null
resetTokenExpiresAt: Date | null
}
export const handleTusUpload = (
req: FastifyRequest,
res: FastifyReply,
tusHandler: Server,
isPublicEndpoint: boolean
) => {
if (isProduction) {
if (req.method === 'OPTIONS') handleOptionsRequest(res)
else if (isPublicEndpoint && req.method === 'GET')
tusHandler.handle(req.raw, res.raw)
else if (['GET', 'POST', 'HEAD', 'PATCH'].includes(req.method)) {
if (req.headers.cookie) handleAuthenticatedRequest(req, res, tusHandler)
else {
res.raw.statusCode = 401
res.raw.end('Unauthenticated')
}
} else {
res.raw.statusCode = 405
res.raw.end('Method not allowed')
}
} else tusHandler.handle(req.raw, res.raw)
}
const handleAuthenticatedRequest = async (
req: FastifyRequest,
res: FastifyReply,
tusHandler: Server
) => {
try {
const sessionCookie = extractSessionCookie(req.headers.cookie)
validateSessionCookie(sessionCookie)
const userId = decryptAndValidateSession(sessionCookie)
if (userId) {
res.raw.setHeader('Access-Control-Allow-Credentials', 'true')
try {
const user = await db.user.findUnique({
where: {
id: userId,
},
})
addUserMetadataToRequest(req, user)
if ((req.raw as any).userId) tusHandler.handle(req.raw, res.raw)
else {
res.raw.statusCode = 500
res.raw.end('Server error')
}
} catch (error) {
res.raw.statusCode = 500
res.raw.end('Server error')
}
} else {
res.raw.statusCode = 403
res.raw.end('Forbidden')
}
} catch (error) {
res.raw.statusCode = 401
res.raw.end('Unauthenticated')
}
}
const addUserMetadataToRequest = (req: FastifyRequest, user: User) => {
;(req.raw as any).userId = user.id
;(req.raw as any).userEmail = user.email
}
const handleOptionsRequest = (res: FastifyReply) => {
setCorsHeaders(res)
res.raw.statusCode = 204
res.raw.end()
}
const extractSessionCookie = (cookie: string) => {
const sessionCookie = cookie
.split(';')
.find((item) => item.trim().startsWith('session_8911'))
?.trim()
if (!sessionCookie) throw new ValidationError('Invalid token')
return sessionCookie
}