import { CanActivate, createParamDecorator, ExecutionContext, Injectable, UnauthorizedException, } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { JwtService } from '@nestjs/jwt'; export type PortalActor = { personId: string; organizationId: string; mobile: string; }; @Injectable() export class PortalAuthGuard implements CanActivate { constructor( private readonly jwt: JwtService, private readonly config: ConfigService, ) {} canActivate(context: ExecutionContext): boolean { const req = context.switchToHttp().getRequest<{ headers: { authorization?: string }; portalActor?: PortalActor; }>(); const header = req.headers.authorization; if (!header?.startsWith('Bearer ')) { throw new UnauthorizedException('ورود پرتال لازم است'); } const token = header.slice(7); try { const payload = this.jwt.verify<{ sub: string; organizationId: string; typ?: string; mobile?: string; }>(token, { secret: this.config.get('JWT_SECRET') ?? 'dev-secret', }); if (payload.typ !== 'portal' || !payload.sub || !payload.organizationId) { throw new UnauthorizedException('توکن پرتال نامعتبر است'); } req.portalActor = { personId: payload.sub, organizationId: payload.organizationId, mobile: payload.mobile ?? '', }; return true; } catch { throw new UnauthorizedException('نشست پرتال منقضی یا نامعتبر است'); } } } export const CurrentPortal = createParamDecorator( (_data: unknown, ctx: ExecutionContext): PortalActor => { const req = ctx.switchToHttp().getRequest<{ portalActor?: PortalActor }>(); if (!req.portalActor) { throw new UnauthorizedException('ورود پرتال لازم است'); } return req.portalActor; }, );