Files
CRM_Montzar/apps/api/src/public-api/api-key-auth.guard.ts
T

51 lines
1.5 KiB
TypeScript
Raw Normal View History

import {
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { BillingService } from '../billing/billing.service';
import { ApiKeysService } from './api-keys.service';
@Injectable()
export class ApiKeyAuthGuard implements CanActivate {
constructor(
private readonly apiKeys: ApiKeysService,
private readonly billing: BillingService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const req = context.switchToHttp().getRequest<{
headers: Record<string, string | string[] | undefined>;
user?: {
userId: string;
organizationId: string;
role: string;
apiKeyId?: string;
};
}>();
const header =
req.headers['x-api-key'] ??
(typeof req.headers.authorization === 'string' &&
req.headers.authorization.toLowerCase().startsWith('bearer mk_')
? req.headers.authorization.slice(7).trim()
: undefined);
const raw = Array.isArray(header) ? header[0] : header;
if (!raw?.trim()) throw new UnauthorizedException('کلید API لازم است');
const auth = await this.apiKeys.authenticate(raw.trim());
await this.billing.requireActiveForOrganization(auth.organizationId);
await this.billing.requireModule(auth.organizationId, 'public_api');
req.user = {
userId: `api-key:${auth.apiKeyId}`,
organizationId: auth.organizationId,
role: auth.role,
apiKeyId: auth.apiKeyId,
};
return true;
}
}