From ef21ceb332c7aeb59354ddd08624ac167680e6e4 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Thu, 18 Feb 2021 19:48:36 -0500 Subject: [PATCH] Add segment locking --- databases/_upgrade_sponsorTimes_6.sql | 27 ++++++++++++++++++ src/routes/voteOnSponsorTime.ts | 9 ++++-- test/cases/voteOnSponsorTime.ts | 41 ++++++++++++++++----------- 3 files changed, 58 insertions(+), 19 deletions(-) create mode 100644 databases/_upgrade_sponsorTimes_6.sql diff --git a/databases/_upgrade_sponsorTimes_6.sql b/databases/_upgrade_sponsorTimes_6.sql new file mode 100644 index 0000000..3901602 --- /dev/null +++ b/databases/_upgrade_sponsorTimes_6.sql @@ -0,0 +1,27 @@ +BEGIN TRANSACTION; + +/* Add new voting field */ +CREATE TABLE "sqlb_temp_table_6" ( + "videoID" TEXT NOT NULL, + "startTime" REAL NOT NULL, + "endTime" REAL NOT NULL, + "votes" INTEGER NOT NULL, + "locked" INTEGER NOT NULL default '0', + "incorrectVotes" INTEGER NOT NULL default '1', + "UUID" TEXT NOT NULL UNIQUE, + "userID" TEXT NOT NULL, + "timeSubmitted" INTEGER NOT NULL, + "views" INTEGER NOT NULL, + "category" TEXT NOT NULL DEFAULT "sponsor", + "shadowHidden" INTEGER NOT NULL, + "hashedVideoID" TEXT NOT NULL default "" +); + +INSERT INTO sqlb_temp_table_6 SELECT videoID,startTime,endTime,votes,"0",incorrectVotes,UUID,userID,timeSubmitted,views,category,shadowHidden,hashedVideoID FROM sponsorTimes; + +DROP TABLE sponsorTimes; +ALTER TABLE sqlb_temp_table_6 RENAME TO "sponsorTimes"; + +UPDATE config SET value = 6 WHERE key = "version"; + +COMMIT; \ No newline at end of file diff --git a/src/routes/voteOnSponsorTime.ts b/src/routes/voteOnSponsorTime.ts index d32ce68..e343ed3 100644 --- a/src/routes/voteOnSponsorTime.ts +++ b/src/routes/voteOnSponsorTime.ts @@ -245,11 +245,12 @@ async function voteOnSponsorTime(req: Request, res: Response) { // If not upvote if (!isVIP && type !== 1) { - const isVideoLocked = !!db.prepare('get', 'SELECT noSegments.category from noSegments left join sponsorTimes' + + const isSegmentLocked = () => !!db.prepare('get', "SELECT locked FROM sponsorTimes WHERE UUID = ?", [UUID])?.locked; + const isVideoLocked = () => !!db.prepare('get', 'SELECT noSegments.category from noSegments left join sponsorTimes' + ' on (noSegments.videoID = sponsorTimes.videoID and noSegments.category = sponsorTimes.category)' + ' where UUID = ?', [UUID]); - if (isVideoLocked) { + if (isSegmentLocked() || isVideoLocked()) { res.status(403).send("Vote rejected: A moderator has decided that this segment is correct"); return; } @@ -369,6 +370,10 @@ async function voteOnSponsorTime(req: Request, res: Response) { //update the vote count on this sponsorTime //oldIncrementAmount will be zero is row is null db.prepare('run', "UPDATE sponsorTimes SET " + columnName + " = " + columnName + " + ? WHERE UUID = ?", [incrementAmount - oldIncrementAmount, UUID]); + if (isVIP && incrementAmount > 0 && voteTypeEnum === voteTypes.normal) { + // Lock this submission + db.prepare('run', "UPDATE sponsorTimes SET locked = 1 WHERE UUID = ?", [UUID]); + } //for each positive vote, see if a hidden submission can be shown again if (incrementAmount > 0 && voteTypeEnum === voteTypes.normal) { diff --git a/test/cases/voteOnSponsorTime.ts b/test/cases/voteOnSponsorTime.ts index 65e1d4b..8ac4574 100644 --- a/test/cases/voteOnSponsorTime.ts +++ b/test/cases/voteOnSponsorTime.ts @@ -44,6 +44,7 @@ describe('voteOnSponsorTime', () => { db.exec(startOfQuery + "('vote-testtesttest', 1, 11, 2, 'warnvote-uuid-0', 'testman', 0, 50, 'sponsor', 0, '" + getHash('vote-testtesttest', 1) + "')"); db.exec(startOfQuery + "('no-sponsor-segments-video', 1, 11, 2, 'no-sponsor-segments-uuid-0', 'no-sponsor-segments', 0, 50, 'sponsor', 0, '" + getHash('no-sponsor-segments-video', 1) + "')"); db.exec(startOfQuery + "('no-sponsor-segments-video', 1, 11, 2, 'no-sponsor-segments-uuid-1', 'no-sponsor-segments', 0, 50, 'intro', 0, '" + getHash('no-sponsor-segments-video', 1) + "')"); + db.exec(startOfQuery + "('segment-locking-video', 1, 11, 2, 'segment-locking-uuid-1', 'segment-locking-user', 0, 50, 'intro', 0, '" + getHash('segment-locking-video', 1) + "')"); db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + now + "', '" + warnVip01Hash + "', 1)"); db.exec(startOfWarningQuery + "('" + warnUser01Hash + "', '" + (now - 1000) + "', '" + warnVip01Hash + "', 1)"); @@ -407,9 +408,9 @@ describe('voteOnSponsorTime', () => { .catch(err => done(err)); }); - it('Non-VIP should not be able to vote on a segment with no-segments category', (done: Done) => { + it('Non-VIP should not be able to downvote on a segment with no-segments category', (done: Done) => { fetch(getbaseURL() - + "/api/voteOnSponsorTime?userID=no-segments-voter&UUID=no-sponsor-segments-uuid-0&type=1") + + "/api/voteOnSponsorTime?userID=no-segments-voter&UUID=no-sponsor-segments-uuid-0&type=0") .then(res => { if (res.status === 403) { done(); @@ -420,6 +421,19 @@ describe('voteOnSponsorTime', () => { .catch(err => done(err)); }); + it('Non-VIP should be able to upvote on a segment with no-segments category', (done: Done) => { + fetch(getbaseURL() + + "/api/voteOnSponsorTime?userID=no-segments-voter&UUID=no-sponsor-segments-uuid-0&type=1") + .then(res => { + if (res.status === 200) { + done(); + } else { + done("Status code was " + res.status + " instead of 200"); + } + }) + .catch(err => done(err)); + }); + it('Non-VIP should not be able to category vote on a segment with no-segments category', (done: Done) => { fetch(getbaseURL() + "/api/voteOnSponsorTime?userID=no-segments-voter&UUID=no-sponsor-segments-uuid-0&category=outro") @@ -433,12 +447,17 @@ describe('voteOnSponsorTime', () => { .catch(err => done(err)); }); - it('VIP should able to vote on a segment with no-segments category', (done: Done) => { + it('VIP upvote should lock segment', (done: Done) => { fetch(getbaseURL() - + "/api/voteOnSponsorTime?userID=VIPUser&UUID=no-sponsor-segments-uuid-0&type=1") + + "/api/voteOnSponsorTime?userID=VIPUser&UUID=segment-locking-uuid-1&type=1") .then(res => { if (res.status === 200) { - done(); + let row = db.prepare('get', "SELECT locked FROM sponsorTimes WHERE UUID = ?", ["segment-locking-uuid-1"]); + if (row?.locked) { + done(); + } else { + done("Segment not locked"); + } } else { done("Status code was " + res.status + " instead of 200"); } @@ -446,16 +465,4 @@ describe('voteOnSponsorTime', () => { .catch(err => done(err)); }); - it('Non-VIP should be able to vote on a segment on a no-segments video with a category that doesn\'t have no-segments', (done: Done) => { - fetch(getbaseURL() - + "/api/voteOnSponsorTime?userID=no-segments-voter&UUID=no-sponsor-segments-uuid-1&type=1") - .then(res => { - if (res.status === 200) { - done(); - } else { - done("Status code was " + res.status + " instead of 200"); - } - }) - .catch(err => done(err)); - }); });