Files
aurak/server/src/auth/api-key.guard.ts
T
Developer 0a9588abb7 feat: implement QuestionBank CRUD with pagination and template query
- Add pagination support to findAll (page, limit query params)
- Add findByTemplateId method to service
- Add GET /by-template/:templateId endpoint to controller
- Service already includes CRUD for QuestionBank and QuestionBankItem
2026-04-23 17:19:11 +08:00

57 lines
1.5 KiB
TypeScript

import {
Injectable,
CanActivate,
ExecutionContext,
UnauthorizedException,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { UserService } from '../user/user.service';
import { Request } from 'express';
import { IS_PUBLIC_KEY } from './public.decorator';
@Injectable()
export class ApiKeyGuard implements CanActivate {
constructor(
private reflector: Reflector,
private userService: UserService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
context.getHandler(),
context.getClass(),
]);
if (isPublic) {
return true;
}
const request = context
.switchToHttp()
.getRequest<Request & { user?: any; tenantId?: string }>();
const apiKey = this.extractApiKeyFromHeader(request);
if (apiKey) {
const user = await this.userService.findByApiKey(apiKey);
if (user) {
request.user = user;
request.tenantId = user.tenantId;
return true;
}
throw new UnauthorizedException('Invalid API key');
}
throw new UnauthorizedException('Missing API key');
}
private extractApiKeyFromHeader(request: Request): string | undefined {
const authHeader = request.headers.authorization;
if (authHeader && authHeader.startsWith('Bearer kb_')) {
return authHeader.substring(7, authHeader.length);
}
const headerKey = request.headers['x-api-key'] as string;
if (headerKey) return headerKey;
return undefined;
}
}