validateBodyController.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. const axios = require('axios');
  2. const urlRegex = require('url-regex');
  3. const validator = require('express-validator/check');
  4. const { validationResult } = require('express-validator/check');
  5. const config = require('../config');
  6. exports.validationCriterias = [
  7. validator
  8. .body('email')
  9. .exists()
  10. .withMessage('Email must be provided.')
  11. .isEmail()
  12. .withMessage('Email is not valid.')
  13. .trim()
  14. .normalizeEmail(),
  15. validator
  16. .body('password', 'Password must be at least 8 chars long.')
  17. .exists()
  18. .withMessage('Password must be provided.')
  19. .isLength({ min: 8 }),
  20. ];
  21. exports.validateBody = (req, res, next) => {
  22. const errors = validationResult(req);
  23. if (!errors.isEmpty()) {
  24. const errorsObj = errors.mapped();
  25. const emailError = errorsObj.email && errorsObj.email.msg;
  26. const passwordError = errorsObj.password && errorsObj.password.msg;
  27. return res.status(400).json({ error: emailError || passwordError });
  28. }
  29. return next();
  30. };
  31. const preservedUrls = [
  32. 'login',
  33. 'logout',
  34. 'signup',
  35. 'reset-password',
  36. 'resetpassword',
  37. 'url-password',
  38. 'settings',
  39. 'stats',
  40. 'verify',
  41. 'api',
  42. '404',
  43. 'static',
  44. 'images',
  45. ];
  46. exports.preservedUrls = preservedUrls;
  47. exports.validateUrl = async ({ body, user }, res, next) => {
  48. // Validate URL existence
  49. if (!body.target) return res.status(400).json({ error: 'No target has been provided.' });
  50. // validate URL length
  51. if (body.target.length > 1024) {
  52. return res.status(400).json({ error: 'Maximum URL length is 1024.' });
  53. }
  54. // Validate URL
  55. const isValidUrl = urlRegex({ exact: true, strict: false }).test(body.target);
  56. if (!isValidUrl) return res.status(400).json({ error: 'URL is not valid.' });
  57. // Validate password length
  58. if (body.password && body.password.length > 64) {
  59. return res.status(400).json({ error: 'Maximum password length is 64.' });
  60. }
  61. // Custom URL validations
  62. if (user && body.customurl) {
  63. // Validate custom URL
  64. if (!/^[a-zA-Z1-9-_]+$/g.test(body.customurl.trim())) {
  65. return res.status(400).json({ error: 'Custom URL is not valid.' });
  66. }
  67. // Prevent from using preserved URLs
  68. if (preservedUrls.some(url => url === body.customurl)) {
  69. return res.status(400).json({ error: "You can't use this custom URL name." });
  70. }
  71. // Validate custom URL length
  72. if (body.customurl.length > 64) {
  73. return res.status(400).json({ error: 'Maximum custom URL length is 64.' });
  74. }
  75. }
  76. return next();
  77. };
  78. exports.malwareCheck = async ({ body }, res, next) => {
  79. const isMalware = await axios.post(
  80. `https://safebrowsing.googleapis.com/v4/threatMatches:find?key=${
  81. config.GOOGLE_SAFE_BROWSING_KEY
  82. }`,
  83. {
  84. client: {
  85. clientId: config.DEFAULT_DOMAIN.toLowerCase().replace('.', ''),
  86. clientVersion: '1.0.0',
  87. },
  88. threatInfo: {
  89. threatTypes: ['MALWARE', 'SOCIAL_ENGINEERING'],
  90. platformTypes: ['WINDOWS'],
  91. threatEntryTypes: ['URL'],
  92. threatEntries: [{ url: body.target }],
  93. },
  94. }
  95. );
  96. if (isMalware.data && isMalware.data.matches) {
  97. return res.status(400).json({ error: 'Malware detected!' });
  98. }
  99. return next();
  100. };