Blocking users with too many active warnings from submitting votes and submissions

This commit is contained in:
Nanobyte 2020-09-16 22:40:11 +02:00
parent 3c79c0f7a8
commit 36f654f41c
7 changed files with 125 additions and 3 deletions

View file

@ -22,5 +22,7 @@
"mode": "development",
"readOnly": false,
"webhooks": [],
"categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "music_offtopic"] // List of supported categories any other category will be rejected
"categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "music_offtopic"], // List of supported categories any other category will be rejected
"maxNumberOfActiveWarnings": 3, // Users with this number of warnings will be blocked until warnings expire
"hoursAfterWarningExpire": 24
}

View file

@ -20,7 +20,9 @@ addDefaults(config, {
"privateDBSchema": "./databases/_private.db.sql",
"readOnly": false,
"webhooks": [],
"categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "music_offtopic"]
"categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "music_offtopic"],
"maxNumberOfActiveWarnings": 3,
"hoursAfterWarningExpires": 24
})
module.exports = config;

View file

@ -269,6 +269,16 @@ module.exports = async function postSkipSegments(req, res) {
//hash the ip 5000 times so no one can get it from the database
let hashedIP = getHash(getIP(req) + config.globalSalt);
const MILLISECONDS_IN_HOUR = 3600000;
const now = Date.now();
let warningsCount = db.prepare('get', "SELECT count(1) as count FROM warnings WHERE userID = ? AND issueTime > ?",
[userID, Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR))]
).count;
if (warningsCount >= config.maxNumberOfActiveWarnings) {
return res.status(403).send('Submission blocked. Too many active warnings!');
}
let noSegmentList = db.prepare('all', 'SELECT category from noSegments where videoID = ?', [videoID]).map((list) => { return list.category });

View file

@ -235,6 +235,16 @@ async function voteOnSponsorTime(req, res) {
return;
}
}
const MILLISECONDS_IN_HOUR = 3600000;
const now = Date.now();
let warningsCount = db.prepare('get', "SELECT count(1) as count FROM warnings WHERE userID = ? AND issueTime > ?",
[nonAnonUserID, Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR))]
).count;
if (warningsCount >= config.maxNumberOfActiveWarnings) {
return res.status(403).send('Vote blocked. Too many active warnings!');
}
let voteTypeEnum = (type == 0 || type == 1) ? voteTypes.normal : voteTypes.incorrect;

View file

@ -49,5 +49,7 @@
]
}
],
"categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "music_offtopic"]
"categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "music_offtopic"],
"maxNumberOfActiveWarnings": 3,
"hoursAfterWarningExpires": 24
}

View file

