mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 23:27:14 +00:00
feat: request ID support
This commit is contained in:
@@ -17,6 +17,7 @@ import { Logger } from "pino";
|
|||||||
import { HsmModule } from "@app/ee/services/hsm/hsm-types";
|
import { HsmModule } from "@app/ee/services/hsm/hsm-types";
|
||||||
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||||
import { getConfig, IS_PACKAGED } from "@app/lib/config/env";
|
import { getConfig, IS_PACKAGED } from "@app/lib/config/env";
|
||||||
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
import { TQueueServiceFactory } from "@app/queue";
|
import { TQueueServiceFactory } from "@app/queue";
|
||||||
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
||||||
|
|
||||||
@@ -47,6 +48,7 @@ export const main = async ({ db, hsmModule, auditLogDb, smtp, logger, queue, key
|
|||||||
|
|
||||||
const server = fastify({
|
const server = fastify({
|
||||||
logger: appCfg.NODE_ENV === "test" ? false : logger,
|
logger: appCfg.NODE_ENV === "test" ? false : logger,
|
||||||
|
genReqId: () => `req-${alphaNumericNanoId(14)}`,
|
||||||
trustProxy: true,
|
trustProxy: true,
|
||||||
connectionTimeout: appCfg.isHsmConfigured ? 90_000 : 30_000,
|
connectionTimeout: appCfg.isHsmConfigured ? 90_000 : 30_000,
|
||||||
ignoreTrailingSlash: true,
|
ignoreTrailingSlash: true,
|
||||||
|
|||||||
@@ -39,77 +39,96 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider
|
|||||||
if (error instanceof BadRequestError) {
|
if (error instanceof BadRequestError) {
|
||||||
void res
|
void res
|
||||||
.status(HttpStatusCodes.BadRequest)
|
.status(HttpStatusCodes.BadRequest)
|
||||||
.send({ statusCode: HttpStatusCodes.BadRequest, message: error.message, error: error.name });
|
.send({ requestId: req.id, statusCode: HttpStatusCodes.BadRequest, message: error.message, error: error.name });
|
||||||
} else if (error instanceof NotFoundError) {
|
} else if (error instanceof NotFoundError) {
|
||||||
void res
|
void res
|
||||||
.status(HttpStatusCodes.NotFound)
|
.status(HttpStatusCodes.NotFound)
|
||||||
.send({ statusCode: HttpStatusCodes.NotFound, message: error.message, error: error.name });
|
.send({ requestId: req.id, statusCode: HttpStatusCodes.NotFound, message: error.message, error: error.name });
|
||||||
} else if (error instanceof UnauthorizedError) {
|
} else if (error instanceof UnauthorizedError) {
|
||||||
void res
|
void res.status(HttpStatusCodes.Unauthorized).send({
|
||||||
.status(HttpStatusCodes.Unauthorized)
|
requestId: req.id,
|
||||||
.send({ statusCode: HttpStatusCodes.Unauthorized, message: error.message, error: error.name });
|
statusCode: HttpStatusCodes.Unauthorized,
|
||||||
|
message: error.message,
|
||||||
|
error: error.name
|
||||||
|
});
|
||||||
} else if (error instanceof DatabaseError || error instanceof InternalServerError) {
|
} else if (error instanceof DatabaseError || error instanceof InternalServerError) {
|
||||||
void res
|
void res.status(HttpStatusCodes.InternalServerError).send({
|
||||||
.status(HttpStatusCodes.InternalServerError)
|
requestId: req.id,
|
||||||
.send({ statusCode: HttpStatusCodes.InternalServerError, message: "Something went wrong", error: error.name });
|
statusCode: HttpStatusCodes.InternalServerError,
|
||||||
|
message: "Something went wrong",
|
||||||
|
error: error.name
|
||||||
|
});
|
||||||
} else if (error instanceof GatewayTimeoutError) {
|
} else if (error instanceof GatewayTimeoutError) {
|
||||||
void res
|
void res.status(HttpStatusCodes.GatewayTimeout).send({
|
||||||
.status(HttpStatusCodes.GatewayTimeout)
|
requestId: req.id,
|
||||||
.send({ statusCode: HttpStatusCodes.GatewayTimeout, message: error.message, error: error.name });
|
statusCode: HttpStatusCodes.GatewayTimeout,
|
||||||
|
message: error.message,
|
||||||
|
error: error.name
|
||||||
|
});
|
||||||
} else if (error instanceof ZodError) {
|
} else if (error instanceof ZodError) {
|
||||||
void res
|
void res.status(HttpStatusCodes.Unauthorized).send({
|
||||||
.status(HttpStatusCodes.Unauthorized)
|
requestId: req.id,
|
||||||
.send({ statusCode: HttpStatusCodes.Unauthorized, error: "ValidationFailure", message: error.issues });
|
statusCode: HttpStatusCodes.Unauthorized,
|
||||||
|
error: "ValidationFailure",
|
||||||
|
message: error.issues
|
||||||
|
});
|
||||||
} else if (error instanceof ForbiddenError) {
|
} else if (error instanceof ForbiddenError) {
|
||||||
void res.status(HttpStatusCodes.Forbidden).send({
|
void res.status(HttpStatusCodes.Forbidden).send({
|
||||||
|
requestId: req.id,
|
||||||
statusCode: HttpStatusCodes.Forbidden,
|
statusCode: HttpStatusCodes.Forbidden,
|
||||||
error: "PermissionDenied",
|
error: "PermissionDenied",
|
||||||
message: `You are not allowed to ${error.action} on ${error.subjectType} - ${JSON.stringify(error.subject)}`
|
message: `You are not allowed to ${error.action} on ${error.subjectType} - ${JSON.stringify(error.subject)}`
|
||||||
});
|
});
|
||||||
} else if (error instanceof ForbiddenRequestError) {
|
} else if (error instanceof ForbiddenRequestError) {
|
||||||
void res.status(HttpStatusCodes.Forbidden).send({
|
void res.status(HttpStatusCodes.Forbidden).send({
|
||||||
|
requestId: req.id,
|
||||||
statusCode: HttpStatusCodes.Forbidden,
|
statusCode: HttpStatusCodes.Forbidden,
|
||||||
message: error.message,
|
message: error.message,
|
||||||
error: error.name
|
error: error.name
|
||||||
});
|
});
|
||||||
} else if (error instanceof RateLimitError) {
|
} else if (error instanceof RateLimitError) {
|
||||||
void res.status(HttpStatusCodes.TooManyRequests).send({
|
void res.status(HttpStatusCodes.TooManyRequests).send({
|
||||||
|
requestId: req.id,
|
||||||
statusCode: HttpStatusCodes.TooManyRequests,
|
statusCode: HttpStatusCodes.TooManyRequests,
|
||||||
message: error.message,
|
message: error.message,
|
||||||
error: error.name
|
error: error.name
|
||||||
});
|
});
|
||||||
} else if (error instanceof ScimRequestError) {
|
} else if (error instanceof ScimRequestError) {
|
||||||
void res.status(error.status).send({
|
void res.status(error.status).send({
|
||||||
|
requestId: req.id,
|
||||||
schemas: error.schemas,
|
schemas: error.schemas,
|
||||||
status: error.status,
|
status: error.status,
|
||||||
detail: error.detail
|
detail: error.detail
|
||||||
});
|
});
|
||||||
} else if (error instanceof OidcAuthError) {
|
} else if (error instanceof OidcAuthError) {
|
||||||
void res
|
void res.status(HttpStatusCodes.InternalServerError).send({
|
||||||
.status(HttpStatusCodes.InternalServerError)
|
requestId: req.id,
|
||||||
.send({ statusCode: HttpStatusCodes.InternalServerError, message: error.message, error: error.name });
|
statusCode: HttpStatusCodes.InternalServerError,
|
||||||
|
message: error.message,
|
||||||
|
error: error.name
|
||||||
|
});
|
||||||
} else if (error instanceof jwt.JsonWebTokenError) {
|
} else if (error instanceof jwt.JsonWebTokenError) {
|
||||||
const message = (() => {
|
let errorMessage = error.message;
|
||||||
if (error.message === JWTErrors.JwtExpired) {
|
|
||||||
return "Your token has expired. Please re-authenticate.";
|
|
||||||
}
|
|
||||||
if (error.message === JWTErrors.JwtMalformed) {
|
|
||||||
return "The provided access token is malformed. Please use a valid token or generate a new one and try again.";
|
|
||||||
}
|
|
||||||
if (error.message === JWTErrors.InvalidAlgorithm) {
|
|
||||||
return "The access token is signed with an invalid algorithm. Please provide a valid token and try again.";
|
|
||||||
}
|
|
||||||
|
|
||||||
return error.message;
|
if (error.message === JWTErrors.JwtExpired) {
|
||||||
})();
|
errorMessage = "Your token has expired. Please re-authenticate.";
|
||||||
|
} else if (error.message === JWTErrors.JwtMalformed) {
|
||||||
|
errorMessage =
|
||||||
|
"The provided access token is malformed. Please use a valid token or generate a new one and try again.";
|
||||||
|
} else if (error.message === JWTErrors.InvalidAlgorithm) {
|
||||||
|
errorMessage =
|
||||||
|
"The access token is signed with an invalid algorithm. Please provide a valid token and try again.";
|
||||||
|
}
|
||||||
|
|
||||||
void res.status(HttpStatusCodes.Forbidden).send({
|
void res.status(HttpStatusCodes.Forbidden).send({
|
||||||
|
requestId: req.id,
|
||||||
statusCode: HttpStatusCodes.Forbidden,
|
statusCode: HttpStatusCodes.Forbidden,
|
||||||
error: "TokenError",
|
error: "TokenError",
|
||||||
message
|
message: errorMessage
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
void res.status(HttpStatusCodes.InternalServerError).send({
|
void res.status(HttpStatusCodes.InternalServerError).send({
|
||||||
|
requestId: req.id,
|
||||||
statusCode: HttpStatusCodes.InternalServerError,
|
statusCode: HttpStatusCodes.InternalServerError,
|
||||||
error: "InternalServerError",
|
error: "InternalServerError",
|
||||||
message: "Something went wrong"
|
message: "Something went wrong"
|
||||||
|
|||||||
@@ -30,26 +30,31 @@ export const integrationAuthPubSchema = IntegrationAuthsSchema.pick({
|
|||||||
|
|
||||||
export const DefaultResponseErrorsSchema = {
|
export const DefaultResponseErrorsSchema = {
|
||||||
400: z.object({
|
400: z.object({
|
||||||
|
requestId: z.string(),
|
||||||
statusCode: z.literal(400),
|
statusCode: z.literal(400),
|
||||||
message: z.string(),
|
message: z.string(),
|
||||||
error: z.string()
|
error: z.string()
|
||||||
}),
|
}),
|
||||||
404: z.object({
|
404: z.object({
|
||||||
|
requestId: z.string(),
|
||||||
statusCode: z.literal(404),
|
statusCode: z.literal(404),
|
||||||
message: z.string(),
|
message: z.string(),
|
||||||
error: z.string()
|
error: z.string()
|
||||||
}),
|
}),
|
||||||
401: z.object({
|
401: z.object({
|
||||||
|
requestId: z.string(),
|
||||||
statusCode: z.literal(401),
|
statusCode: z.literal(401),
|
||||||
message: z.any(),
|
message: z.any(),
|
||||||
error: z.string()
|
error: z.string()
|
||||||
}),
|
}),
|
||||||
403: z.object({
|
403: z.object({
|
||||||
|
requestId: z.string(),
|
||||||
statusCode: z.literal(403),
|
statusCode: z.literal(403),
|
||||||
message: z.string(),
|
message: z.string(),
|
||||||
error: z.string()
|
error: z.string()
|
||||||
}),
|
}),
|
||||||
500: z.object({
|
500: z.object({
|
||||||
|
requestId: z.string(),
|
||||||
statusCode: z.literal(500),
|
statusCode: z.literal(500),
|
||||||
message: z.string(),
|
message: z.string(),
|
||||||
error: z.string()
|
error: z.string()
|
||||||
|
|||||||
@@ -50,12 +50,15 @@ export enum ApiErrorTypes {
|
|||||||
|
|
||||||
export type TApiErrors =
|
export type TApiErrors =
|
||||||
| {
|
| {
|
||||||
|
requestId: string;
|
||||||
error: ApiErrorTypes.ValidationError;
|
error: ApiErrorTypes.ValidationError;
|
||||||
message: ZodIssue[];
|
message: ZodIssue[];
|
||||||
statusCode: 403;
|
statusCode: 403;
|
||||||
}
|
}
|
||||||
| { error: ApiErrorTypes.ForbiddenError; message: string; statusCode: 401 }
|
| { requestId: string; error: ApiErrorTypes.ForbiddenError; message: string; statusCode: 403 }
|
||||||
|
| { requestId: string; error: ApiErrorTypes.UnauthorizedError; message: string; statusCode: 401 }
|
||||||
| {
|
| {
|
||||||
|
requestId: string;
|
||||||
statusCode: 400;
|
statusCode: 400;
|
||||||
message: string;
|
message: string;
|
||||||
error: ApiErrorTypes.BadRequestError;
|
error: ApiErrorTypes.BadRequestError;
|
||||||
|
|||||||
@@ -28,20 +28,26 @@ export const queryClient = new QueryClient({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
<div className="mt-2">Request ID: {serverResponse.requestId}</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (serverResponse.statusCode === 401) {
|
|
||||||
|
const title =
|
||||||
|
// eslint-disable-next-line no-nested-ternary
|
||||||
|
serverResponse.statusCode === 403
|
||||||
|
? "Forbidden Access"
|
||||||
|
: serverResponse.statusCode === 401
|
||||||
|
? "Unauthorized Access"
|
||||||
|
: "Bad Request";
|
||||||
|
|
||||||
createNotification({
|
createNotification({
|
||||||
title: "Forbidden Access",
|
title,
|
||||||
type: "error",
|
type: "error",
|
||||||
text: serverResponse.message
|
text: `${serverResponse.message} [requestId=${serverResponse.requestId}]`
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
|
||||||
createNotification({ title: "Bad Request", type: "error", text: serverResponse.message });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user