Refactor backend and add exception handlers (#189)

This commit is contained in:
Charles Bochet
2023-06-04 00:21:36 +02:00
committed by GitHub
parent a2fe159c2c
commit bbc80cd543
35 changed files with 459 additions and 899 deletions
+7 -2
View File
@@ -11,10 +11,12 @@ import { AffectedRows } from '../@generated/prisma/affected-rows.output';
import { DeleteManyCompanyArgs } from '../@generated/company/delete-many-company.args';
import { Workspace } from '@prisma/client';
import { ArgsService } from './services/args.service';
import { CheckWorkspaceOwnership } from 'src/auth/guards/check-workspace-ownership.guard';
import { Prisma } from '@prisma/client';
import { UpdateOneGuard } from './guards/update-one.guard';
import { DeleteManyGuard } from './guards/delete-many.guard';
import { CreateOneGuard } from './guards/create-one.guard';
@UseGuards(JwtAuthGuard, CheckWorkspaceOwnership)
@UseGuards(JwtAuthGuard)
@Resolver(() => Company)
export class CompanyResolver {
constructor(
@@ -35,6 +37,7 @@ export class CompanyResolver {
return this.prismaService.company.findMany(preparedArgs);
}
@UseGuards(UpdateOneGuard)
@Mutation(() => Company, {
nullable: true,
})
@@ -50,6 +53,7 @@ export class CompanyResolver {
} satisfies UpdateOneCompanyArgs as Prisma.CompanyUpdateArgs);
}
@UseGuards(DeleteManyGuard)
@Mutation(() => AffectedRows, {
nullable: false,
})
@@ -61,6 +65,7 @@ export class CompanyResolver {
});
}
@UseGuards(CreateOneGuard)
@Mutation(() => Company, {
nullable: false,
})
@@ -0,0 +1,18 @@
import { Catch, HttpException } from '@nestjs/common';
import { GqlExceptionFilter } from '@nestjs/graphql';
import { Prisma } from '@prisma/client';
import { GraphQLError } from 'graphql';
@Catch()
export class ExceptionFilter implements GqlExceptionFilter {
catch(exception: HttpException) {
if (exception instanceof Prisma.PrismaClientValidationError) {
throw new GraphQLError('Invalid request', {
extensions: {
code: 'INVALID_REQUEST',
},
});
}
return exception;
}
}
@@ -0,0 +1,12 @@
import { CanActivate, Injectable } from '@nestjs/common';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class CreateOneGuard implements CanActivate {
constructor(private prismaService: PrismaService) {}
async canActivate(): Promise<boolean> {
// TODO
return true;
}
}
@@ -0,0 +1,12 @@
import { CanActivate, Injectable } from '@nestjs/common';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class DeleteManyGuard implements CanActivate {
constructor(private prismaService: PrismaService) {}
async canActivate(): Promise<boolean> {
// TODO
return true;
}
}
@@ -0,0 +1,50 @@
import {
CanActivate,
ExecutionContext,
HttpException,
HttpStatus,
Injectable,
} from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class UpdateOneGuard implements CanActivate {
constructor(private prismaService: PrismaService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const gqlContext = GqlExecutionContext.create(context);
const request = gqlContext.getContext().req;
const entity = gqlContext.getArgByIndex(3).returnType?.name;
const args = gqlContext.getArgs();
console.log(args.data);
if (!entity || !args.where?.id) {
throw new HttpException(
{ reason: 'Invalid Request' },
HttpStatus.BAD_REQUEST,
);
}
const object = await this.prismaService[entity].findUniqueOrThrow({
where: { id: args.where.id },
});
if (!object) {
throw new HttpException(
{ reason: 'Record not found' },
HttpStatus.NOT_FOUND,
);
}
const workspace = await request.workspace;
if (object.workspaceId !== workspace.id) {
throw new HttpException(
{ reason: 'Record not found' },
HttpStatus.NOT_FOUND,
);
}
return true;
}
}
+7 -2
View File
@@ -11,10 +11,12 @@ import { DeleteManyPersonArgs } from '../@generated/person/delete-many-person.ar
import { Workspace } from '../@generated/workspace/workspace.model';
import { AuthWorkspace } from './decorators/auth-workspace.decorator';
import { ArgsService } from './services/args.service';
import { CheckWorkspaceOwnership } from 'src/auth/guards/check-workspace-ownership.guard';
import { Prisma } from '@prisma/client';
import { UpdateOneGuard } from './guards/update-one.guard';
import { DeleteManyGuard } from './guards/delete-many.guard';
import { CreateOneGuard } from './guards/create-one.guard';
@UseGuards(JwtAuthGuard, CheckWorkspaceOwnership)
@UseGuards(JwtAuthGuard)
@Resolver(() => Person)
export class PersonResolver {
constructor(
@@ -39,6 +41,7 @@ export class PersonResolver {
});
}
@UseGuards(UpdateOneGuard)
@Mutation(() => Person, {
nullable: true,
})
@@ -54,6 +57,7 @@ export class PersonResolver {
} satisfies UpdateOnePersonArgs as Prisma.PersonUpdateArgs);
}
@UseGuards(DeleteManyGuard)
@Mutation(() => AffectedRows, {
nullable: false,
})
@@ -65,6 +69,7 @@ export class PersonResolver {
});
}
@UseGuards(CreateOneGuard)
@Mutation(() => Person, {
nullable: false,
})
+6 -9
View File
@@ -1,23 +1,20 @@
import { Resolver, Query, Args } from '@nestjs/graphql';
import { PrismaService } from 'src/database/prisma.service';
import { UseGuards } from '@nestjs/common';
import { JwtAuthGuard } from 'src/auth/guards/jwt.auth.guard';
import { UseFilters, UseGuards } from '@nestjs/common';
import { User } from '../@generated/user/user.model';
import { FindManyUserArgs } from '../@generated/user/find-many-user.args';
import { Workspace } from '@prisma/client';
import { AuthWorkspace } from './decorators/auth-workspace.decorator';
import { ArgsService } from './services/args.service';
import { CheckWorkspaceOwnership } from 'src/auth/guards/check-workspace-ownership.guard';
import { ExceptionFilter } from './exception-filters/exception.filter';
import { JwtAuthGuard } from 'src/auth/guards/jwt.auth.guard';
@UseGuards(JwtAuthGuard, CheckWorkspaceOwnership)
@UseGuards(JwtAuthGuard)
@Resolver(() => User)
export class UserResolver {
constructor(
private readonly prismaService: PrismaService,
private readonly argsService: ArgsService,
) {}
constructor(private readonly prismaService: PrismaService) {}
@UseFilters(ExceptionFilter)
@Query(() => [User], {
nullable: false,
})