55 lines
1.9 KiB
TypeScript
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' };
|
|
}
|
|
}
|