Forráskód Böngészése

Add cooldown and banning spamers

Pouria Ezzati 7 éve
szülő
commit
aad791830f

+ 3 - 0
server/controllers/authController.js

@@ -46,6 +46,9 @@ const authenticate = (type, error, isStrict = true) =>
     return passport.authenticate(type, (err, user) => {
       if (err) return res.status(400);
       if (!user && isStrict) return res.status(401).json({ error });
+      if (user.banned) {
+        return res.status(400).json({ error: 'Your are banned from using this website.' });
+      }
       req.user = user;
       return next();
     })(req, res, next);

+ 20 - 2
server/controllers/validateBodyController.js

@@ -1,7 +1,9 @@
 const axios = require('axios');
 const urlRegex = require('url-regex');
 const validator = require('express-validator/check');
+const { subHours } = require('date-fns/');
 const { validationResult } = require('express-validator/check');
+const { addCooldown, banUser, getCooldowns } = require('../db/user');
 const config = require('../config');
 
 exports.validationCriterias = [
@@ -88,7 +90,22 @@ exports.validateUrl = async ({ body, user }, res, next) => {
   return next();
 };
 
-exports.malwareCheck = async ({ body }, res, next) => {
+exports.cooldownCheck = async ({ user }, res, next) => {
+  if (user) {
+    const { cooldowns } = await getCooldowns(user);
+    if (cooldowns.length > 4) {
+      await banUser(user);
+      return res.status(400).json({ error: 'Too much malware requests. You are now banned.' });
+    }
+    const hasCooldownNow = cooldowns.some(cooldown => cooldown > subHours(new Date(), 12).toJSON());
+    if (hasCooldownNow) {
+      return res.status(400).json({ error: 'Cooldown because of a malware URL. Wait 12h' });
+    }
+  }
+  return next();
+};
+
+exports.malwareCheck = async ({ body, user }, res, next) => {
   const isMalware = await axios.post(
     `https://safebrowsing.googleapis.com/v4/threatMatches:find?key=${
       config.GOOGLE_SAFE_BROWSING_KEY
@@ -107,7 +124,8 @@ exports.malwareCheck = async ({ body }, res, next) => {
     }
   );
   if (isMalware.data && isMalware.data.matches) {
-    return res.status(400).json({ error: 'Malware detected!' });
+    await addCooldown(user);
+    return res.status(400).json({ error: 'Malware detected! Cooldown for 12h.' });
   }
   return next();
 };

+ 61 - 0
server/db/user.js

@@ -163,3 +163,64 @@ exports.resetPassword = ({ resetPasswordToken }) =>
       })
       .catch(err => reject(err));
   });
+
+exports.addCooldown = ({ email }) =>
+  new Promise((resolve, reject) => {
+    const session = driver.session();
+    session
+      .writeTransaction(tx =>
+        tx.run(
+          'MATCH (u:USER { email: $email }) ' +
+            'MERGE (u)-[r:RECEIVED]->(c:COOLDOWN { date: $date }) ' +
+            'RETURN COUNT(r) as count',
+          {
+            date: new Date().toJSON(),
+            email,
+          }
+        )
+      )
+      .then(({ records }) => {
+        session.close();
+        const count = records.length && records[0].get('count').toNumber();
+        return resolve({ count });
+      })
+      .catch(err => reject(err));
+  });
+
+exports.getCooldowns = ({ email }) =>
+  new Promise((resolve, reject) => {
+    const session = driver.session();
+    session
+      .writeTransaction(tx =>
+        tx.run(
+          'MATCH (u:USER { email: $email }) MATCH (u)-[r:RECEIVED]->(c) RETURN c.date as date',
+          {
+            date: new Date().toJSON(),
+            email,
+          }
+        )
+      )
+      .then(({ records = [] }) => {
+        session.close();
+        const cooldowns = records.map(record => record.get('date'));
+        return resolve({ cooldowns });
+      })
+      .catch(err => reject(err));
+  });
+
+exports.banUser = ({ email }) =>
+  new Promise((resolve, reject) => {
+    const session = driver.session();
+    session
+      .writeTransaction(tx =>
+        tx.run('MATCH (u:USER { email: $email }) SET u.banned = true RETURN u', {
+          email,
+        })
+      )
+      .then(({ records = [] }) => {
+        session.close();
+        const user = records.length && records[0].get('u');
+        return resolve({ user });
+      })
+      .catch(err => reject(err));
+  });

+ 2 - 0
server/server.js

@@ -11,6 +11,7 @@ const {
   validationCriterias,
   preservedUrls,
   validateUrl,
+  cooldownCheck,
   malwareCheck,
 } = require('./controllers/validateBodyController');
 const auth = require('./controllers/authController');
@@ -100,6 +101,7 @@ app.prepare().then(() => {
     auth.authJwtLoose,
     catchErrors(auth.recaptcha),
     catchErrors(validateUrl),
+    catchErrors(cooldownCheck),
     catchErrors(malwareCheck),
     catchErrors(url.urlShortener)
   );