tambahan
This commit is contained in:
@@ -1,62 +1,51 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { Elysia } from 'elysia'
|
|
||||||
import jwt, { type JWTPayloadSpec } from '@elysiajs/jwt'
|
import jwt, { type JWTPayloadSpec } from '@elysiajs/jwt'
|
||||||
import bearer from '@elysiajs/bearer'
|
import Elysia from 'elysia'
|
||||||
import { prisma } from '../lib/prisma'
|
import { prisma } from '../lib/prisma'
|
||||||
|
|
||||||
// =========================================================
|
|
||||||
// JWT Secret Validation
|
|
||||||
// =========================================================
|
|
||||||
const secret = process.env.JWT_SECRET
|
const secret = process.env.JWT_SECRET
|
||||||
if (!secret) throw new Error('JWT_SECRET environment variable is missing')
|
|
||||||
|
|
||||||
// =========================================================
|
|
||||||
// Auth Middleware Plugin
|
|
||||||
// =========================================================
|
|
||||||
export default function apiAuth(app: Elysia) {
|
export default function apiAuth(app: Elysia) {
|
||||||
if (!secret) throw new Error('JWT_SECRET environment variable is missing')
|
if (!secret) {
|
||||||
|
throw new Error('JWT_SECRET is not defined')
|
||||||
|
}
|
||||||
return app
|
return app
|
||||||
// Register Bearer and JWT plugins
|
|
||||||
.use(bearer()) // ✅ Extracts Bearer token automatically (case-insensitive)
|
|
||||||
.use(
|
.use(
|
||||||
jwt({
|
jwt({
|
||||||
name: 'jwt',
|
name: 'jwt',
|
||||||
secret,
|
secret,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
.derive(async ({ cookie, headers, jwt }) => {
|
||||||
|
let token: string | undefined
|
||||||
|
|
||||||
// Derive user from JWT or cookie
|
if (cookie?.token?.value) {
|
||||||
.derive(async ({ bearer, cookie, jwt }) => {
|
token = cookie.token.value as any
|
||||||
// Normalize token type to string or undefined
|
}
|
||||||
const token =
|
if (headers['x-token']?.startsWith('Bearer ')) {
|
||||||
(typeof bearer === 'string' ? bearer : undefined) ??
|
token = (headers['x-token'] as string).slice(7)
|
||||||
(typeof cookie?.token?.value === 'string' ? cookie.token.value : undefined)
|
}
|
||||||
|
if (headers['authorization']?.startsWith('Bearer ')) {
|
||||||
let user: Awaited<ReturnType<typeof prisma.user.findUnique>> | null = null
|
token = (headers['authorization'] as string).slice(7)
|
||||||
|
}
|
||||||
|
|
||||||
|
let user: null | Awaited<ReturnType<typeof prisma.user.findUnique>> = null
|
||||||
if (token) {
|
if (token) {
|
||||||
try {
|
try {
|
||||||
const decoded = (await jwt.verify(token)) as JWTPayloadSpec
|
const decoded = (await jwt.verify(token)) as JWTPayloadSpec
|
||||||
|
if (decoded.sub) {
|
||||||
if (decoded?.sub && typeof decoded.sub === 'string') {
|
|
||||||
user = await prisma.user.findUnique({
|
user = await prisma.user.findUnique({
|
||||||
where: { id: decoded.sub },
|
where: { id: decoded.sub as string },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('[SERVER][apiAuth] Invalid token:', (err as Error).message)
|
console.warn('[SERVER][apiAuth] Invalid token', err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { user }
|
return { user }
|
||||||
})
|
})
|
||||||
|
.onBeforeHandle(({ user, set }) => {
|
||||||
// Protect all routes by default
|
|
||||||
.onBeforeHandle(({ user, set, request }) => {
|
|
||||||
// Whitelist public routes if needed
|
|
||||||
const publicPaths = ['/auth/login', '/auth/register', '/public']
|
|
||||||
if (publicPaths.some((path) => request.url.includes(path))) return
|
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
set.status = 401
|
set.status = 401
|
||||||
return { error: 'Unauthorized' }
|
return { error: 'Unauthorized' }
|
||||||
|
|||||||
Reference in New Issue
Block a user