use shared parseParams helper

This commit is contained in:
Michael C
2023-01-28 02:40:09 -05:00
parent 894cd48182
commit a64b8f99b7
8 changed files with 180 additions and 158 deletions

View File

@@ -3,17 +3,12 @@ import { Logger } from "../utils/logger";
import { Request, Response } from "express"; import { Request, Response } from "express";
import { ActionType, Category, VideoID } from "../types/segments.model"; import { ActionType, Category, VideoID } from "../types/segments.model";
import { getService } from "../utils/getService"; import { getService } from "../utils/getService";
import { parseActionTypes } from "../utils/parseParams";
export async function getLockCategories(req: Request, res: Response): Promise<Response> { export async function getLockCategories(req: Request, res: Response): Promise<Response> {
const videoID = req.query.videoID as VideoID; const videoID = req.query.videoID as VideoID;
const service = getService(req.query.service as string); const service = getService(req.query.service as string);
const actionTypes: ActionType[] = req.query.actionTypes const actionTypes: ActionType[] = parseActionTypes(req, [ActionType.Skip, ActionType.Mute]);
? JSON.parse(req.query.actionTypes as string)
: req.query.actionType
? Array.isArray(req.query.actionType)
? req.query.actionType
: [req.query.actionType]
: [ActionType.Skip, ActionType.Mute];
if (!videoID || !Array.isArray(actionTypes)) { if (!videoID || !Array.isArray(actionTypes)) {
//invalid request //invalid request
return res.sendStatus(400); return res.sendStatus(400);

View File

@@ -3,6 +3,7 @@ import { Logger } from "../utils/logger";
import { Request, Response } from "express"; import { Request, Response } from "express";
import { hashPrefixTester } from "../utils/hashPrefixTester"; import { hashPrefixTester } from "../utils/hashPrefixTester";
import { ActionType, Category, VideoID, VideoIDHash } from "../types/segments.model"; import { ActionType, Category, VideoID, VideoIDHash } from "../types/segments.model";
import { parseActionTypes } from "../utils/parseParams";
interface LockResultByHash { interface LockResultByHash {
videoID: VideoID, videoID: VideoID,
@@ -44,25 +45,13 @@ const mergeLocks = (source: DBLock[], actionTypes: ActionType[]): LockResultByHa
export async function getLockCategoriesByHash(req: Request, res: Response): Promise<Response> { export async function getLockCategoriesByHash(req: Request, res: Response): Promise<Response> {
let hashPrefix = req.params.prefix as VideoIDHash; let hashPrefix = req.params.prefix as VideoIDHash;
let actionTypes: ActionType[] = []; const actionTypes: ActionType[] = parseActionTypes(req, [ActionType.Skip, ActionType.Mute]);
try { if (!Array.isArray(actionTypes)) {
actionTypes = req.query.actionTypes
? JSON.parse(req.query.actionTypes as string)
: req.query.actionType
? Array.isArray(req.query.actionType)
? req.query.actionType
: [req.query.actionType]
: [ActionType.Skip, ActionType.Mute];
if (!Array.isArray(actionTypes)) {
//invalid request
return res.sendStatus(400);
}
} catch (err) {
//invalid request //invalid request
return res.status(400).send("Invalid request: JSON parse error (actionTypes)"); return res.sendStatus(400);
} }
if (!hashPrefixTester(req.params.prefix)) {
if (!hashPrefixTester(req.params.prefix)) {
return res.status(400).send("Hash prefix does not match format requirements."); // Exit early on faulty prefix return res.status(400).send("Hash prefix does not match format requirements."); // Exit early on faulty prefix
} }
hashPrefix = hashPrefix.toLowerCase() as VideoIDHash; hashPrefix = hashPrefix.toLowerCase() as VideoIDHash;

View File

@@ -2,9 +2,8 @@ import { db } from "../databases/databases";
import { Logger } from "../utils/logger"; import { Logger } from "../utils/logger";
import { Request, Response } from "express"; import { Request, Response } from "express";
import { Category, VideoID, ActionType } from "../types/segments.model"; import { Category, VideoID, ActionType } from "../types/segments.model";
import { config } from "../config"; import { filterInvalidCategoryActionType, parseActionTypes, parseCategories } from "../utils/parseParams";
const categorySupportList = config.categorySupport;
interface lockArray { interface lockArray {
category: Category; category: Category;
locked: number, locked: number,
@@ -13,62 +12,19 @@ interface lockArray {
userName: string, userName: string,
} }
const filterActionType = (actionTypes: ActionType[]) => {
const filterCategories = new Set();
for (const [key, value] of Object.entries(categorySupportList)) {
for (const type of actionTypes) {
if (value.includes(type)) {
filterCategories.add(key as Category);
}
}
}
return [...filterCategories];
};
export async function getLockReason(req: Request, res: Response): Promise<Response> { export async function getLockReason(req: Request, res: Response): Promise<Response> {
const videoID = req.query.videoID as VideoID; const videoID = req.query.videoID as VideoID;
if (!videoID) { const actionTypes = parseActionTypes(req, [ActionType.Skip, ActionType.Mute]);
// invalid request const categories = parseCategories(req, []);
return res.status(400).send("No videoID provided");
}
let categories: Category[] = [];
let actionTypes: ActionType[] = [];
try {
actionTypes = req.query.actionTypes
? JSON.parse(req.query.actionTypes as string)
: req.query.actionType
? Array.isArray(req.query.actionType)
? req.query.actionType
: [req.query.actionType]
: [ActionType.Skip, ActionType.Mute];
if (!Array.isArray(actionTypes)) {
//invalid request
return res.status(400).send("actionTypes parameter does not match format requirements");
}
} catch (error) {
return res.status(400).send("Bad parameter: actionTypes (invalid JSON)");
}
const possibleCategories = filterActionType(actionTypes);
try { // invalid requests
categories = req.query.categories const errors = [];
? JSON.parse(req.query.categories as string) if (!videoID) errors.push("No videoID provided");
: req.query.category if (!Array.isArray(actionTypes)) errors.push("actionTypes parameter does not match format requirements");
? Array.isArray(req.query.category) if (!Array.isArray(categories)) errors.push("Categories parameter does not match format requirements.");
? req.query.category if (errors.length) return res.status(400).send(errors.join(", "));
: [req.query.category]
: []; // default to empty, will be set to all
if (!Array.isArray(categories)) {
return res.status(400).send("Categories parameter does not match format requirements.");
}
} catch(error) {
return res.status(400).send("Bad parameter: categories (invalid JSON)");
}
// only take valid categories // only take valid categories
const searchCategories = (categories.length === 0 ) const searchCategories = filterInvalidCategoryActionType(categories, actionTypes);
? possibleCategories
: categories.filter(x =>
possibleCategories.includes(x));
try { try {
// Get existing lock categories markers // Get existing lock categories markers

View File

@@ -2,6 +2,8 @@ import { Request, Response } from "express";
import { db } from "../databases/databases"; import { db } from "../databases/databases";
import { ActionType, Category, DBSegment, Service, VideoID, SortableFields } from "../types/segments.model"; import { ActionType, Category, DBSegment, Service, VideoID, SortableFields } from "../types/segments.model";
import { getService } from "../utils/getService"; import { getService } from "../utils/getService";
import { parseActionTypes, parseCategories } from "../utils/parseParams";
const maxSegmentsPerPage = 100; const maxSegmentsPerPage = 100;
const defaultSegmentsPerPage = 10; const defaultSegmentsPerPage = 10;
@@ -73,25 +75,15 @@ async function handleGetSegments(req: Request, res: Response): Promise<searchSeg
return false; return false;
} }
// Default to sponsor // Default to sponsor
const categories: Category[] = req.query.categories const categories: Category[] = parseCategories(req, []);
? JSON.parse(req.query.categories as string) console.log(categories)
: req.query.category
? Array.isArray(req.query.category)
? req.query.category
: [req.query.category]
: [];
if (!Array.isArray(categories)) { if (!Array.isArray(categories)) {
res.status(400).send("Categories parameter does not match format requirements."); res.status(400).send("Categories parameter does not match format requirements.");
return false; return false;
} }
const actionTypes: ActionType[] = req.query.actionTypes const actionTypes: ActionType[] = parseActionTypes(req, [ActionType.Skip]);
? JSON.parse(req.query.actionTypes as string) console.log(actionTypes)
: req.query.actionType
? Array.isArray(req.query.actionType)
? req.query.actionType
: [req.query.actionType]
: [ActionType.Skip];
if (!Array.isArray(actionTypes)) { if (!Array.isArray(actionTypes)) {
res.status(400).send("actionTypes parameter does not match format requirements."); res.status(400).send("actionTypes parameter does not match format requirements.");
return false; return false;
@@ -184,6 +176,7 @@ async function endpoint(req: Request, res: Response): Promise<Response> {
} }
} catch (err) { } catch (err) {
/* istanbul ignore next */ /* istanbul ignore next */
console.log(err)
if (err instanceof SyntaxError) { if (err instanceof SyntaxError) {
return res.status(400).send("Invalid array in parameters"); return res.status(400).send("Invalid array in parameters");
} else return res.sendStatus(500); } else return res.sendStatus(500);

View File

@@ -6,11 +6,13 @@ import { Category, Service, VideoID, VideoIDHash } from "../types/segments.model
import { UserID } from "../types/user.model"; import { UserID } from "../types/user.model";
import { QueryCacher } from "../utils/queryCacher"; import { QueryCacher } from "../utils/queryCacher";
import { isUserVIP } from "../utils/isUserVIP"; import { isUserVIP } from "../utils/isUserVIP";
import { parseCategories } from "../utils/parseParams";
export async function shadowBanUser(req: Request, res: Response): Promise<Response> { export async function shadowBanUser(req: Request, res: Response): Promise<Response> {
const userID = req.query.userID as UserID; const userID = req.query.userID as UserID;
const hashedIP = req.query.hashedIP as string; const hashedIP = req.query.hashedIP as string;
const adminUserIDInput = req.query.adminUserID as UserID; const adminUserIDInput = req.query.adminUserID as UserID;
const type = req.query.type as string ?? "1";
const enabled = req.query.enabled === undefined const enabled = req.query.enabled === undefined
? true ? true
@@ -19,10 +21,9 @@ export async function shadowBanUser(req: Request, res: Response): Promise<Respon
//if enabled is false and the old submissions should be made visible again //if enabled is false and the old submissions should be made visible again
const unHideOldSubmissions = req.query.unHideOldSubmissions !== "false"; const unHideOldSubmissions = req.query.unHideOldSubmissions !== "false";
const categories: string[] = req.query.categories ? JSON.parse(req.query.categories as string) : config.categoryList; const categories: Category[] = parseCategories(req, config.categoryList as Category[]);
categories.filter((category) => typeof category === "string" && !(/[^a-z|_|-]/.test(category)));
if (adminUserIDInput == undefined || (userID == undefined && hashedIP == undefined)) { if (adminUserIDInput == undefined || (userID == undefined && hashedIP == undefined || type !== "1" && type !== "2")) {
//invalid request //invalid request
return res.sendStatus(400); return res.sendStatus(400);
} }
@@ -48,7 +49,7 @@ export async function shadowBanUser(req: Request, res: Response): Promise<Respon
//find all previous submissions and hide them //find all previous submissions and hide them
if (unHideOldSubmissions) { if (unHideOldSubmissions) {
await unHideSubmissions(categories, userID); await unHideSubmissions(categories, userID, type);
} }
} else if (!enabled && row.userCount > 0) { } else if (!enabled && row.userCount > 0) {
//remove them from the shadow ban list //remove them from the shadow ban list
@@ -66,7 +67,7 @@ export async function shadowBanUser(req: Request, res: Response): Promise<Respon
return segmentsToIgnore.indexOf(item) === -1; return segmentsToIgnore.indexOf(item) === -1;
}).map(async (UUID: string) => { }).map(async (UUID: string) => {
// collect list for unshadowbanning // collect list for unshadowbanning
(await db.prepare("all", `SELECT "videoID", "hashedVideoID", "service", "votes", "views", "userID" FROM "sponsorTimes" WHERE "UUID" = ? AND "shadowHidden" = 1 AND "category" in (${categories.map((c) => `'${c}'`).join(",")})`, [UUID])) (await db.prepare("all", `SELECT "videoID", "hashedVideoID", "service", "votes", "views", "userID" FROM "sponsorTimes" WHERE "UUID" = ? AND "shadowHidden" >= 1 AND "category" in (${categories.map((c) => `'${c}'`).join(",")})`, [UUID]))
.forEach((videoInfo: {category: Category, videoID: VideoID, hashedVideoID: VideoIDHash, service: Service, userID: UserID}) => { .forEach((videoInfo: {category: Category, videoID: VideoID, hashedVideoID: VideoIDHash, service: Service, userID: UserID}) => {
QueryCacher.clearSegmentCache(videoInfo); QueryCacher.clearSegmentCache(videoInfo);
} }
@@ -79,7 +80,7 @@ export async function shadowBanUser(req: Request, res: Response): Promise<Respon
} else if (enabled && row.userCount > 0) { } else if (enabled && row.userCount > 0) {
// apply unHideOldSubmissions if applicable // apply unHideOldSubmissions if applicable
if (unHideOldSubmissions) { if (unHideOldSubmissions) {
await unHideSubmissions(categories, userID); await unHideSubmissions(categories, userID, type);
return res.sendStatus(200); return res.sendStatus(200);
} }
@@ -100,7 +101,7 @@ export async function shadowBanUser(req: Request, res: Response): Promise<Respon
//find all previous submissions and hide them //find all previous submissions and hide them
if (unHideOldSubmissions) { if (unHideOldSubmissions) {
await db.prepare("run", `UPDATE "sponsorTimes" SET "shadowHidden" = 1 WHERE "timeSubmitted" IN await db.prepare("run", `UPDATE "sponsorTimes" SET "shadowHidden" = ${type} WHERE "timeSubmitted" IN
(SELECT "privateDB"."timeSubmitted" FROM "sponsorTimes" LEFT JOIN "privateDB"."sponsorTimes" as "privateDB" ON "sponsorTimes"."timeSubmitted"="privateDB"."timeSubmitted" (SELECT "privateDB"."timeSubmitted" FROM "sponsorTimes" LEFT JOIN "privateDB"."sponsorTimes" as "privateDB" ON "sponsorTimes"."timeSubmitted"="privateDB"."timeSubmitted"
WHERE "privateDB"."hashedIP" = ?)`, [hashedIP]); WHERE "privateDB"."hashedIP" = ?)`, [hashedIP]);
} }
@@ -117,8 +118,8 @@ export async function shadowBanUser(req: Request, res: Response): Promise<Respon
return res.sendStatus(200); return res.sendStatus(200);
} }
async function unHideSubmissions(categories: string[], userID: UserID) { async function unHideSubmissions(categories: string[], userID: UserID, type = "1") {
await db.prepare("run", `UPDATE "sponsorTimes" SET "shadowHidden" = 1 WHERE "userID" = ? AND "category" in (${categories.map((c) => `'${c}'`).join(",")}) await db.prepare("run", `UPDATE "sponsorTimes" SET "shadowHidden" = ${type} WHERE "userID" = ? AND "category" in (${categories.map((c) => `'${c}'`).join(",")})
AND NOT EXISTS ( SELECT "videoID", "category" FROM "lockCategories" WHERE AND NOT EXISTS ( SELECT "videoID", "category" FROM "lockCategories" WHERE
"sponsorTimes"."videoID" = "lockCategories"."videoID" AND "sponsorTimes"."service" = "lockCategories"."service" AND "sponsorTimes"."category" = "lockCategories"."category")`, [userID]); "sponsorTimes"."videoID" = "lockCategories"."videoID" AND "sponsorTimes"."service" = "lockCategories"."service" AND "sponsorTimes"."category" = "lockCategories"."category")`, [userID]);

75
src/utils/parseParams.ts Normal file
View File

@@ -0,0 +1,75 @@
import { Request } from "express";
import { ActionType, SegmentUUID, Category } from "../types/segments.model";
import { config } from "../config";
type fn = (req: Request, fallback: any) => any[];
const syntaxErrorWrapper = (fn: fn, req: Request, fallback: any) => {
try { return fn(req, fallback); }
catch (e) {
return undefined;
}
};
const getCategories = (req: Request, fallback: Category[] ): string[] | Category[] =>
req.query.categories
? JSON.parse(req.query.categories as string)
: req.query.category
? Array.isArray(req.query.category)
? req.query.category
: [req.query.category]
: fallback;
const validateString = (array: any[]): any[] => {
if (!Array.isArray(array)) return undefined;
return array
.filter((item: any) => typeof item === "string")
.filter((item: string) => !(/[^a-z|_|-]/.test(item)));
};
const filterActionType = (actionTypes: ActionType[]) => {
const filterCategories = new Set();
for (const [key, value] of Object.entries(config.categorySupport)) {
for (const type of actionTypes) {
if (value.includes(type)) {
filterCategories.add(key as Category);
}
}
}
return [...filterCategories];
};
export const filterInvalidCategoryActionType = (categories: Category[], actionTypes: ActionType[]): Category[] =>
categories.filter((category: Category) => filterActionType(actionTypes).includes(category));
const getActionTypes = (req: Request, fallback: ActionType[]): ActionType[] =>
req.query.actionTypes
? JSON.parse(req.query.actionTypes as string)
: req.query.actionType
? Array.isArray(req.query.actionType)
? req.query.actionType
: [req.query.actionType]
: fallback;
// fallback to empty array
const getRequiredSegments = (req: Request): SegmentUUID[] =>
req.query.requiredSegments
? JSON.parse(req.query.requiredSegments as string)
: req.query.requiredSegment
? Array.isArray(req.query.requiredSegment)
? req.query.requiredSegment
: [req.query.requiredSegment]
: [];
export const parseCategories = (req: Request, fallback: Category[]): Category[] => {
const categories = syntaxErrorWrapper(getCategories, req, fallback);
return categories ? validateString(categories) : undefined;
};
export const parseActionTypes = (req: Request, fallback: ActionType[]): ActionType[] => {
const actionTypes = syntaxErrorWrapper(getActionTypes, req, fallback);
return actionTypes ? validateString(actionTypes) : undefined;
};
export const parseRequiredSegments = (req: Request): SegmentUUID[] | undefined =>
syntaxErrorWrapper(getRequiredSegments, req, []); // never fall back

View File

@@ -2,42 +2,7 @@ import { Request } from "express";
import { ActionType, SegmentUUID, Category, Service } from "../types/segments.model"; import { ActionType, SegmentUUID, Category, Service } from "../types/segments.model";
import { getService } from "./getService"; import { getService } from "./getService";
type fn = (req: Request) => any[]; import { parseCategories, parseActionTypes, parseRequiredSegments } from "./parseParams";
const syntaxErrorWrapper = (fn: fn, req: Request) => {
try { return fn(req); }
catch (e) { return undefined; }
};
// Default to sponsor
const getCategories = (req: Request): Category[] =>
req.query.categories
? JSON.parse(req.query.categories as string)
: req.query.category
? Array.isArray(req.query.category)
? req.query.category
: [req.query.category]
: ["sponsor"];
// Default to skip
const getActionTypes = (req: Request): ActionType[] =>
req.query.actionTypes
? JSON.parse(req.query.actionTypes as string)
: req.query.actionType
? Array.isArray(req.query.actionType)
? req.query.actionType
: [req.query.actionType]
: [ActionType.Skip];
// Default to empty array
const getRequiredSegments = (req: Request): SegmentUUID[] =>
req.query.requiredSegments
? JSON.parse(req.query.requiredSegments as string)
: req.query.requiredSegment
? Array.isArray(req.query.requiredSegment)
? req.query.requiredSegment
: [req.query.requiredSegment]
: [];
const errorMessage = (parameter: string) => `${parameter} parameter does not match format requirements.`; const errorMessage = (parameter: string) => `${parameter} parameter does not match format requirements.`;
@@ -48,20 +13,14 @@ export function parseSkipSegments(req: Request): {
service: Service; service: Service;
errors: string[]; errors: string[];
} { } {
let categories: Category[] = syntaxErrorWrapper(getCategories, req); const categories: Category[] = parseCategories(req, [ "sponsor" as Category ]);
const actionTypes: ActionType[] = syntaxErrorWrapper(getActionTypes, req); const actionTypes: ActionType[] = parseActionTypes(req, [ActionType.Skip]);
const requiredSegments: SegmentUUID[] = syntaxErrorWrapper(getRequiredSegments, req); const requiredSegments: SegmentUUID[] = parseRequiredSegments(req);
const service: Service = getService(req.query.service, req.body.services); const service: Service = getService(req.query.service, req.body.services);
const errors: string[] = []; const errors: string[] = [];
if (!Array.isArray(categories)) errors.push(errorMessage("categories")); if (!Array.isArray(categories)) errors.push(errorMessage("categories"));
else { else if (categories.length === 0) errors.push("No valid categories provided.");
// check category names for invalid characters
// and none string elements
categories = categories
.filter((item: any) => typeof item === "string")
.filter((category) => !(/[^a-z|_|-]/.test(category)));
if (categories.length === 0) errors.push("No valid categories provided.");
}
if (!Array.isArray(actionTypes)) errors.push(errorMessage("actionTypes")); if (!Array.isArray(actionTypes)) errors.push(errorMessage("actionTypes"));
if (!Array.isArray(requiredSegments)) errors.push(errorMessage("requiredSegments")); if (!Array.isArray(requiredSegments)) errors.push(errorMessage("requiredSegments"));
// finished parsing // finished parsing

View File

@@ -11,22 +11,26 @@ describe("shadowBanUser", () => {
const endpoint = "/api/shadowBanUser"; const endpoint = "/api/shadowBanUser";
const VIPuserID = "shadow-ban-vip"; const VIPuserID = "shadow-ban-vip";
const video = "shadowBanVideo";
const videohash = getHash(video, 1);
before(async () => { before(async () => {
const insertQuery = `INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", "views", "category", "service", "videoDuration", "hidden", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`; const insertQuery = `INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", "views", "category", "service", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
await db.prepare("run", insertQuery, ["testtesttest", 1, 11, 2, 0, "shadow-1-uuid-0", "shadowBanned", 0, 50, "sponsor", "YouTube", 100, 0, 0, getHash("testtesttest", 1)]); await db.prepare("run", insertQuery, [video, 1, 11, 2, 0, "shadow-10", "shadowBanned", 0, 50, "sponsor", "YouTube", 0, videohash]);
await db.prepare("run", insertQuery, ["testtesttest2", 1, 11, 2, 0, "shadow-1-uuid-0-1", "shadowBanned", 0, 50, "sponsor", "PeerTube", 120, 0, 0, getHash("testtesttest2", 1)]); await db.prepare("run", insertQuery, [video, 1, 11, 2, 0, "shadow-11", "shadowBanned", 0, 50, "sponsor", "PeerTube", 0, videohash]);
await db.prepare("run", insertQuery, ["testtesttest", 20, 33, 2, 0, "shadow-1-uuid-2", "shadowBanned", 0, 50, "intro", "YouTube", 101, 0, 0, getHash("testtesttest", 1)]); await db.prepare("run", insertQuery, [video, 20, 33, 2, 0, "shadow-12", "shadowBanned", 0, 50, "intro", "YouTube", 0, videohash]);
await db.prepare("run", insertQuery, ["testtesttest", 1, 11, 2, 0, "shadow-2-uuid-0", "shadowBanned2", 0, 50, "sponsor", "YouTube", 100, 0, 0, getHash("testtesttest", 1)]); await db.prepare("run", insertQuery, [video, 1, 11, 2, 0, "shadow-20", "shadowBanned2", 0, 50, "sponsor", "YouTube", 0, videohash]);
await db.prepare("run", insertQuery, ["testtesttest2", 1, 11, 2, 0, "shadow-2-uuid-0-1", "shadowBanned2", 0, 50, "sponsor", "PeerTube", 120, 0, 0, getHash("testtesttest2", 1)]); await db.prepare("run", insertQuery, [video, 1, 11, 2, 0, "shadow-21", "shadowBanned2", 0, 50, "sponsor", "PeerTube", 0, videohash]);
await db.prepare("run", insertQuery, ["testtesttest", 20, 33, 2, 0, "shadow-2-uuid-2", "shadowBanned2", 0, 50, "intro", "YouTube", 101, 0, 0, getHash("testtesttest", 1)]); await db.prepare("run", insertQuery, [video, 20, 33, 2, 0, "shadow-22", "shadowBanned2", 0, 50, "intro", "YouTube", 0, videohash]);
await db.prepare("run", insertQuery, ["testtesttest", 1, 11, 2, 0, "shadow-3-uuid-0", "shadowBanned3", 0, 50, "sponsor", "YouTube", 100, 0, 1, getHash("testtesttest", 1)]); await db.prepare("run", insertQuery, [video, 1, 11, 2, 0, "shadow-30", "shadowBanned3", 0, 50, "sponsor", "YouTube", 1, videohash]);
await db.prepare("run", insertQuery, ["testtesttest2", 1, 11, 2, 0, "shadow-3-uuid-0-1", "shadowBanned3", 0, 50, "sponsor", "PeerTube", 120, 0, 1, getHash("testtesttest2", 1)]); await db.prepare("run", insertQuery, [video, 1, 11, 2, 0, "shadow-31", "shadowBanned3", 0, 50, "sponsor", "PeerTube", 1, videohash]);
await db.prepare("run", insertQuery, ["testtesttest", 20, 33, 2, 0, "shadow-3-uuid-2", "shadowBanned3", 0, 50, "intro", "YouTube", 101, 0, 1, getHash("testtesttest", 1)]); await db.prepare("run", insertQuery, [video, 20, 33, 2, 0, "shadow-32", "shadowBanned3", 0, 50, "intro", "YouTube", 1, videohash]);
await db.prepare("run", insertQuery, ["testtesttest", 21, 34, 2, 0, "shadow-4-uuid-1", "shadowBanned4", 0, 50, "sponsor", "YouTube", 101, 0, 0, getHash("testtesttest", 1)]); await db.prepare("run", insertQuery, [video, 21, 34, 2, 0, "shadow-40", "shadowBanned4", 0, 50, "sponsor", "YouTube", 0, videohash]);
await db.prepare("run", insertQuery, [video, 20, 10, 2, 0, "shadow-50", "shadowBanned5", 0, 50, "sponsor", "YouTube", 0, videohash]);
await db.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES(?)`, ["shadowBanned3"]); await db.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES(?)`, ["shadowBanned3"]);
await db.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES(?)`, ["shadowBanned4"]); await db.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES(?)`, ["shadowBanned4"]);
@@ -220,4 +224,54 @@ describe("shadowBanUser", () => {
}) })
.catch(err => done(err)); .catch(err => done(err));
}); });
it("Should be able to shadowban user with different type", (done) => {
const userID = "shadowBanned5";
client({
method: "POST",
url: endpoint,
params: {
userID,
adminUserID: VIPuserID,
enabled: true,
categories: `["sponsor"]`,
unHideOldSubmissions: true,
type: "2"
}
})
.then(async res => {
assert.strictEqual(res.status, 200);
const type2Videos = await getShadowBanSegmentCategory(userID, 2);
const type1Videos = await getShadowBanSegmentCategory(userID, 1);
const type0Videos = await getShadowBanSegmentCategory(userID, 0);
const shadowRow = await getShadowBan(userID);
assert.ok(shadowRow); // ban still exists
assert.ok(type2Videos.length > 0); // videos at type 2
assert.strictEqual(type1Videos.length, 0); // no videos at type 1
assert.strictEqual(type0Videos.length, 0); // no videos at type 0
done();
})
.catch(err => done(err));
});
it("Should not be able to shadowban user with invalid type", (done) => {
const userID = "shadowBanned5";
client({
method: "POST",
url: endpoint,
params: {
userID,
adminUserID: VIPuserID,
enabled: true,
categories: `["sponsor"]`,
unHideOldSubmissions: true,
type: "3"
}
})
.then(res => {
assert.strictEqual(res.status, 400);
done();
})
.catch(err => done(err));
});
}); });