@ -1,5 +1,7 @@
var assert = require('assert');
var request = require('request');
var config = require('../../src/config.js');
var getHash = require('../../src/utils/getHash.js');
var utils = require('../utils.js');
@ -7,6 +9,24 @@ var databases = require('../../src/databases/databases.js');
var db = databases.db;
describe('postSkipSegments', () => {
before(() => {
const now = Date.now();
const warnVip01Hash = getHash("warn-vip01");
const warnUser01Hash = getHash("warn-user01");
const warnUser02Hash = getHash("warn-user02");
const MILLISECONDS_IN_HOUR = 3600000;
const warningExpireTime = MILLISECONDS_IN_HOUR * config.hoursAfterWarningExpires;
const startOfWarningQuery = 'INSERT INTO warnings (userID, issueTime, issuerUserID) VALUES';
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + now + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now-1000) + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now-2000) + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now-3601000) + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + now + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + now + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + (now-(warningExpireTime + 1000)) + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + (now-(warningExpireTime + 2000)) + "', '" + warnVip01Hash + "')");
});
it('Should be able to submit a single time (Params method)', (done) => {
request.post(utils.getbaseURL()
+ "/api/postVideoSponsorTimes?videoID=dQw4w9WgXcR&startTime=2&endTime=10&userID=test&category=sponsor", null,
@ -130,6 +150,50 @@ describe('postSkipSegments', () => {
});
});
it('Should be rejected if user has to many active warnings', (done) => {
request.post(utils.getbaseURL()
+ "/api/postVideoSponsorTimes", {
json: {
userID: "warn-user01",
videoID: "dQw4w9WgXcF",
segments: [{
segment: [0, 10],
category: "sponsor"
}]
}
},
(err, res, body) => {
if (err) done(err);
else if (res.statusCode === 403) {
done(); // success
} else {
done("Status code was " + res.statusCode);
}
});
});
it('Should be accepted if user has some active warnings', (done) => {
request.post(utils.getbaseURL()
+ "/api/postVideoSponsorTimes", {
json: {
userID: "warn-user02",
videoID: "dQw4w9WgXcF",
segments: [{
segment: [50, 60],
category: "sponsor"
}]
}
},
(err, res, body) => {
if (err) done(err);
else if (res.statusCode === 200) {
done(); // success
} else {
done("Status code was " + res.statusCode + " " + body);
}
});
});
it('Should be allowed if youtube thinks duration is 0', (done) => {
request.get(utils.getbaseURL()
+ "/api/postVideoSponsorTimes?videoID=noDuration&startTime=30&endTime=10000&userID=testing", null,

View file

@ -1,11 +1,19 @@
const request = require('request');
const config = require('../../src/config.js');
const { db, privateDB } = require('../../src/databases/databases.js');
const utils = require('../utils.js');
const getHash = require('../../src/utils/getHash.js');
describe('voteOnSponsorTime', () => {
before(() => {
const now = Date.now();
const warnVip01Hash = getHash("warn-vip01");
const warnUser01Hash = getHash("warn-voteuser01");
const warnUser02Hash = getHash("warn-voteuser02");
const MILLISECONDS_IN_HOUR = 3600000;
const warningExpireTime = MILLISECONDS_IN_HOUR * config.hoursAfterWarningExpires;
let startOfQuery = "INSERT INTO sponsorTimes (videoID, startTime, endTime, votes, UUID, userID, timeSubmitted, views, category, shadowHidden, hashedVideoID) VALUES";
const startOfWarningQuery = 'INSERT INTO warnings (userID, issueTime, issuerUserID) VALUES';
db.exec(startOfQuery + "('vote-testtesttest', 1, 11, 2, 'vote-uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest', 1) + "')");
db.exec(startOfQuery + "('vote-testtesttest2', 1, 11, 2, 'vote-uuid-1', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest2', 1) + "')");
@ -25,6 +33,17 @@ describe('voteOnSponsorTime', () => {
db.exec(startOfQuery + "('not-own-submission-video', 1, 11, 500, 'not-own-submission-uuid', '"+ getHash('somebody-else-id') +"', 0, 50, 'sponsor', 0, '" + getHash('not-own-submission-video', 1) + "')");
db.exec(startOfQuery + "('incorrect-category', 1, 11, 500, 'incorrect-category', '"+ getHash('somebody-else-id') +"', 0, 50, 'sponsor', 0, '" + getHash('incorrect-category', 1) + "')");
db.exec(startOfQuery + "('incorrect-category-change', 1, 11, 500, 'incorrect-category-change', '"+ getHash('somebody-else-id') +"', 0, 50, 'sponsor', 0, '" + getHash('incorrect-category-change', 1) + "')");
db.exec(startOfQuery + "('vote-testtesttest', 1, 11, 2, 'warnvote-uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest', 1) + "')");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + now + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now-1000) + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now-2000) + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now-3601000) + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + now + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + now + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + (now-(warningExpireTime + 1000)) + "', '" + warnVip01Hash + "')");
db.exec(startOfWarningQuery + "('" + warnUser02Hash + "', '" + (now-(warningExpireTime + 2000)) + "', '" + warnVip01Hash + "')");
db.exec("INSERT INTO vipUsers (userID) VALUES ('" + getHash("VIPUser") + "')");
privateDB.exec("INSERT INTO shadowBannedUsers (userID) VALUES ('" + getHash("randomID4") + "')");
@ -332,4 +351,17 @@ describe('voteOnSponsorTime', () => {
});
});
it('Should not be able to upvote a segment (Too many warning)', (done) => {
request.get(utils.getbaseURL()
+ "/api/voteOnSponsorTime?userID=warn-voteuser01&UUID=warnvote-uuid-0&type=1", null,
(err, res, body) => {
if (err) done(err);
else if (res.statusCode === 403) {
done(); // success
} else {
done("Status code was " + res.statusCode);
}
});
});
});