Merge branch 'dev' into feature-email-verification

This commit is contained in:
Stefan
2022-04-29 11:40:28 +02:00
committed by GitHub
8 changed files with 184 additions and 19 deletions
+7 -7
View File
@@ -19,13 +19,13 @@ export const getAllEvents = async (req: Request, res: Response) => {
id: false,
},
});
if (events.length > 0)
res.status(200).json({
type: "success",
payload: {
events,
},
});
res.status(200).json({
type: "success",
payload: {
events,
},
});
};
export const getEvent = async (req: Request, res: Response) => {
+11
View File
@@ -0,0 +1,11 @@
import { NextFunction, Request, Response } from "express";
import logger from "../error/logger";
export default function debugLogger(req: Request, res: Response, next: NextFunction) {
// Only log when in development mode
if (process.env.NODE_ENV === "development") {
logger.debug(`Request to: ${req.url}`);
}
next();
}
+16
View File
@@ -0,0 +1,16 @@
export default class ForwardableError extends Error {
// If in different context
private readonly __id = "CUSTOM_ERROR";
public readonly status: number;
constructor(status: number, message: string) {
super(message);
this.status = status;
}
static isForwardableError(error: any): error is ForwardableError {
return error.__id === "CUSTOM_ERROR";
}
}
+82
View File
@@ -0,0 +1,82 @@
import { PrismaClientUnknownRequestError } from "@prisma/client/runtime";
import { NextFunction, Request, Response } from "express";
import ForwardableError from "./ForwardableError";
import logger from "./logger";
const env = process.env.NODE_ENV || "production";
type ErrorHandler = (err: any, req: Request, res: Response) => boolean;
const customHandlers: ErrorHandler[] = [];
export function addCustomHandler(handler: ErrorHandler) {
customHandlers.push(handler);
}
export function removeCustomHandler(handler: ErrorHandler): Boolean {
const index = customHandlers.findIndex((h) => h === handler);
if (index < 0) {
return false;
}
customHandlers.splice(index);
return true;
}
export default function defaultErrorHandler(err: any, req: Request, res: Response, next: NextFunction) {
for (const handler of customHandlers) {
// Run custom handler
if (handler(err, req, res)) {
return;
}
}
if (ForwardableError.isForwardableError(err)) {
return res.status(err.status).json({
type: "error",
payload: {
message: err.message,
...(env === "development"
? {
stack: err.stack,
}
: {}),
},
});
}
if (err instanceof PrismaClientUnknownRequestError) {
logger.warning(err);
return res.status(404).json({
type: "error",
payload: {
message: "An unknown error occured. This could be due to malformed IDs",
...(env === "development"
? {
prisma: err.message,
stack: err.stack,
}
: {}),
},
});
}
logger.error("--- Unhandled error ---");
logger.error(err);
return res.status(err.status).json({
type: "error",
payload: {
message: err.message,
...(env === "development"
? {
notice: "This error was not caught by any handler, please add handling!",
stack: err.stack,
}
: {}),
},
});
}
+41
View File
@@ -0,0 +1,41 @@
import winston, { createLogger } from "winston";
const {
format: { printf, colorize, combine, timestamp, json, errors, prettyPrint },
} = winston;
const defaultJsonFormat = combine(errors({ stack: true }), timestamp(), json({ space: 2 }));
const customCLIFormat = printf(({ level, message, label, timestamp, stack }) => {
let output = `${level}${stack ? `(1/2:message)` : ""} at ${timestamp}${label ? ` (#${label})` : ""}: ${message}${
stack ? "\n" : ""
}`;
if (stack) {
output += `\n${level}(2/2:stack)${label ? ` (#${label})` : ""}: ${stack}\n\n`;
}
return output;
});
export default createLogger({
levels: winston.config.syslog.levels,
format: combine(errors({ stack: true }), timestamp()),
transports: [
new winston.transports.Console({
level: "debug",
format: combine(timestamp(), colorize(), customCLIFormat),
}),
new winston.transports.File({
filename: "/app/error.log",
level: "error",
format: defaultJsonFormat,
}),
new winston.transports.File({
level: "debug",
filename: "/app/debug.log",
format: defaultJsonFormat,
silent: !(process.env.NODE_ENV === "development"), // Silent when not in development
}),
],
});
+23 -11
View File
@@ -11,11 +11,21 @@ import argon2 from "argon2";
import adminRouter from "./Routes/admin.routes";
import organisationRouter from "./Routes/organisation.routes";
import groupRouter from "./Routes/group.routes";
import defaultErrorHandler from "./Middleware/error/handler";
import logger from "./Middleware/error/logger";
import debugLogger from "./Middleware/debug/logger";
// Set up async error handling
require("express-async-errors");
require("dotenv").config(); // Load dotenv config
const app = express();
if (process.env.NODE_ENV === "development") {
logger.info("Using development mode");
}
async function main() {
// Dev
await prisma.admin.upsert({
@@ -34,16 +44,7 @@ async function main() {
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use((err: any, req: Request, res: Response, next: NextFunction) => {
if (err) {
res.status(400).send({
type: "error",
payload: "The body of your request did not contain valid data",
});
} else {
next();
}
});
app.use(debugLogger);
// Admin authentication endpoints
app.use("/api/authentication", adminAuthRouter);
@@ -56,13 +57,24 @@ async function main() {
app.use("/api/organisations", organisationRouter);
app.use("/api/groups", groupRouter);
// Error handling
app.use(defaultErrorHandler);
app.listen(process.env.PORT, () => {
console.log(`Listening on Port: ${process.env.PORT}`);
logger.info(`Listening on port ${process.env.PORT}`);
});
logger.info("Server started");
process.on("exit", () => {
logger.info("Server stopping...");
});
}
main()
.catch((e) => {
logger.crit(e);
throw e;
})
.finally(async () => {