177 lines
5.8 KiB
TypeScript
177 lines
5.8 KiB
TypeScript
import config, { WebConfig } from "./config";
|
|
import express from "express";
|
|
import { Express } from "express";
|
|
|
|
import Logging from "@hibas123/nodelogging";
|
|
import { Format } from "@hibas123/logging";
|
|
|
|
import bodyparser from "body-parser";
|
|
import cookieparser from "cookie-parser";
|
|
import session from "express-session";
|
|
import MongoStore from "connect-mongo";
|
|
|
|
import i18n from "i18n";
|
|
import compression from "compression";
|
|
import ApiRouter from "./api";
|
|
import ViewRouter from "./views";
|
|
import RequestError, { HttpStatusCode } from "./helper/request_error";
|
|
import DB from "./database";
|
|
import promiseMiddleware from "./helper/promiseMiddleware";
|
|
import User from "./models/user";
|
|
import LoginToken, { CheckToken } from "./models/login_token";
|
|
|
|
export default class Web {
|
|
server: Express;
|
|
private port: number;
|
|
|
|
constructor(config: WebConfig) {
|
|
this.server = express();
|
|
this.server.set("trust proxy", 1);
|
|
this.port = Number(config.port);
|
|
this.registerMiddleware();
|
|
this.registerUserSession();
|
|
this.registerEndpoints();
|
|
this.registerErrorHandler();
|
|
}
|
|
|
|
listen() {
|
|
this.server.listen(this.port, () => {
|
|
Logging.log(`Server listening on port ${this.port}`);
|
|
});
|
|
}
|
|
|
|
private registerMiddleware() {
|
|
this.server.use(session({
|
|
secret: config.core.secret,
|
|
resave: false,
|
|
saveUninitialized: false,
|
|
store: MongoStore.create({
|
|
client: DB.getClient(),
|
|
dbName: DB.db.databaseName,
|
|
collectionName: "sessions",
|
|
autoRemove: "native",
|
|
touchAfter: 60 * 60 * 24,
|
|
}),
|
|
cookie: {
|
|
maxAge: 1000 * 60 * 60 * 24 * 30 * 6,
|
|
secure: !config.core.dev,
|
|
sameSite: "strict",
|
|
}
|
|
}))
|
|
this.server.use(cookieparser());
|
|
this.server.use(
|
|
bodyparser.json(),
|
|
bodyparser.urlencoded({ extended: true })
|
|
);
|
|
this.server.use(i18n.init);
|
|
|
|
//Logging Middleware
|
|
this.server.use((req, res, next) => {
|
|
let start = process.hrtime();
|
|
let finished = false;
|
|
let to = false;
|
|
let listener = () => {
|
|
if (finished) return;
|
|
finished = true;
|
|
let td = process.hrtime(start);
|
|
let time = !to ? (td[0] * 1e3 + td[1] / 1e6).toFixed(2) : "--.--";
|
|
let resFormat: (arg: any) => any = (arg) => arg;
|
|
if (res.statusCode >= 200 && res.statusCode < 300)
|
|
resFormat = Format.green;
|
|
//Green
|
|
else if (res.statusCode === 304 || res.statusCode === 302)
|
|
resFormat = Format.yellow; //"\x1b[33m";
|
|
else if (res.statusCode >= 400 && res.statusCode < 500)
|
|
resFormat = Format.red; // "\x1b[36m";
|
|
//Cyan
|
|
else if (res.statusCode >= 500 && res.statusCode < 600)
|
|
resFormat = Format.cyan //"\x1b[31m"; //Red
|
|
|
|
let m = req.method;
|
|
while (m.length < 4) m += " ";
|
|
Logging.getChild("HTTP").log(
|
|
`${m} ${req.originalUrl} ${(req as any).language || ""
|
|
}`, resFormat(res.statusCode), `- ${time}ms`
|
|
);
|
|
res.removeListener("finish", listener);
|
|
};
|
|
res.on("finish", listener);
|
|
setTimeout(() => {
|
|
to = true;
|
|
listener();
|
|
}, 2000);
|
|
next();
|
|
});
|
|
|
|
this.server.use(
|
|
compression({
|
|
filter: (req, res) => {
|
|
if (req.headers["x-no-compression"]) {
|
|
return false;
|
|
}
|
|
return compression.filter(req, res);
|
|
},
|
|
})
|
|
);
|
|
}
|
|
|
|
private registerEndpoints() {
|
|
this.server.use("/api", ApiRouter);
|
|
this.server.use("/", ViewRouter);
|
|
}
|
|
|
|
private registerErrorHandler() {
|
|
this.server.use((error, req: express.Request, res, next) => {
|
|
if (!(error instanceof RequestError)) {
|
|
error = new RequestError(
|
|
error.message,
|
|
error.status || HttpStatusCode.INTERNAL_SERVER_ERROR,
|
|
error.nolog || false
|
|
);
|
|
}
|
|
|
|
if (error.status === 500 && !(<any>error).nolog) {
|
|
Logging.error(error);
|
|
} else {
|
|
Logging.log("Responded with Error", error.status, error.message);
|
|
}
|
|
|
|
if (req.accepts(["json"])) {
|
|
res.json_status = error.status || 500;
|
|
res.json({
|
|
error: error.message,
|
|
status: error.status || 500,
|
|
additional: error.additional,
|
|
});
|
|
} else res.status(error.status || 500).send(error.message);
|
|
});
|
|
}
|
|
|
|
private registerUserSession() {
|
|
this.server.use(promiseMiddleware(async (req, res, next) => {
|
|
// if (!req.session.user_id) {
|
|
// if (req.cookies && req.cookies.login) {
|
|
// let token = await LoginToken.findOne({ token: req.cookies.login, valid: true });
|
|
// if (await CheckToken(token, true)) {
|
|
// req.session.user_id = token.user.toString();
|
|
// }
|
|
// }
|
|
|
|
// if (req.cookies && req.cookies.special) {
|
|
// let token = await LoginToken.findOne({ token: req.cookies.special, valid: true });
|
|
// if (await CheckToken(token, true)) {
|
|
// req.session.user_id = token.user.toString();
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
if (req.session.user_id) {
|
|
req.user = await User.findById(req.session.user_id);
|
|
req.isAdmin = req.user.admin;
|
|
}
|
|
|
|
return next();
|
|
}));
|
|
}
|
|
}
|