import { Injectable, UnauthorizedException } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { PassportStrategy } from '@nestjs/passport'; import type { Request } from 'express'; import { ExtractJwt, Strategy } from 'passport-jwt'; import type { JwtPayload } from '../auth.types'; import type { AuthUser } from '../auth.types'; import { PlatformPrismaService } from '../../prisma/platform-prisma.service'; import { TenantConnectionService } from '../../tenancy/tenant-connection.service'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor( config: ConfigService, private readonly platform: PlatformPrismaService, private readonly tenants: TenantConnectionService, ) { super({ jwtFromRequest: ExtractJwt.fromExtractors([ (request: Request) => request?.cookies?.sinka_access ?? null, ExtractJwt.fromAuthHeaderAsBearerToken(), ]), ignoreExpiration: false, secretOrKey: config.getOrThrow('JWT_SECRET'), }); } async validate(payload: JwtPayload): Promise { if (payload.role === 'PLATFORM_ADMIN') { const user = await this.platform.platformUser.findUnique({ where: { id: payload.sub } }); if (!user) { throw new UnauthorizedException(); } return { ...payload, kind: 'platform' }; } if (!payload.tenantId) { throw new UnauthorizedException(); } const tenant = await this.platform.tenant.findUnique({ where: { id: payload.tenantId } }); if (!tenant || tenant.status !== 'ACTIVE') { throw new UnauthorizedException(); } const db = await this.tenants.getByTenantId(tenant.id); const user = await db.user.findUnique({ where: { id: payload.sub } }); if (!user) { throw new UnauthorizedException(); } return { ...payload, tenantSlug: tenant.slug, kind: 'tenant' }; } }