|
|
@@ -1,15 +1,20 @@
|
|
|
-const { body } = require('express-validator/check');
|
|
|
+const axios = require('axios');
|
|
|
+const urlRegex = require('url-regex');
|
|
|
+const validator = require('express-validator/check');
|
|
|
const { validationResult } = require('express-validator/check');
|
|
|
+const config = require('../config');
|
|
|
|
|
|
exports.validationCriterias = [
|
|
|
- body('email')
|
|
|
+ validator
|
|
|
+ .body('email')
|
|
|
.exists()
|
|
|
.withMessage('Email must be provided.')
|
|
|
.isEmail()
|
|
|
.withMessage('Email is not valid.')
|
|
|
.trim()
|
|
|
.normalizeEmail(),
|
|
|
- body('password', 'Password must be at least 8 chars long.')
|
|
|
+ validator
|
|
|
+ .body('password', 'Password must be at least 8 chars long.')
|
|
|
.exists()
|
|
|
.withMessage('Password must be provided.')
|
|
|
.isLength({ min: 8 }),
|
|
|
@@ -25,3 +30,84 @@ exports.validateBody = (req, res, next) => {
|
|
|
}
|
|
|
return next();
|
|
|
};
|
|
|
+
|
|
|
+const preservedUrls = [
|
|
|
+ 'login',
|
|
|
+ 'logout',
|
|
|
+ 'signup',
|
|
|
+ 'reset-password',
|
|
|
+ 'resetpassword',
|
|
|
+ 'url-password',
|
|
|
+ 'settings',
|
|
|
+ 'stats',
|
|
|
+ 'verify',
|
|
|
+ 'api',
|
|
|
+ '404',
|
|
|
+ 'static',
|
|
|
+ 'images',
|
|
|
+];
|
|
|
+
|
|
|
+exports.preservedUrls = preservedUrls;
|
|
|
+
|
|
|
+exports.validateUrl = async ({ body, user }, res, next) => {
|
|
|
+ // Validate URL existence
|
|
|
+ if (!body.target) return res.status(400).json({ error: 'No target has been provided.' });
|
|
|
+
|
|
|
+ // validate URL length
|
|
|
+ if (body.target.length > 1024) {
|
|
|
+ return res.status(400).json({ error: 'Maximum URL length is 1024.' });
|
|
|
+ }
|
|
|
+
|
|
|
+ // Validate URL
|
|
|
+ const isValidUrl = urlRegex({ exact: true, strict: false }).test(body.target);
|
|
|
+ if (!isValidUrl) return res.status(400).json({ error: 'URL is not valid.' });
|
|
|
+
|
|
|
+ // Validate password length
|
|
|
+ if (body.password && body.password.length > 64) {
|
|
|
+ return res.status(400).json({ error: 'Maximum password length is 64.' });
|
|
|
+ }
|
|
|
+
|
|
|
+ // Custom URL validations
|
|
|
+ if (user && body.customurl) {
|
|
|
+ // Validate custom URL
|
|
|
+ if (!/^[a-zA-Z1-9-_]+$/g.test(body.customurl.trim())) {
|
|
|
+ return res.status(400).json({ error: 'Custom URL is not valid.' });
|
|
|
+ }
|
|
|
+
|
|
|
+ // Prevent from using preserved URLs
|
|
|
+ if (preservedUrls.some(url => url === body.customurl)) {
|
|
|
+ return res.status(400).json({ error: "You can't use this custom URL name." });
|
|
|
+ }
|
|
|
+
|
|
|
+ // Validate custom URL length
|
|
|
+ if (body.customurl.length > 64) {
|
|
|
+ return res.status(400).json({ error: 'Maximum custom URL length is 64.' });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return next();
|
|
|
+};
|
|
|
+
|
|
|
+exports.malwareCheck = async ({ body }, res, next) => {
|
|
|
+ const isMalware = await axios.post(
|
|
|
+ `https://safebrowsing.googleapis.com/v4/threatMatches:find?key=${
|
|
|
+ config.GOOGLE_SAFE_BROWSING_KEY
|
|
|
+ }`,
|
|
|
+ {
|
|
|
+ client: {
|
|
|
+ clientId: config.DEFAULT_DOMAIN.toLowerCase().replace('.', ''),
|
|
|
+ clientVersion: '1.0.0',
|
|
|
+ },
|
|
|
+ threatInfo: {
|
|
|
+ threatTypes: ['MALWARE', 'SOCIAL_ENGINEERING'],
|
|
|
+ platformTypes: ['WINDOWS'],
|
|
|
+ threatEntryTypes: ['URL'],
|
|
|
+ threatEntries: [{ url: body.target }],
|
|
|
+ },
|
|
|
+ }
|
|
|
+ );
|
|
|
+ if (isMalware.data && isMalware.data.matches) {
|
|
|
+ return res.status(400).json({ error: 'Malware detected!' });
|
|
|
+ }
|
|
|
+ return next();
|
|
|
+};
|