feat(api): improve errors and error handling

This commit is contained in:
Daniel Hougaard
2024-09-27 20:02:43 +04:00
parent 02c51b05b6
commit 2d51ed317f
99 changed files with 922 additions and 847 deletions
+1 -1
View File
@@ -70,7 +70,7 @@ export const injectAuditLogInfo = fp(async (server: FastifyZodProvider) => {
metadata: {}
};
} else {
throw new BadRequestError({ message: "Missing logic for other actor" });
throw new BadRequestError({ message: "Invalid actor type provided" });
}
req.auditLogInfo = payload;
});
@@ -5,7 +5,7 @@ import jwt, { JwtPayload } from "jsonwebtoken";
import { TServiceTokens, TUsers } from "@app/db/schemas";
import { TScimTokenJwtPayload } from "@app/ee/services/scim/scim-types";
import { getConfig } from "@app/lib/config/env";
import { UnauthorizedError } from "@app/lib/errors";
import { BadRequestError } from "@app/lib/errors";
import { ActorType, AuthMethod, AuthMode, AuthModeJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
import { TIdentityAccessTokenJwtPayload } from "@app/services/identity-access-token/identity-access-token-types";
@@ -167,7 +167,7 @@ export const injectIdentity = fp(async (server: FastifyZodProvider) => {
break;
}
default:
throw new UnauthorizedError({ name: "Unknown token strategy" });
throw new BadRequestError({ message: "Invalid token strategy provided" });
}
});
});
@@ -1,6 +1,6 @@
import { FastifyReply, FastifyRequest, HookHandlerDoneFunction } from "fastify";
import { UnauthorizedError } from "@app/lib/errors";
import { ForbiddenRequestError } from "@app/lib/errors";
import { ActorType } from "@app/services/auth/auth-type";
export const verifySuperAdmin = <T extends FastifyRequest>(
@@ -9,9 +9,8 @@ export const verifySuperAdmin = <T extends FastifyRequest>(
done: HookHandlerDoneFunction
) => {
if (req.auth.actor !== ActorType.USER || !req.auth.user.superAdmin)
throw new UnauthorizedError({
name: "Unauthorized access",
message: "Requires superadmin access"
throw new ForbiddenRequestError({
message: "Requires elevated super admin privileges"
});
done();
};
@@ -1,6 +1,6 @@
import { FastifyReply, FastifyRequest, HookHandlerDoneFunction } from "fastify";
import { UnauthorizedError } from "@app/lib/errors";
import { ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
import { AuthMode } from "@app/services/auth/auth-type";
interface TAuthOptions {
@@ -11,11 +11,11 @@ export const verifyAuth =
<T extends FastifyRequest>(authStrategies: AuthMode[], options: TAuthOptions = { requireOrg: true }) =>
(req: T, _res: FastifyReply, done: HookHandlerDoneFunction) => {
if (!Array.isArray(authStrategies)) throw new Error("Auth strategy must be array");
if (!req.auth) throw new UnauthorizedError({ name: "Unauthorized access", message: "Token missing" });
if (!req.auth) throw new UnauthorizedError({ message: "Token missing" });
const isAccessAllowed = authStrategies.some((strategy) => strategy === req.auth.authMode);
if (!isAccessAllowed) {
throw new UnauthorizedError({ name: `${req.url} Unauthorized Access` });
throw new ForbiddenRequestError({ name: `Forbidden access to ${req.url}` });
}
// New optional option. There are some routes which do not require an organization ID to be present on the request.
+13 -6
View File
@@ -6,6 +6,7 @@ import { ZodError } from "zod";
import {
BadRequestError,
DatabaseError,
ForbiddenRequestError,
InternalServerError,
NotFoundError,
ScimRequestError,
@@ -26,17 +27,23 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider
} else if (error instanceof NotFoundError) {
void res.status(404).send({ statusCode: 404, message: error.message, error: error.name });
} else if (error instanceof UnauthorizedError) {
void res.status(403).send({ statusCode: 403, message: error.message, error: error.name });
void res.status(401).send({ statusCode: 401, message: error.message, error: error.name });
} else if (error instanceof DatabaseError || error instanceof InternalServerError) {
void res.status(500).send({ statusCode: 500, message: "Something went wrong", error: error.name });
} else if (error instanceof ZodError) {
void res.status(403).send({ statusCode: 403, error: "ValidationFailure", message: error.issues });
void res.status(401).send({ statusCode: 401, error: "ValidationFailure", message: error.issues });
} else if (error instanceof ForbiddenError) {
void res.status(401).send({
statusCode: 401,
void res.status(403).send({
statusCode: 403,
error: "PermissionDenied",
message: `You are not allowed to ${error.action} on ${error.subjectType}`
});
} else if (error instanceof ForbiddenRequestError) {
void res.status(403).send({
statusCode: 403,
message: error.message,
error: error.name
});
} else if (error instanceof ScimRequestError) {
void res.status(error.status).send({
schemas: error.schemas,
@@ -59,8 +66,8 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider
return error.message;
})();
void res.status(401).send({
statusCode: 401,
void res.status(403).send({
statusCode: 403,
error: "TokenError",
message
});