api-key.guard.ts 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common';
  2. import { Reflector } from '@nestjs/core';
  3. import { UserService } from '../user/user.service';
  4. import { Request } from 'express';
  5. import { IS_PUBLIC_KEY } from './public.decorator';
  6. @Injectable()
  7. export class ApiKeyGuard implements CanActivate {
  8. constructor(
  9. private reflector: Reflector,
  10. private userService: UserService,
  11. ) { }
  12. async canActivate(context: ExecutionContext): Promise<boolean> {
  13. const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
  14. context.getHandler(),
  15. context.getClass(),
  16. ]);
  17. if (isPublic) {
  18. return true;
  19. }
  20. const request = context.switchToHttp().getRequest<Request & { user?: any, tenantId?: string }>();
  21. const apiKey = this.extractApiKeyFromHeader(request);
  22. if (apiKey) {
  23. const user = await this.userService.findByApiKey(apiKey);
  24. if (user) {
  25. request.user = user;
  26. request.tenantId = user.tenantId;
  27. return true;
  28. }
  29. throw new UnauthorizedException('Invalid API key');
  30. }
  31. throw new UnauthorizedException('Missing API key');
  32. }
  33. private extractApiKeyFromHeader(request: Request): string | undefined {
  34. const authHeader = request.headers.authorization;
  35. if (authHeader && authHeader.startsWith('Bearer kb_')) {
  36. return authHeader.substring(7, authHeader.length);
  37. }
  38. const headerKey = request.headers['x-api-key'] as string;
  39. if (headerKey) return headerKey;
  40. return undefined;
  41. }
  42. }