Optimize metadata queries (#7013)

In this PR:

1. Refactor guards to avoid duplicated queries: WorkspaceAuthGuard and
UserAuthGuard only check for existence of workspace and user in the
request without querying the database
This commit is contained in:
Charles Bochet
2024-09-13 19:11:32 +02:00
committed by Charles Bochet
parent cf8b1161cc
commit 523df5398a
132 changed files with 818 additions and 6372 deletions

View File

@ -1,27 +1,27 @@
import {
Injectable,
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { GqlExecutionContext } from '@nestjs/graphql';
import { Observable } from 'rxjs';
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
import { getRequest } from 'src/utils/extract-request';
@Injectable()
export class DemoEnvGuard extends AuthGuard(['jwt']) {
constructor(private readonly environmentService: EnvironmentService) {
super();
}
export class DemoEnvGuard implements CanActivate {
constructor(private readonly environmentService: EnvironmentService) {}
getRequest(context: ExecutionContext) {
return getRequest(context);
}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const ctx = GqlExecutionContext.create(context);
const request = ctx.getContext().req;
// TODO: input should be typed
handleRequest(err: any, user: any) {
const demoWorkspaceIds = this.environmentService.get('DEMO_WORKSPACE_IDS');
const currentUserWorkspaceId = user?.workspace?.id;
const currentUserWorkspaceId = request.workspace?.id;
if (!currentUserWorkspaceId) {
throw new UnauthorizedException('Unauthorized for not logged in user');
@ -31,6 +31,6 @@ export class DemoEnvGuard extends AuthGuard(['jwt']) {
throw new UnauthorizedException('Unauthorized for demo workspace');
}
return user;
return true;
}
}

View File

@ -0,0 +1,35 @@
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
@Injectable()
export class JwtAuthGuard implements CanActivate {
constructor(
private readonly tokenService: TokenService,
private readonly workspaceStorageCacheService: WorkspaceCacheStorageService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
try {
const data = await this.tokenService.validateToken(request);
const metadataVersion =
await this.workspaceStorageCacheService.getMetadataVersion(
data.workspace.id,
);
request.user = data.user;
request.apiKey = data.apiKey;
request.workspace = data.workspace;
request.workspaceId = data.workspace.id;
request.workspaceMetadataVersion = metadataVersion;
request.workspaceMemberId = data.workspaceMemberId;
return true;
} catch (error) {
return false;
}
}
}

View File

@ -1,40 +0,0 @@
import {
ExecutionContext,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { JsonWebTokenError } from 'jsonwebtoken';
import { assert } from 'src/utils/assert';
import { getRequest } from 'src/utils/extract-request';
@Injectable()
export class JwtAuthGuard extends AuthGuard(['jwt']) {
constructor() {
super();
}
getRequest(context: ExecutionContext) {
return getRequest(context);
}
handleRequest(err: any, user: any, info: any) {
assert(user, '', UnauthorizedException);
if (err) {
throw err;
}
if (info && info instanceof Error) {
if (info instanceof JsonWebTokenError) {
info = String(info);
}
throw new UnauthorizedException(info);
}
return user;
}
}

View File

@ -1,23 +0,0 @@
import { ExecutionContext, Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { getRequest } from 'src/utils/extract-request';
@Injectable()
export class OptionalJwtAuthGuard extends AuthGuard(['jwt']) {
constructor() {
super();
}
getRequest(context: ExecutionContext) {
const request = getRequest(context);
return request;
}
handleRequest(err, user, info) {
if (err || info) return null;
return user;
}
}

View File

@ -0,0 +1,15 @@
import { CanActivate, ExecutionContext } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { Observable } from 'rxjs';
export class UserAuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const ctx = GqlExecutionContext.create(context);
const request = ctx.getContext().req;
return request.user !== undefined;
}
}

View File

@ -0,0 +1,15 @@
import { CanActivate, ExecutionContext } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { Observable } from 'rxjs';
export class WorkspaceAuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const ctx = GqlExecutionContext.create(context);
const request = ctx.getContext().req;
return request.workspace !== undefined;
}
}