From 39ad5fb62a4de5f0283606baf1ab63755e4908ff Mon Sep 17 00:00:00 2001 From: mini-bomba <55105495+mini-bomba@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:13:47 +0200 Subject: [PATCH 1/5] voteOnSponsorTime: move warning check before call to categoryVote --- src/routes/voteOnSponsorTime.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/routes/voteOnSponsorTime.ts b/src/routes/voteOnSponsorTime.ts index 941189f..021d60f 100644 --- a/src/routes/voteOnSponsorTime.ts +++ b/src/routes/voteOnSponsorTime.ts @@ -367,6 +367,19 @@ export async function vote(ip: IPAddress, UUID: SegmentUUID, paramUserID: UserID return { status: 400 }; } + const MILLISECONDS_IN_HOUR = 3600000; + const now = Date.now(); + const warnings = (await db.prepare("all", `SELECT "reason" FROM warnings WHERE "userID" = ? AND "issueTime" > ? AND enabled = 1`, + [nonAnonUserID, Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR))], + )); + + if (warnings.length >= config.maxNumberOfActiveWarnings) { + const warningReason = warnings[0]?.reason; + return { status: 403, message: "Vote rejected due to a warning from a moderator. This means that we noticed you were making some common mistakes that are not malicious, and we just want to clarify the rules. " + + "Could you please send a message in Discord or Matrix so we can further help you?" + + `${(warningReason.length > 0 ? ` Warning reason: '${warningReason}'` : "")}` }; + } + // no type but has category, categoryVote if (!type && category) { return categoryVote(UUID, nonAnonUserID, isVIP, isTempVIP, isOwnSubmission, category, hashedIP, finalResponse); @@ -396,19 +409,6 @@ export async function vote(ip: IPAddress, UUID: SegmentUUID, paramUserID: UserID } } - const MILLISECONDS_IN_HOUR = 3600000; - const now = Date.now(); - const warnings = (await db.prepare("all", `SELECT "reason" FROM warnings WHERE "userID" = ? AND "issueTime" > ? AND enabled = 1`, - [nonAnonUserID, Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR))], - )); - - if (warnings.length >= config.maxNumberOfActiveWarnings) { - const warningReason = warnings[0]?.reason; - return { status: 403, message: "Vote rejected due to a warning from a moderator. This means that we noticed you were making some common mistakes that are not malicious, and we just want to clarify the rules. " + - "Could you please send a message in Discord or Matrix so we can further help you?" + - `${(warningReason.length > 0 ? ` Warning reason: '${warningReason}'` : "")}` }; - } - const voteTypeEnum = (type == 0 || type == 1 || type == 20) ? voteTypes.normal : voteTypes.incorrect; // no restrictions on checkDuration From 70c98e081991fcb25a50f888818943260d6e949f Mon Sep 17 00:00:00 2001 From: mini-bomba <55105495+mini-bomba@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:22:44 +0200 Subject: [PATCH 2/5] voteOnSponsorTime: add ban check to categoryVote --- src/routes/voteOnSponsorTime.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/voteOnSponsorTime.ts b/src/routes/voteOnSponsorTime.ts index 021d60f..ef5d925 100644 --- a/src/routes/voteOnSponsorTime.ts +++ b/src/routes/voteOnSponsorTime.ts @@ -247,7 +247,8 @@ async function categoryVote(UUID: SegmentUUID, userID: UserID, isVIP: boolean, i const timeSubmitted = Date.now(); const voteAmount = (isVIP || isTempVIP) ? 500 : 1; - const ableToVote = isVIP || isTempVIP || finalResponse.finalStatus === 200 || true; + const ableToVote = finalResponse.finalStatus === 200 + && (await db.prepare("get", `SELECT "userID" FROM "shadowBannedUsers" WHERE "userID" = ?`, [userID])) === undefined; if (ableToVote) { // Add the vote From f24a1415daf4531ec149ea795c13060e151a1899 Mon Sep 17 00:00:00 2001 From: mini-bomba <55105495+mini-bomba@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:24:22 +0200 Subject: [PATCH 3/5] voteOnSponsorTime: check for VIP/ownSubmission before doing math in categoryVote --- src/routes/voteOnSponsorTime.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/voteOnSponsorTime.ts b/src/routes/voteOnSponsorTime.ts index ef5d925..bd92ac9 100644 --- a/src/routes/voteOnSponsorTime.ts +++ b/src/routes/voteOnSponsorTime.ts @@ -291,7 +291,7 @@ async function categoryVote(UUID: SegmentUUID, userID: UserID, isVIP: boolean, i //TODO: In the future, raise this number from zero to make it harder to change categories // VIPs change it every time - if (nextCategoryCount - currentCategoryCount >= Math.max(Math.ceil(submissionInfo?.votes / 2), 2) || isVIP || isTempVIP || isOwnSubmission) { + if (isVIP || isTempVIP || isOwnSubmission || nextCategoryCount - currentCategoryCount >= Math.max(Math.ceil(submissionInfo?.votes / 2), 2)) { // Replace the category await db.prepare("run", `update "sponsorTimes" set "category" = ? where "UUID" = ?`, [category, UUID]); } From 9c0f0d8e4f4532a32ffcb53b53c0827f7db69c28 Mon Sep 17 00:00:00 2001 From: mini-bomba <55105495+mini-bomba@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:28:45 +0200 Subject: [PATCH 4/5] voteOnSponsorTime: simplify currentCategoryCount computation in categoryVote --- src/routes/voteOnSponsorTime.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/voteOnSponsorTime.ts b/src/routes/voteOnSponsorTime.ts index bd92ac9..7f308ef 100644 --- a/src/routes/voteOnSponsorTime.ts +++ b/src/routes/voteOnSponsorTime.ts @@ -279,7 +279,7 @@ async function categoryVote(UUID: SegmentUUID, userID: UserID, isVIP: boolean, i // Change this value from 1 in the future to make it harder to change categories // Done this way without ORs incase the value is zero - const currentCategoryCount = (currentCategoryInfo === undefined || currentCategoryInfo === null) ? startingVotes : currentCategoryInfo.votes; + const currentCategoryCount = currentCategoryInfo?.votes ?? startingVotes; // Add submission as vote if (!currentCategoryInfo && submissionInfo) { From 55a8b5d514a515fe2f43f69476050b36931df81d Mon Sep 17 00:00:00 2001 From: mini-bomba <55105495+mini-bomba@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:56:44 +0200 Subject: [PATCH 5/5] voteOnSponsorTime: add test cases for categoryVote as warned/banned user --- test/cases/voteOnSponsorTime.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/cases/voteOnSponsorTime.ts b/test/cases/voteOnSponsorTime.ts index e2bff51..f915fc2 100644 --- a/test/cases/voteOnSponsorTime.ts +++ b/test/cases/voteOnSponsorTime.ts @@ -59,6 +59,8 @@ describe("voteOnSponsorTime", () => { await db.prepare("run", insertSponsorTimeQuery, ["category-change-test-1", 8, 12, 0, 1, "category-change-uuid-6", categoryChangeUserHash, 0, 50, "intro", "skip", 0, 0]); await db.prepare("run", insertSponsorTimeQuery, ["category-change-test-1", 9, 14, 0, 0, "category-change-uuid-7", categoryChangeUserHash, 0, 50, "intro", "skip", 0, 0]); await db.prepare("run", insertSponsorTimeQuery, ["category-change-test-1", 7, 12, 0, 1, "category-change-uuid-8", categoryChangeUserHash, 0, 50, "intro", "skip", 0, 0]); + await db.prepare("run", insertSponsorTimeQuery, ["category-change-test-2", 7, 14, 0, 0, "category-warnvote-uuid-0", categoryChangeUserHash, 0, 50, "intro", "skip", 0, 0]); + await db.prepare("run", insertSponsorTimeQuery, ["category-change-test-2", 8, 13, 0, 0, "category-banvote-uuid-0", categoryChangeUserHash, 0, 50, "intro", "skip", 0, 0]); await db.prepare("run", insertSponsorTimeQuery, ["duration-update", 1, 10, 0, 0, "duration-update-uuid-1", "testman", 0, 0, "intro", "skip", 0, 0]); await db.prepare("run", insertSponsorTimeQuery, ["full-video", 1, 10, 0, 0, "full-video-uuid-1", "testman", 0, 0, "sponsor", "full", 0, 0]); // videoDuration change @@ -445,6 +447,32 @@ describe("voteOnSponsorTime", () => { .catch(err => done(err)); }); + it("Should not be able to vote for a category of a segment (Too many warning)", (done) => { + const UUID = "category-warnvote-uuid-0"; + const category = "preview"; + postVoteCategory("warn-voteuser01", UUID, category) + .then(res => { + assert.strictEqual(res.status, 403); + done(); + }) + .catch(err => done(err)); + }); + + it("Should be able to vote for a category as a shadowbanned user, but it shouldn't add your vote to the database", (done) => { + const UUID = "category-banvote-uuid-0"; + const category = "preview"; + postVoteCategory("randomID4", UUID, category) + .then(async res => { + assert.strictEqual(res.status, 200); + const row = await getSegmentCategory(UUID); + const categoryRows = await db.prepare("all", `SELECT votes, category FROM "categoryVotes" WHERE "UUID" = ?`, [UUID]); + assert.strictEqual(row.category, "intro"); + assert.strictEqual(categoryRows.length, 0); + done(); + }) + .catch(err => done(err)); + }); + it("Should not be able to category-vote on an invalid UUID submission", (done) => { const UUID = "invalid-uuid"; postVoteCategory("randomID3", UUID, "intro")