sinka/api/src/auth/strategies/jwt.strategy.ts
2026-09-15 21:10:42 -03:00

55 lines
1.9 KiB
TypeScript

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<string>('JWT_SECRET'),
});
}
async validate(payload: JwtPayload): Promise<AuthUser> {
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' };
}
}