helpers.handler.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. const { validationResult } = require("express-validator");
  2. const signale = require("signale");
  3. const { logger } = require("../config/winston");
  4. const { CustomError, sanitize } = require("../utils");
  5. const query = require("../queries")
  6. const env = require("../env");
  7. // export const ip: Handler = (req, res, next) => {
  8. // req.realIP =
  9. // (req.headers["x-real-ip"] as string) || req.connection.remoteAddress || "";
  10. // return next();
  11. // };
  12. /**
  13. * @type {import("express").Handler}
  14. */
  15. function isHTML(req, res, next) {
  16. const accepts = req.accepts(["json", "html"]);
  17. req.isHTML = accepts === "html";
  18. next();
  19. }
  20. function addNoLayoutLocals(req, res, next) {
  21. /**
  22. * @type {import("express").Handler}
  23. */
  24. res.locals.layout = null;
  25. next();
  26. }
  27. function viewTemplate(template) {
  28. return function (req, res, next) {
  29. req.viewTemplate = template;
  30. next();
  31. }
  32. }
  33. /**
  34. * @type {import("express").Handler}
  35. */
  36. function addConfigLocals(req, res, next) {
  37. res.locals.default_domain = env.DEFAULT_DOMAIN;
  38. next();
  39. }
  40. /**
  41. * @type {import("express").Handler}
  42. */
  43. async function addUserLocals(req, res, next) {
  44. const user = req.user;
  45. res.locals.user = user;
  46. res.locals.domains = user && (await query.domain.get({ user_id: user.id })).map(sanitize.domain);
  47. next();
  48. }
  49. /**
  50. * @type {import("express").ErrorRequestHandler}
  51. */
  52. function error(error, req, res, _next) {
  53. if (env.isDev) {
  54. signale.fatal(error);
  55. }
  56. const message = error instanceof CustomError ? error.message : "An error occurred.";
  57. const statusCode = error.statusCode ?? 500;
  58. if (req.isHTML && req.viewTemplate) {
  59. res.render(req.viewTemplate, { error: message });
  60. return;
  61. }
  62. return res.status(statusCode).json({ error: message });
  63. };
  64. /**
  65. * @type {import("express").Handler}
  66. */
  67. function verify(req, res, next) {
  68. const result = validationResult(req);
  69. if (result.isEmpty()) return next();
  70. const errors = result.array();
  71. const error = errors[0].msg;
  72. res.locals.errors = {};
  73. errors.forEach(e => {
  74. if (res.locals.errors[e.param]) return;
  75. res.locals.errors[e.param] = e.msg;
  76. });
  77. throw new CustomError(error, 400);
  78. }
  79. function parseQuery(req, res, next) {
  80. const { admin } = req.user || {};
  81. if (
  82. typeof req.query.limit !== "undefined" &&
  83. typeof req.query.limit !== "string"
  84. ) {
  85. return res.status(400).json({ error: "limit query is not valid." });
  86. }
  87. if (
  88. typeof req.query.skip !== "undefined" &&
  89. typeof req.query.skip !== "string"
  90. ) {
  91. return res.status(400).json({ error: "skip query is not valid." });
  92. }
  93. if (
  94. typeof req.query.search !== "undefined" &&
  95. typeof req.query.search !== "string"
  96. ) {
  97. return res.status(400).json({ error: "search query is not valid." });
  98. }
  99. const limit = parseInt(req.query.limit) || 10;
  100. const skip = parseInt(req.query.skip) || 0;
  101. req.context = {
  102. limit: limit > 50 ? 50 : limit,
  103. skip,
  104. all: admin ? req.query.all === "true" : false
  105. };
  106. next();
  107. };
  108. module.exports = {
  109. addConfigLocals,
  110. addNoLayoutLocals,
  111. addUserLocals,
  112. error,
  113. isHTML,
  114. parseQuery,
  115. verify,
  116. viewTemplate,
  117. }