Files
CRM_Montzar/apps/api/src/portal/portal-auth.ts
T

67 lines
1.9 KiB
TypeScript

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<string>('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;
},
);