mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-06 03:26:59 +03:00
Merge pull request #610 from mini-bomba/warning-history
Keep a history of warnings in the public database
This commit is contained in:
@@ -31,15 +31,15 @@ module.exports = {
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["src/**/*.ts"],
|
||||
files: ["**/*.ts"],
|
||||
|
||||
parserOptions: {
|
||||
project: ["./tsconfig.json"],
|
||||
project: ["./tsconfig.eslint.json"],
|
||||
},
|
||||
|
||||
rules: {
|
||||
"@typescript-eslint/no-misused-promises": "warn",
|
||||
"@typescript-eslint/no-floating-promises" : "warn"
|
||||
"@typescript-eslint/no-misused-promises": "error",
|
||||
"@typescript-eslint/no-floating-promises" : "error"
|
||||
}
|
||||
},
|
||||
],
|
||||
|
||||
1
ci.json
1
ci.json
@@ -56,7 +56,6 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"hoursAfterWarningExpires": 24,
|
||||
"rateLimit": {
|
||||
"vote": {
|
||||
"windowMs": 900000,
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
"webhooks": [],
|
||||
"categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "preview", "music_offtopic", "poi_highlight"], // List of supported categories any other category will be rejected
|
||||
"getTopUsersCacheTimeMinutes": 5, // cacheTime for getTopUsers result in minutes
|
||||
"maxNumberOfActiveWarnings": 3, // Users with this number of warnings will be blocked until warnings expire
|
||||
"hoursAfterWarningExpire": 24,
|
||||
"rateLimit": {
|
||||
"vote": {
|
||||
"windowMs": 900000, // 15 minutes
|
||||
|
||||
7
databases/_upgrade_sponsorTimes_45.sql
Normal file
7
databases/_upgrade_sponsorTimes_45.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
ALTER TABLE "warnings" ADD "disableTime" INTEGER NULL;
|
||||
|
||||
UPDATE "config" SET value = 45 WHERE key = 'version';
|
||||
|
||||
COMMIT;
|
||||
@@ -37,8 +37,6 @@ addDefaults(config, {
|
||||
},
|
||||
deArrowTypes: ["title", "thumbnail"],
|
||||
maxTitleLength: 110,
|
||||
maxNumberOfActiveWarnings: 1,
|
||||
hoursAfterWarningExpires: 16300000,
|
||||
adminUserID: "",
|
||||
discordCompletelyIncorrectReportWebhookURL: null,
|
||||
discordFirstTimeSubmissionsWebhookURL: null,
|
||||
|
||||
@@ -3,7 +3,6 @@ import { CronJob } from "cron";
|
||||
import { config as serverConfig } from "../config";
|
||||
import { Logger } from "../utils/logger";
|
||||
import { db } from "../databases/databases";
|
||||
import { DBSegment } from "../types/segments.model";
|
||||
|
||||
const jobConfig = serverConfig?.crons?.downvoteSegmentArchive;
|
||||
|
||||
@@ -14,18 +13,18 @@ export const archiveDownvoteSegment = async (dayLimit: number, voteLimit: number
|
||||
Logger.info(`DownvoteSegmentArchiveJob starts at ${timeNow}`);
|
||||
try {
|
||||
// insert into archive sponsorTime
|
||||
await db.prepare(
|
||||
"run",
|
||||
`INSERT INTO "archivedSponsorTimes"
|
||||
SELECT *
|
||||
FROM "sponsorTimes"
|
||||
WHERE "votes" < ? AND (? - "timeSubmitted") > ?`,
|
||||
[
|
||||
voteLimit,
|
||||
timeNow,
|
||||
threshold
|
||||
]
|
||||
) as DBSegment[];
|
||||
await db.prepare(
|
||||
"run",
|
||||
`INSERT INTO "archivedSponsorTimes"
|
||||
SELECT *
|
||||
FROM "sponsorTimes"
|
||||
WHERE "votes" < ? AND (? - "timeSubmitted") > ?`,
|
||||
[
|
||||
voteLimit,
|
||||
timeNow,
|
||||
threshold
|
||||
]
|
||||
);
|
||||
|
||||
} catch (err) {
|
||||
Logger.error("Execption when insert segment in archivedSponsorTimes");
|
||||
@@ -35,15 +34,15 @@ export const archiveDownvoteSegment = async (dayLimit: number, voteLimit: number
|
||||
|
||||
// remove from sponsorTime
|
||||
try {
|
||||
await db.prepare(
|
||||
"run",
|
||||
'DELETE FROM "sponsorTimes" WHERE "votes" < ? AND (? - "timeSubmitted") > ?',
|
||||
[
|
||||
voteLimit,
|
||||
timeNow,
|
||||
threshold
|
||||
]
|
||||
) as DBSegment[];
|
||||
await db.prepare(
|
||||
"run",
|
||||
'DELETE FROM "sponsorTimes" WHERE "votes" < ? AND (? - "timeSubmitted") > ?',
|
||||
[
|
||||
voteLimit,
|
||||
timeNow,
|
||||
threshold
|
||||
]
|
||||
);
|
||||
|
||||
} catch (err) {
|
||||
Logger.error("Execption when deleting segment in sponsorTimes");
|
||||
|
||||
@@ -6,11 +6,14 @@ export interface QueryOption {
|
||||
export interface IDatabase {
|
||||
init(): Promise<void>;
|
||||
|
||||
prepare(type: QueryType, query: string, params?: any[], options?: QueryOption): Promise<any | any[] | void>;
|
||||
prepare(type: "run", query: string, params?: any[], options?: QueryOption): Promise<void>;
|
||||
prepare(type: "get", query: string, params?: any[], options?: QueryOption): Promise<any>;
|
||||
prepare(type: "all", query: string, params?: any[], options?: QueryOption): Promise<any[]>;
|
||||
prepare(type: QueryType, query: string, params?: any[], options?: QueryOption): Promise<any>;
|
||||
|
||||
highLoad(): boolean;
|
||||
|
||||
shouldUseRedisTimeout(): boolean;
|
||||
}
|
||||
|
||||
export type QueryType = "get" | "all" | "run";
|
||||
export type QueryType = "get" | "all" | "run";
|
||||
|
||||
@@ -109,7 +109,7 @@ export class Postgres implements IDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
async prepare(type: QueryType, query: string, params?: any[], options: QueryOption = {}): Promise<any[]> {
|
||||
async prepare(type: QueryType, query: string, params?: any[], options: QueryOption = {}): Promise<any> {
|
||||
// Convert query to use numbered parameters
|
||||
let count = 1;
|
||||
for (let char = 0; char < query.length; char++) {
|
||||
|
||||
@@ -13,7 +13,7 @@ export class Sqlite implements IDatabase {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
async prepare(type: QueryType, query: string, params: any[] = []): Promise<any[]> {
|
||||
async prepare(type: QueryType, query: string, params: any[] = []): Promise<any> {
|
||||
// Logger.debug(`prepare (sqlite): type: ${type}, query: ${query}, params: ${params}`);
|
||||
const preparedQuery = this.db.prepare(Sqlite.processQuery(query));
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ function chooseSegment<T extends DBSegment>(choices: T[]): FullVideoSegmentVideo
|
||||
return {
|
||||
segments: transformDBSegments(choices),
|
||||
hasStartSegment
|
||||
}
|
||||
};
|
||||
}
|
||||
// if locked, only choose from locked
|
||||
const locked = choices.filter((segment) => segment.locked);
|
||||
|
||||
@@ -164,20 +164,15 @@ async function autoModerateSubmission(apiVideoDetails: videoDetails,
|
||||
}
|
||||
|
||||
async function checkUserActiveWarning(userID: HashedUserID): Promise<CheckResult> {
|
||||
const MILLISECONDS_IN_HOUR = 3600000;
|
||||
const now = Date.now();
|
||||
const warnings = (await db.prepare("all",
|
||||
const warning = await db.prepare("get",
|
||||
`SELECT "reason"
|
||||
FROM warnings
|
||||
WHERE "userID" = ? AND "issueTime" > ? AND enabled = 1 AND type = 0
|
||||
WHERE "userID" = ? AND enabled = 1 AND type = 0
|
||||
ORDER BY "issueTime" DESC`,
|
||||
[
|
||||
userID,
|
||||
Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR))
|
||||
],
|
||||
) as {reason: string}[]).sort((a, b) => (b?.reason?.length ?? 0) - (a?.reason?.length ?? 0));
|
||||
[userID],
|
||||
) as {reason: string};
|
||||
|
||||
if (warnings?.length >= config.maxNumberOfActiveWarnings) {
|
||||
if (warning != null) {
|
||||
const defaultMessage = "Submission rejected due to a tip 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.gg/SponsorBlock or matrix.to/#/#sponsor:ajay.app so we can further help you? "
|
||||
@@ -185,7 +180,7 @@ async function checkUserActiveWarning(userID: HashedUserID): Promise<CheckResult
|
||||
|
||||
return {
|
||||
pass: false,
|
||||
errorMessage: defaultMessage + (warnings[0]?.reason?.length > 0 ? `\n\nTip message: '${warnings[0].reason}'` : ""),
|
||||
errorMessage: defaultMessage + (warning.reason?.length > 0 ? `\n\nTip message: '${warning.reason}'` : ""),
|
||||
errorCode: 403
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { db } from "../databases/databases";
|
||||
import { isUserVIP } from "../utils/isUserVIP";
|
||||
import { getHashCache } from "../utils/getHashCache";
|
||||
import { HashedUserID, UserID } from "../types/user.model";
|
||||
import { config } from "../config";
|
||||
import { generateWarningDiscord, warningData, dispatchEvent } from "../utils/webhookUtils";
|
||||
import { WarningType } from "../types/warning.model";
|
||||
|
||||
@@ -16,12 +15,7 @@ type warningEntry = {
|
||||
reason: string
|
||||
}
|
||||
|
||||
function checkExpiredWarning(warning: warningEntry): boolean {
|
||||
const MILLISECONDS_IN_HOUR = 3600000;
|
||||
const now = Date.now();
|
||||
const expiry = Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR));
|
||||
return warning.issueTime > expiry && !warning.enabled;
|
||||
}
|
||||
const MAX_EDIT_DELAY = 900000; // 15 mins
|
||||
|
||||
const getUsername = (userID: HashedUserID) => db.prepare("get", `SELECT "userName" FROM "userNames" WHERE "userID" = ?`, [userID], { useReplica: true });
|
||||
|
||||
@@ -44,30 +38,30 @@ export async function postWarning(req: Request, res: Response): Promise<Response
|
||||
|
||||
try {
|
||||
if (enabled) {
|
||||
const previousWarning = await db.prepare("get", 'SELECT * FROM "warnings" WHERE "userID" = ? AND "issuerUserID" = ? AND "type" = ?', [userID, issuerUserID, type]) as warningEntry;
|
||||
if (!reason) {
|
||||
return res.status(400).json({ "message": "Missing warning reason" });
|
||||
}
|
||||
const previousWarning = await db.prepare("get", 'SELECT * FROM "warnings" WHERE "userID" = ? AND "type" = ? AND "enabled" = 1', [userID, type]) as warningEntry;
|
||||
|
||||
if (!previousWarning) {
|
||||
if (!reason) {
|
||||
return res.status(400).json({ "message": "Missing warning reason" });
|
||||
}
|
||||
await db.prepare(
|
||||
"run",
|
||||
'INSERT INTO "warnings" ("userID", "issueTime", "issuerUserID", "enabled", "reason", "type") VALUES (?, ?, ?, 1, ?, ?)',
|
||||
[userID, issueTime, issuerUserID, reason, type]
|
||||
);
|
||||
resultStatus = "issued to";
|
||||
// check if warning is still within issue time and warning is not enabled
|
||||
} else if (checkExpiredWarning(previousWarning) ) {
|
||||
// allow a warning to be edited by the same vip within 15 mins of issuing
|
||||
} else if (issuerUserID === previousWarning.issuerUserID && (Date.now() - MAX_EDIT_DELAY) < previousWarning.issueTime) {
|
||||
await db.prepare(
|
||||
"run", 'UPDATE "warnings" SET "enabled" = 1, "reason" = ? WHERE "userID" = ? AND "issueTime" = ?',
|
||||
"run", 'UPDATE "warnings" SET "reason" = ? WHERE "userID" = ? AND "issueTime" = ?',
|
||||
[reason, userID, previousWarning.issueTime]
|
||||
);
|
||||
resultStatus = "re-enabled for";
|
||||
resultStatus = "edited for";
|
||||
} else {
|
||||
return res.sendStatus(409);
|
||||
}
|
||||
} else {
|
||||
await db.prepare("run", 'UPDATE "warnings" SET "enabled" = 0 WHERE "userID" = ? AND "type" = ?', [userID, type]);
|
||||
await db.prepare("run", 'UPDATE "warnings" SET "enabled" = 0, "disableTime" = ? WHERE "userID" = ? AND "type" = ? AND "enabled" = 1', [issueTime, userID, type]);
|
||||
resultStatus = "removed from";
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { isUserBanned } from "../utils/checkBan";
|
||||
import { HashedUserID } from "../types/user.model";
|
||||
import { isRequestInvalid } from "../utils/requestValidator";
|
||||
|
||||
function logUserNameChange(userID: string, newUserName: string, oldUserName: string, updatedByAdmin: boolean): Promise<Response> {
|
||||
function logUserNameChange(userID: string, newUserName: string, oldUserName: string, updatedByAdmin: boolean): Promise<void> {
|
||||
return privateDB.prepare("run",
|
||||
`INSERT INTO "userNameLogs"("userID", "newUserName", "oldUserName", "updatedByAdmin", "updatedAt") VALUES(?, ?, ?, ?, ?)`,
|
||||
[userID, newUserName, oldUserName, + updatedByAdmin, new Date().getTime()]
|
||||
|
||||
@@ -379,14 +379,12 @@ 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 AND type = 0`,
|
||||
[nonAnonUserID, Math.floor(now - (config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR))],
|
||||
const warning = (await db.prepare("get", `SELECT "reason" FROM warnings WHERE "userID" = ? AND enabled = 1 AND type = 0`,
|
||||
[nonAnonUserID],
|
||||
));
|
||||
|
||||
if (warnings.length >= config.maxNumberOfActiveWarnings) {
|
||||
const warningReason = warnings[0]?.reason;
|
||||
if (warning != null) {
|
||||
const warningReason = warning.reason;
|
||||
lock.unlock();
|
||||
return { status: 403, message: "Vote rejected due to a tip 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?" +
|
||||
|
||||
@@ -109,8 +109,6 @@ export interface SBSConfig {
|
||||
categorySupport: Record<string, string[]>;
|
||||
maxTitleLength: number;
|
||||
getTopUsersCacheTimeMinutes: number;
|
||||
maxNumberOfActiveWarnings: number;
|
||||
hoursAfterWarningExpires: number;
|
||||
rateLimit: {
|
||||
vote: RateLimitConfig;
|
||||
view: RateLimitConfig;
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"hoursAfterWarningExpires": 24,
|
||||
"rateLimit": {
|
||||
"vote": {
|
||||
"windowMs": 900000,
|
||||
|
||||
@@ -73,11 +73,11 @@ describe("getUserID", () => {
|
||||
)
|
||||
);
|
||||
|
||||
it("Should be able to get multiple fuzzy user info from middle", () => {
|
||||
it("Should be able to get multiple fuzzy user info from middle", () =>
|
||||
validateSearch("user",
|
||||
[users["fuzzy_1"], users["fuzzy_2"], users["specific_1"]]
|
||||
);
|
||||
});
|
||||
)
|
||||
);
|
||||
|
||||
it("Should be able to get with fuzzy public ID", () => {
|
||||
const userID = users["public_1"].pubID.substring(0,60);
|
||||
@@ -117,4 +117,4 @@ describe("getUserID 400/ 404", () => {
|
||||
it("Should not allow usernames less than 3 characters", () => validateStatus("aa", 400));
|
||||
it("Should return 404 if escaped backslashes present", () => validateStatus("%redos\\\\_", 404));
|
||||
it("Should return 404 if backslashes present", () => validateStatus(`\\%redos\\_`, 404));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -81,19 +81,19 @@ describe("getUserInfo", () => {
|
||||
|
||||
// warnings & bans
|
||||
// warn-0
|
||||
insertWarning(db, users["warn-0"].pubID, { reason: "warning0-0", issueTime: 10 });
|
||||
await insertWarning(db, users["warn-0"].pubID, { reason: "warning0-0", issueTime: 10 });
|
||||
// warn-1
|
||||
insertWarning(db, users["warn-1"].pubID, { reason: "warning1-0", issueTime: 20 });
|
||||
insertWarning(db, users["warn-1"].pubID, { reason: "warning1-1", issueTime: 30 });
|
||||
await insertWarning(db, users["warn-1"].pubID, { reason: "warning1-0", issueTime: 20 });
|
||||
await insertWarning(db, users["warn-1"].pubID, { reason: "warning1-1", issueTime: 30 });
|
||||
// warn -2
|
||||
insertWarning(db, users["warn-2"].pubID, { reason: "warning2-0", issueTime: 40, enabled: false });
|
||||
await insertWarning(db, users["warn-2"].pubID, { reason: "warning2-0", issueTime: 40, enabled: false });
|
||||
// warn-3
|
||||
insertWarning(db, users["warn-3"].pubID, { reason: "warning3-0", issueTime: 50 });
|
||||
insertWarning(db, users["warn-3"].pubID, { reason: "warning3-1", issueTime: 60, enabled: false });
|
||||
await insertWarning(db, users["warn-3"].pubID, { reason: "warning3-0", issueTime: 50 });
|
||||
await insertWarning(db, users["warn-3"].pubID, { reason: "warning3-1", issueTime: 60, enabled: false });
|
||||
|
||||
// ban-
|
||||
insertBan(db, users["ban-1"].pubID);
|
||||
insertBan(db, users["ban-2"].pubID);
|
||||
await insertBan(db, users["ban-1"].pubID);
|
||||
await insertBan(db, users["ban-2"].pubID);
|
||||
});
|
||||
|
||||
it("Should be able to get a 200", () => statusTest(200, { userID: users["n-1"].privID }));
|
||||
|
||||
@@ -33,11 +33,11 @@ const checkUserViews = (user: User) =>
|
||||
});
|
||||
|
||||
describe("getViewsForUser", function() {
|
||||
before(() => {
|
||||
before(async () => {
|
||||
// add views for users
|
||||
insertSegment(db, { userID: users["u-1"].pubID, views: users["u-1"].info.views1 });
|
||||
insertSegment(db, { userID: users["u-1"].pubID, views: users["u-1"].info.views2 });
|
||||
insertSegment(db, { userID: users["u-2"].pubID, views: users["u-2"].info.views });
|
||||
await insertSegment(db, { userID: users["u-1"].pubID, views: users["u-1"].info.views1 });
|
||||
await insertSegment(db, { userID: users["u-1"].pubID, views: users["u-1"].info.views2 });
|
||||
await insertSegment(db, { userID: users["u-2"].pubID, views: users["u-2"].info.views });
|
||||
});
|
||||
it("Should get back views for user one", () =>
|
||||
checkUserViews(users["u-1"])
|
||||
@@ -53,4 +53,4 @@ describe("getViewsForUser", function() {
|
||||
client({ url: endpoint })
|
||||
.then(res => assert.strictEqual(res.status, 400))
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,7 +15,6 @@ describe("postBranding", () => {
|
||||
const userID5 = `PostBrandingUser5${".".repeat(16)}`;
|
||||
const userID6 = `PostBrandingUser6${".".repeat(16)}`;
|
||||
const userID7 = `PostBrandingUser7${".".repeat(16)}`;
|
||||
const userID8 = `PostBrandingUser8${".".repeat(16)}`;
|
||||
const bannedUser = `BannedPostBrandingUser${".".repeat(16)}`;
|
||||
|
||||
|
||||
|
||||
@@ -50,12 +50,12 @@ describe("postSkipSegments", () => {
|
||||
const queryDatabaseActionType = (videoID: string) => db.prepare("get", `SELECT "startTime", "endTime", "locked", "category", "actionType" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]);
|
||||
const queryDatabaseVideoInfo = (videoID: string) => db.prepare("get", `SELECT * FROM "videoInfo" WHERE "videoID" = ?`, [videoID]);
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const insertSponsorTimeQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "videoDuration", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
db.prepare("run", insertSponsorTimeQuery, ["full_video_segment", 0, 0, 0, "full-video-uuid-0", submitUserTwoHash, 0, 0, "sponsor", "full", 0, 0, "full_video_segment"]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, ["full_video_segment", 0, 0, 0, "full-video-uuid-0", submitUserTwoHash, 0, 0, "sponsor", "full", 0, 0, "full_video_segment"]);
|
||||
|
||||
const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)';
|
||||
db.prepare("run", insertVipUserQuery, [getHash(submitVIPuser)]);
|
||||
await db.prepare("run", insertVipUserQuery, [getHash(submitVIPuser)]);
|
||||
});
|
||||
|
||||
it("Should be able to submit a single time (Params method)", (done) => {
|
||||
|
||||
@@ -19,11 +19,11 @@ describe("postSkipSegments - Automod 80%", () => {
|
||||
|
||||
const queryDatabaseCategory = (videoID: string) => db.prepare("all", `SELECT "startTime", "endTime", "category" FROM "sponsorTimes" WHERE "videoID" = ? and "votes" > -1`, [videoID]);
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const insertSponsorTimeQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "videoDuration", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
db.prepare("run", insertSponsorTimeQuery, [over80VideoID, 0, 1000, 0, "80percent-uuid-0", userIDHash, 0, 0, "interaction", "skip", 0, 0, over80VideoID]);
|
||||
db.prepare("run", insertSponsorTimeQuery, [over80VideoID, 1001, 1005, 0, "80percent-uuid-1", userIDHash, 0, 0, "interaction", "skip", 0, 0, over80VideoID]);
|
||||
db.prepare("run", insertSponsorTimeQuery, [over80VideoID, 0, 5000, -2, "80percent-uuid-2", userIDHash, 0, 0, "interaction", "skip", 0, 0, over80VideoID]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, [over80VideoID, 0, 1000, 0, "80percent-uuid-0", userIDHash, 0, 0, "interaction", "skip", 0, 0, over80VideoID]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, [over80VideoID, 1001, 1005, 0, "80percent-uuid-1", userIDHash, 0, 0, "interaction", "skip", 0, 0, over80VideoID]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, [over80VideoID, 0, 5000, -2, "80percent-uuid-2", userIDHash, 0, 0, "interaction", "skip", 0, 0, over80VideoID]);
|
||||
});
|
||||
|
||||
it("Should allow multiple times if total is under 80% of video (JSON method)", (done) => {
|
||||
|
||||
@@ -21,10 +21,10 @@ describe("postSkipSegments - duration", () => {
|
||||
|
||||
const queryDatabaseDuration = (videoID: string) => db.prepare("get", `SELECT "startTime", "endTime", "locked", "category", "videoDuration" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]);
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const insertSponsorTimeQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "videoDuration", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
db.prepare("run", insertSponsorTimeQuery, ["full_video_duration_segment", 0, 0, 0, "full-video-duration-uuid-0", userIDTwo, 0, 0, "sponsor", "full", 123, 0, "full_video_duration_segment"]);
|
||||
db.prepare("run", insertSponsorTimeQuery, ["full_video_duration_segment", 25, 30, 0, "full-video-duration-uuid-1", userIDTwo, 0, 0, "sponsor", "skip", 123, 0, "full_video_duration_segment"]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, ["full_video_duration_segment", 0, 0, 0, "full-video-duration-uuid-0", userIDTwo, 0, 0, "sponsor", "full", 123, 0, "full_video_duration_segment"]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, ["full_video_duration_segment", 25, 30, 0, "full-video-duration-uuid-1", userIDTwo, 0, 0, "sponsor", "skip", 123, 0, "full_video_duration_segment"]);
|
||||
});
|
||||
|
||||
it("Should be able to submit a single time with a precise duration close to the one from the YouTube API (JSON method)", (done) => {
|
||||
@@ -202,4 +202,4 @@ describe("postSkipSegments - duration", () => {
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -21,17 +21,17 @@ describe("postSkipSegments Features - Chapters", () => {
|
||||
};
|
||||
}
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const submitNumberOfTimes = 10;
|
||||
const submitUser_reputationHash = getHash(submitUser_reputation);
|
||||
const insertSponsorTimeQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "locked", "UUID", "userID", "timeSubmitted", views, category, "actionType", "shadowHidden") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
for (let i = 0; i < submitNumberOfTimes; i++) {
|
||||
const uuid = `post_reputation_uuid-${i}`;
|
||||
const videoID = `post_reputation_video-${i}`;
|
||||
db.prepare("run", insertSponsorTimeQuery, [videoID, 1, 11, 5, 1, uuid, submitUser_reputationHash, 1597240000000, 50, "sponsor", "skip", 0]);
|
||||
await db.prepare("run", insertSponsorTimeQuery, [videoID, 1, 11, 5, 1, uuid, submitUser_reputationHash, 1597240000000, 50, "sponsor", "skip", 0]);
|
||||
}
|
||||
// user feature
|
||||
db.prepare("run", `INSERT INTO "userFeatures" ("userID", "feature", "issuerUserID", "timeSubmitted") VALUES(?, ?, ?, ?)`, [getHash(submitUser_feature), Feature.ChapterSubmitter, "generic-VIP", 0]);
|
||||
await db.prepare("run", `INSERT INTO "userFeatures" ("userID", "feature", "issuerUserID", "timeSubmitted") VALUES(?, ?, ?, ?)`, [getHash(submitUser_feature), Feature.ChapterSubmitter, "generic-VIP", 0]);
|
||||
});
|
||||
|
||||
it("Should be able to submit a single chapter due to reputation (JSON method)", (done) => {
|
||||
|
||||
@@ -9,10 +9,10 @@ describe("postSkipSegments - LockedVideos", () => {
|
||||
const videoID = "lockedVideo";
|
||||
const userID = userIDOne;
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const insertLockCategoriesQuery = `INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason") VALUES(?, ?, ?, ?)`;
|
||||
db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "sponsor", "Custom Reason"]);
|
||||
db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "intro", ""]);
|
||||
await db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "sponsor", "Custom Reason"]);
|
||||
await db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "intro", ""]);
|
||||
});
|
||||
|
||||
it("Should return 403 and custom reason for submiting in lockedCategory", (done) => {
|
||||
@@ -67,4 +67,4 @@ describe("postSkipSegments - LockedVideos", () => {
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,8 +19,8 @@ describe("postSkipSegments - shadowban", () => {
|
||||
|
||||
const queryDatabaseShadowhidden = (videoID: string) => db.prepare("get", `SELECT "startTime", "endTime", "shadowHidden", "userID" FROM "sponsorTimes" WHERE "videoID" = ?`, [videoID]);
|
||||
|
||||
before(() => {
|
||||
db.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES(?)`, [banUser01Hash]);
|
||||
before(async () => {
|
||||
await db.prepare("run", `INSERT INTO "shadowBannedUsers" ("userID") VALUES(?)`, [banUser01Hash]);
|
||||
});
|
||||
|
||||
it("Should automatically shadowban segments if user is banned", (done) => {
|
||||
@@ -65,4 +65,4 @@ describe("postSkipSegments - shadowban", () => {
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -21,10 +21,10 @@ describe("postSkipSegments - userAgent", () => {
|
||||
};
|
||||
const dbFormatSegment = convertSingleToDBFormat(segment);
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const insertLockCategoriesQuery = `INSERT INTO "lockCategories" ("userID", "videoID", "category", "reason") VALUES(?, ?, ?, ?)`;
|
||||
db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "sponsor", "Custom Reason"]);
|
||||
db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "intro", ""]);
|
||||
await db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "sponsor", "Custom Reason"]);
|
||||
await db.prepare("run", insertLockCategoriesQuery, [getHash(VIPLockUser), videoID, "intro", ""]);
|
||||
});
|
||||
|
||||
it("Should be able to submit with empty user-agent", (done) => {
|
||||
@@ -101,4 +101,4 @@ describe("postSkipSegments - userAgent", () => {
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,20 +1,11 @@
|
||||
import { config } from "../../src/config";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import { db } from "../../src/databases/databases";
|
||||
import assert from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
import { usersForSuite } from "../utils/randomUsers";
|
||||
|
||||
describe("postSkipSegments Warnings", () => {
|
||||
// Constant and helpers
|
||||
const warnUser01 = "warn-user01";
|
||||
const warnUser01Hash = getHash(warnUser01);
|
||||
const warnUser02 = "warn-user02";
|
||||
const warnUser02Hash = getHash(warnUser02);
|
||||
const warnUser03 = "warn-user03";
|
||||
const warnUser03Hash = getHash(warnUser03);
|
||||
const warnUser04 = "warn-user04";
|
||||
const warnUser04Hash = getHash(warnUser04);
|
||||
|
||||
const users = usersForSuite("postSkipSegmentsWarnings");
|
||||
const warnVideoID = "postSkipSegments-warn-video";
|
||||
|
||||
const endpoint = "/api/skipSegments";
|
||||
@@ -24,104 +15,92 @@ describe("postSkipSegments Warnings", () => {
|
||||
data
|
||||
});
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const now = Date.now();
|
||||
|
||||
const warnVip01Hash = getHash("postSkipSegmentsWarnVIP");
|
||||
|
||||
const reason01 = "Reason01";
|
||||
const reason02 = "";
|
||||
const reason03 = "Reason03";
|
||||
|
||||
const MILLISECONDS_IN_HOUR = 3600000;
|
||||
const WARNING_EXPIRATION_TIME = config.hoursAfterWarningExpires * MILLISECONDS_IN_HOUR;
|
||||
|
||||
const insertWarningQuery = 'INSERT INTO warnings ("userID", "issuerUserID", "enabled", "reason", "issueTime") VALUES(?, ?, ?, ?, ?)';
|
||||
// User 1 | 1 active | custom reason
|
||||
db.prepare("run", insertWarningQuery, [warnUser01Hash, warnVip01Hash, 1, reason01, now]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u01.public, users.vip01.public, 1, reason01, now]);
|
||||
// User 2 | 1 inactive | default reason
|
||||
db.prepare("run", insertWarningQuery, [warnUser02Hash, warnVip01Hash, 0, reason02, now]);
|
||||
// User 3 | 1 expired, active | custom reason
|
||||
db.prepare("run", insertWarningQuery, [warnUser03Hash, warnVip01Hash, 1, reason03, (now - WARNING_EXPIRATION_TIME - 1000)]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u02.public, users.vip01.public, 0, reason02, now]);
|
||||
// User 3 | 1 inactive, 1 active | different reasons
|
||||
await db.prepare("run", insertWarningQuery, [users.u03.public, users.vip01.public, 0, reason01, now]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u03.public, users.vip01.public, 1, reason03, now+1]);
|
||||
// User 4 | 1 active | default reason
|
||||
db.prepare("run", insertWarningQuery, [warnUser04Hash, warnVip01Hash, 1, reason02, now]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u04.public, users.vip01.public, 1, reason02, now]);
|
||||
});
|
||||
|
||||
it("Should be rejected with custom message if user has active warnings", (done) => {
|
||||
postSkipSegmentJSON({
|
||||
userID: warnUser01,
|
||||
it("Should be rejected with custom message if user has active warnings", async () => {
|
||||
const res = await postSkipSegmentJSON({
|
||||
userID: users.u01.private,
|
||||
videoID: warnVideoID,
|
||||
segments: [{
|
||||
segment: [0, 10],
|
||||
category: "sponsor",
|
||||
}],
|
||||
})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
const errorMessage = res.data;
|
||||
const reason = "Reason01";
|
||||
const expected = "Submission rejected due to a tip 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.gg/SponsorBlock or matrix.to/#/#sponsor:ajay.app so we can further help you? "
|
||||
+ `Your userID is ${warnUser01Hash}.\n\nTip message: '${reason}'`;
|
||||
});
|
||||
assert.strictEqual(res.status, 403);
|
||||
const errorMessage = res.data;
|
||||
const reason = "Reason01";
|
||||
const expected = "Submission rejected due to a tip 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.gg/SponsorBlock or matrix.to/#/#sponsor:ajay.app so we can further help you? "
|
||||
+ `Your userID is ${users.u01.public}.\n\nTip message: '${reason}'`;
|
||||
|
||||
assert.strictEqual(errorMessage, expected);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
assert.strictEqual(errorMessage, expected);
|
||||
});
|
||||
|
||||
it("Should be accepted if user has inactive warning", (done) => {
|
||||
postSkipSegmentJSON({
|
||||
userID: warnUser02,
|
||||
it("Should be accepted if user has inactive warning", async () => {
|
||||
const res = await postSkipSegmentJSON({
|
||||
userID: users.u02.private,
|
||||
videoID: warnVideoID,
|
||||
segments: [{
|
||||
segment: [50, 60],
|
||||
category: "sponsor",
|
||||
}],
|
||||
})
|
||||
.then(res => {
|
||||
assert.ok(res.status === 200, `Status code was ${res.status} ${res.data}`);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
assert.ok(res.status === 200, `Status code was ${res.status} ${res.data}`);
|
||||
});
|
||||
|
||||
it("Should be accepted if user has expired warning", (done) => {
|
||||
postSkipSegmentJSON({
|
||||
userID: warnUser03,
|
||||
it("Should be rejected with custom message if user has active warnings, even if has one inactive warning, should use current message", async () => {
|
||||
const res = await postSkipSegmentJSON({
|
||||
userID: users.u03.private,
|
||||
videoID: warnVideoID,
|
||||
segments: [{
|
||||
segment: [53, 60],
|
||||
segment: [10, 20],
|
||||
category: "sponsor",
|
||||
}],
|
||||
})
|
||||
.then(res => {
|
||||
assert.ok(res.status === 200, `Status code was ${res.status} ${res.data}`);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
assert.strictEqual(res.status, 403);
|
||||
const errorMessage = res.data;
|
||||
const reason = "Reason03";
|
||||
const expected = "Submission rejected due to a tip 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.gg/SponsorBlock or matrix.to/#/#sponsor:ajay.app so we can further help you? "
|
||||
+ `Your userID is ${users.u03.public}.\n\nTip message: '${reason}'`;
|
||||
|
||||
assert.strictEqual(errorMessage, expected);
|
||||
});
|
||||
|
||||
it("Should be rejected with default message if user has active warning", (done) => {
|
||||
postSkipSegmentJSON({
|
||||
userID: warnUser04,
|
||||
it("Should be rejected with default message if user has active warning", async () => {
|
||||
const res = await postSkipSegmentJSON({
|
||||
userID: users.u04.private,
|
||||
videoID: warnVideoID,
|
||||
segments: [{
|
||||
segment: [0, 10],
|
||||
category: "sponsor",
|
||||
}],
|
||||
})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
const errorMessage = res.data;
|
||||
const expected = "Submission rejected due to a tip 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.gg/SponsorBlock or matrix.to/#/#sponsor:ajay.app so we can further help you? "
|
||||
+ `Your userID is ${warnUser04Hash}.`;
|
||||
assert.strictEqual(errorMessage, expected);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
assert.strictEqual(res.status, 403);
|
||||
const errorMessage = res.data;
|
||||
const expected = "Submission rejected due to a tip 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.gg/SponsorBlock or matrix.to/#/#sponsor:ajay.app so we can further help you? "
|
||||
+ `Your userID is ${users.u04.public}.`;
|
||||
assert.strictEqual(errorMessage, expected);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,199 +3,329 @@ import { db } from "../../src/databases/databases";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import assert from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
import { usersForSuite } from "../utils/randomUsers";
|
||||
|
||||
describe("postWarning", () => {
|
||||
// constants
|
||||
const endpoint = "/api/warnUser";
|
||||
const getWarning = (userID: string, type = 0) => db.prepare("get", `SELECT "userID", "issueTime", "issuerUserID", enabled, "reason" FROM warnings WHERE "userID" = ? AND "type" = ?`, [userID, type]);
|
||||
const getWarning = (userID: string, type = 0) => db.prepare("all", `SELECT * FROM warnings WHERE "userID" = ? AND "type" = ? ORDER BY "issueTime" ASC`, [userID, type]);
|
||||
|
||||
const warneduserOneID = "warning-0";
|
||||
const warnedUserTwoID = "warning-1";
|
||||
const warnedUserOnePublicID = getHash(warneduserOneID);
|
||||
const warnedUserTwoPublicID = getHash(warnedUserTwoID);
|
||||
const warningVipOne = "warning-vip-1";
|
||||
const warningVipTwo = "warning-vip-2";
|
||||
const nonVipUser = "warning-non-vip";
|
||||
const users = usersForSuite("postWarning");
|
||||
|
||||
before(async () => {
|
||||
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES (?)`, [getHash(warningVipOne)]);
|
||||
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES (?)`, [getHash(warningVipTwo)]);
|
||||
const insertWarningQuery = 'INSERT INTO warnings ("userID", "issuerUserID", "enabled", "reason", "issueTime") VALUES(?, ?, ?, ?, ?)';
|
||||
const insertWarningQueryWithDisableTime = 'INSERT INTO warnings ("userID", "issuerUserID", "enabled", "reason", "issueTime", "disableTime") VALUES(?, ?, ?, ?, ?, ?)';
|
||||
const HOUR = 60 * 60 * 1000;
|
||||
|
||||
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES (?)`, [users.vip1.public]);
|
||||
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES (?)`, [users.vip2.public]);
|
||||
|
||||
await db.prepare("run", insertWarningQuery, [users.u1.public, users.vip1.public, 1, "warn reason 1", (Date.now() - 24 * HOUR)]); // 24 hours is much past the edit deadline
|
||||
await db.prepare("run", insertWarningQuery, [users.u2.public, users.vip1.public, 1, "warn reason 2", (Date.now() - 24 * HOUR)]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u3.public, users.vip1.public, 1, "warn reason 3", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u4.public, users.vip1.public, 1, "warn reason 4", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u6.public, users.vip1.public, 1, "warn reason 6", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u9.public, users.vip1.public, 0, "warn reason 9", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u10.public, users.vip1.public, 1, "warn reason 10", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u11.public, users.vip1.public, 1, "warn reason 11", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u12.public, users.vip1.public, 0, "warn reason 12", Date.now()]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u13.public, users.vip1.public, 0, "warn reason 13", Date.now()]);
|
||||
await db.prepare("run", insertWarningQueryWithDisableTime, [users.u14.public, users.vip1.public, 0, "warn reason 14", 123, 12345]);
|
||||
await db.prepare("run", insertWarningQuery, [users.u14.public, users.vip1.public, 1, "another reason 14", Date.now()]);
|
||||
});
|
||||
|
||||
it("Should be able to create warning if vip (exp 200)", (done) => {
|
||||
it("Should be able to create warning if vip (exp 200)", async () => {
|
||||
const json = {
|
||||
issuerUserID: warningVipOne,
|
||||
userID: warnedUserOnePublicID,
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u0.public,
|
||||
reason: "warning-reason-0"
|
||||
};
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1,
|
||||
issuerUserID: getHash(json.issuerUserID),
|
||||
reason: json.reason,
|
||||
};
|
||||
assert.ok(partialDeepEquals(row, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1,
|
||||
issuerUserID: getHash(json.issuerUserID),
|
||||
reason: json.reason,
|
||||
};
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
});
|
||||
|
||||
it("Should be not be able to create a duplicate warning if vip", (done) => {
|
||||
it("Should be not be able to edit a warning if past deadline and same vip", async () => {
|
||||
const json = {
|
||||
issuerUserID: warningVipOne,
|
||||
userID: warnedUserOnePublicID,
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u1.public,
|
||||
reason: "edited reason 1",
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 409);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1,
|
||||
issuerUserID: getHash(json.issuerUserID),
|
||||
};
|
||||
assert.ok(partialDeepEquals(row, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 409);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1,
|
||||
issuerUserID: users.vip1.public,
|
||||
};
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
});
|
||||
|
||||
it("Should be able to remove warning if vip", (done) => {
|
||||
it("Should be not be able to edit a warning if past deadline and different vip", async () => {
|
||||
const json = {
|
||||
issuerUserID: warningVipOne,
|
||||
userID: warnedUserOnePublicID,
|
||||
issuerUserID: users.vip2.private,
|
||||
userID: users.u2.public,
|
||||
reason: "edited reason 2",
|
||||
};
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 409);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1,
|
||||
issuerUserID: users.vip1.public,
|
||||
};
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
});
|
||||
|
||||
it("Should be able to remove warning if same vip as issuer", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u3.public,
|
||||
enabled: false
|
||||
};
|
||||
const beforeTime = Date.now();
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 0
|
||||
};
|
||||
assert.ok(partialDeepEquals(row, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not be able to create warning if not vip (exp 403)", (done) => {
|
||||
const json = {
|
||||
issuerUserID: nonVipUser,
|
||||
userID: warnedUserOnePublicID,
|
||||
const res = await client.post(endpoint, json);
|
||||
const afterTime = Date.now();
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 0
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
// check disableTime
|
||||
assert.ok(row[0].disableTime >= beforeTime && row[0].disableTime <= afterTime, "expected disableTime to be somewhere between execution start and end");
|
||||
});
|
||||
|
||||
it("Should return 400 if missing body", (done) => {
|
||||
client.post(endpoint, {})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should re-enable disabled warning", (done) => {
|
||||
it("Should be able to remove warning if not the same vip as issuer", async () => {
|
||||
const json = {
|
||||
issuerUserID: warningVipOne,
|
||||
userID: warnedUserOnePublicID,
|
||||
enabled: true
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const data = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1
|
||||
};
|
||||
assert.ok(partialDeepEquals(data, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to remove your own warning", (done) => {
|
||||
const json = {
|
||||
userID: warneduserOneID,
|
||||
issuerUserID: users.vip2.private,
|
||||
userID: users.u4.public,
|
||||
enabled: false
|
||||
};
|
||||
const beforeTime = Date.now();
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const data = await getWarning(warnedUserOnePublicID);
|
||||
const expected = {
|
||||
enabled: 0
|
||||
};
|
||||
assert.ok(partialDeepEquals(data, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
const res = await client.post(endpoint, json);
|
||||
const afterTime = Date.now();
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 0
|
||||
};
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
// check disableTime
|
||||
assert.ok(row[0].disableTime >= beforeTime && row[0].disableTime <= afterTime, "expected disableTime to be somewhere between execution start and end");
|
||||
});
|
||||
|
||||
it("Should not be able to add your own warning", (done) => {
|
||||
it("Should not be able to create warning if not vip (exp 403)", async () => {
|
||||
const json = {
|
||||
userID: warneduserOneID,
|
||||
issuerUserID: users.nonvip.private,
|
||||
userID: users.u5.public,
|
||||
reason: "warn reason 5",
|
||||
};
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 403);
|
||||
});
|
||||
|
||||
it("Should return 400 if missing body", async () => {
|
||||
const res = await client.post(endpoint, {});
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
it("Should be able to remove your own warning", async () => {
|
||||
const json = {
|
||||
userID: users.u6.private,
|
||||
enabled: false
|
||||
};
|
||||
const beforeTime = Date.now();
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
const afterTime = Date.now();
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(users.u6.public);
|
||||
const expected = {
|
||||
enabled: 0
|
||||
};
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
// check disableTime
|
||||
assert.ok(row[0].disableTime >= beforeTime && row[0].disableTime <= afterTime, "expected disableTime to be somewhere between execution start and end");
|
||||
});
|
||||
|
||||
it("Should not be able to add your own warning", async () => {
|
||||
const json = {
|
||||
userID: users.u7.private,
|
||||
enabled: true,
|
||||
reason: "warn reason 7",
|
||||
};
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 403);
|
||||
const data = await getWarning(users.u7.public);
|
||||
assert.equal(data.length, 0);
|
||||
});
|
||||
|
||||
it("Should not be able to warn a user without reason", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u8.public,
|
||||
enabled: true
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
const data = await getWarning(warnedUserOnePublicID);
|
||||
const expected = {
|
||||
enabled: 0
|
||||
};
|
||||
assert.ok(partialDeepEquals(data, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
it("Should not be able to warn a user without reason", (done) => {
|
||||
it("Should not be able to re-warn a user without reason", async () => {
|
||||
const json = {
|
||||
issuerUserID: warningVipOne,
|
||||
userID: warnedUserTwoPublicID,
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u9.public,
|
||||
enabled: true
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
it("Should be able to re-warn a user without reason", (done) => {
|
||||
it("Should be able to edit a warning if within deadline and same vip", async () => {
|
||||
const json = {
|
||||
issuerUserID: warningVipOne,
|
||||
userID: warnedUserOnePublicID,
|
||||
enabled: true
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u10.public,
|
||||
enabled: true,
|
||||
reason: "edited reason 10",
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const data = await getWarning(warnedUserOnePublicID);
|
||||
const expected = {
|
||||
enabled: 1
|
||||
};
|
||||
assert.ok(partialDeepEquals(data, expected));
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: json.reason,
|
||||
};
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
});
|
||||
|
||||
it("Should not be able to edit a warning if within deadline and different vip", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip2.private,
|
||||
userID: users.u11.public,
|
||||
enabled: true,
|
||||
reason: "edited reason 11",
|
||||
};
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 409);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = {
|
||||
enabled: 1,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: "warn reason 11",
|
||||
};
|
||||
assert.equal(row.length, 1);
|
||||
assert.ok(partialDeepEquals(row[0], expected));
|
||||
});
|
||||
|
||||
it("Should be able to warn a previously warned user again (same vip)", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip1.private,
|
||||
userID: users.u12.public,
|
||||
enabled: true,
|
||||
reason: "new reason 12",
|
||||
};
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = [
|
||||
{
|
||||
enabled: 0,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: "warn reason 12",
|
||||
},
|
||||
{
|
||||
enabled: 1,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: "new reason 12",
|
||||
}
|
||||
];
|
||||
assert.equal(row.length, 2);
|
||||
assert.ok(partialDeepEquals(row[0], expected[0]), "warning 1");
|
||||
assert.ok(partialDeepEquals(row[1], expected[1]), "warning 2");
|
||||
});
|
||||
|
||||
it("Should be able to warn a previously warned user again (different vip)", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip2.private,
|
||||
userID: users.u13.public,
|
||||
enabled: true,
|
||||
reason: "new reason 13",
|
||||
};
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = [
|
||||
{
|
||||
enabled: 0,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: "warn reason 13",
|
||||
},
|
||||
{
|
||||
enabled: 1,
|
||||
issuerUserID: users.vip2.public,
|
||||
reason: "new reason 13",
|
||||
}
|
||||
];
|
||||
assert.equal(row.length, 2);
|
||||
assert.ok(partialDeepEquals(row[0], expected[0]), "warning 1");
|
||||
assert.ok(partialDeepEquals(row[1], expected[1]), "warning 2");
|
||||
});
|
||||
|
||||
it("Disabling a warning should only set disableTime for the active warning", async () => {
|
||||
const json = {
|
||||
issuerUserID: users.vip2.private,
|
||||
userID: users.u14.public,
|
||||
enabled: false,
|
||||
};
|
||||
const beforeTime = Date.now();
|
||||
|
||||
const res = await client.post(endpoint, json);
|
||||
const afterTime = Date.now();
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getWarning(json.userID);
|
||||
const expected = [
|
||||
{
|
||||
enabled: 0,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: "warn reason 14",
|
||||
disableTime: 12345,
|
||||
},
|
||||
{
|
||||
enabled: 0,
|
||||
issuerUserID: users.vip1.public,
|
||||
reason: "another reason 14",
|
||||
}
|
||||
];
|
||||
assert.equal(row.length, 2);
|
||||
assert.ok(partialDeepEquals(row[0], expected[0]), "warning 1");
|
||||
assert.ok(partialDeepEquals(row[1], expected[1]), "warning 2");
|
||||
// check disableTime
|
||||
assert.ok(row[1].disableTime >= beforeTime && row[1].disableTime <= afterTime, "expected disableTime to be somewhere between execution start and end");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,44 +9,32 @@ const randKey2 = genRandom(16);
|
||||
const randKey3 = genRandom();
|
||||
const randValue3 = genRandom();
|
||||
|
||||
const redisGetCheck = (key: string, expected: string | null, done: Mocha.Done): Promise<void> =>
|
||||
redis.get(key)
|
||||
.then(res => {
|
||||
assert.strictEqual(res, expected);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
|
||||
describe("redis test", function() {
|
||||
before(async function() {
|
||||
if (!config.redis?.enabled) this.skip();
|
||||
await redis.set(randKey1, randValue1);
|
||||
});
|
||||
it("Should get stored value", (done) => {
|
||||
redisGetCheck(randKey1, randValue1, done);
|
||||
it("Should get stored value", async () => {
|
||||
const res = await redis.get(randKey1);
|
||||
assert.strictEqual(res, randValue1);
|
||||
});
|
||||
it("Should not be able to get not stored value", (done) => {
|
||||
redis.get(randKey2)
|
||||
.then(res => {
|
||||
if (res) done("Value should not be found");
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
it("Should not be able to get not stored value", async () => {
|
||||
const res = await redis.get(randKey2);
|
||||
assert.strictEqual(res, null, "Value should not be found");
|
||||
});
|
||||
it("Should be able to delete stored value", (done) => {
|
||||
redis.del(randKey1)
|
||||
.catch(err => done(err))
|
||||
.then(() => redisGetCheck(randKey1, null, done));
|
||||
it("Should be able to delete stored value", async () => {
|
||||
await redis.del(randKey1);
|
||||
const res = await redis.get(randKey1);
|
||||
assert.strictEqual(res, null, "Deleted key should not be found");
|
||||
});
|
||||
it("Should be able to set expiring value", (done) => {
|
||||
redis.setEx(randKey3, 8400, randValue3)
|
||||
.catch(err => done(err))
|
||||
.then(() => redisGetCheck(randKey3, randValue3, done));
|
||||
it("Should be able to set expiring value", async () => {
|
||||
await redis.setEx(randKey3, 8400, randValue3);
|
||||
const res = await redis.get(randKey3);
|
||||
assert.strictEqual(res, randValue3);
|
||||
});
|
||||
it("Should continue when undefined value is fetched", (done) => {
|
||||
it("Should continue when undefined value is fetched", async () => {
|
||||
const undefkey = `undefined.${genRandom()}`;
|
||||
redis.get(undefkey)
|
||||
.then(result => {
|
||||
assert.ok(!result); // result should be falsy
|
||||
done();
|
||||
});
|
||||
const res = await redis.get(undefkey);
|
||||
assert.strictEqual(res, null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -56,12 +56,11 @@ function wellFormatUserName(userName: string) {
|
||||
return userName.replace(/[\u0000-\u001F\u007F-\u009F]/g, "");
|
||||
}
|
||||
|
||||
async function testUserNameChangelog(userID: string, newUserName: string, oldUserName: string, byAdmin: boolean, done: Mocha.Done) {
|
||||
async function testUserNameChangelog(userID: string, newUserName: string, oldUserName: string, byAdmin: boolean) {
|
||||
const log = await getLastLogUserNameChange(userID);
|
||||
assert.strictEqual(newUserName, log.newUserName);
|
||||
assert.strictEqual(oldUserName, log.oldUserName);
|
||||
assert.strictEqual(byAdmin, Boolean(log.updatedByAdmin));
|
||||
return done();
|
||||
}
|
||||
|
||||
const endpoint = "/api/setUsername";
|
||||
@@ -111,147 +110,104 @@ describe("setUsername", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("Should be able to set username that has never been set", (done) => {
|
||||
postSetUserName(user00PrivateUserID, username00)
|
||||
.then(async res => {
|
||||
const usernameInfo = await getUsernameInfo(getHash(user00PrivateUserID));
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(usernameInfo.userName, username00);
|
||||
assert.notStrictEqual(usernameInfo.locked, 1, "username should not be locked");
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
it("Should be able to set username that has never been set", async () => {
|
||||
const res = await postSetUserName(user00PrivateUserID, username00);
|
||||
const usernameInfo = await getUsernameInfo(getHash(user00PrivateUserID));
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(usernameInfo.userName, username00);
|
||||
assert.notStrictEqual(usernameInfo.locked, 1, "username should not be locked");
|
||||
});
|
||||
|
||||
it("Should return 200", (done) => {
|
||||
it("Should return 200", async () => {
|
||||
const username = "Changed%20Username";
|
||||
postSetUserName(user01PrivateUserID, username)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
testUserNameChangelog(user01PrivateUserID, username, username01, false, done);
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
const res = await postSetUserName(user01PrivateUserID, username);
|
||||
assert.strictEqual(res.status, 200);
|
||||
await testUserNameChangelog(user01PrivateUserID, username, username01, false);
|
||||
});
|
||||
|
||||
it('Should return 400 for missing param "userID"', (done) => {
|
||||
client({
|
||||
it('Should return 400 for missing param "userID"', async () => {
|
||||
const res = await client({
|
||||
method: "POST",
|
||||
url: endpoint,
|
||||
data: {
|
||||
userName: "MyUsername"
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
it('Should return 400 for missing param "username"', (done) => {
|
||||
client({
|
||||
it('Should return 400 for missing param "username"', async () => {
|
||||
const res = await client({
|
||||
method: "POST",
|
||||
url: endpoint,
|
||||
data: {
|
||||
userID: "test"
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
it('Should return 400 for "username" longer then 64 characters', (done) => {
|
||||
it('Should return 400 for "username" longer then 64 characters', async () => {
|
||||
const username65 = "0000000000000000000000000000000000000000000000000000000000000000X";
|
||||
postSetUserName("test", username65)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
const res = await postSetUserName("test", username65);
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
|
||||
it('Should not change username if it contains "discord"', (done) => {
|
||||
it('Should not change username if it contains "discord"', async () => {
|
||||
const newUsername = "discord.me";
|
||||
postSetUserName(user02PrivateUserID, newUsername)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const userNameInfo = await getUsernameInfo(getHash(user02PrivateUserID));
|
||||
assert.notStrictEqual(userNameInfo.userName, newUsername);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
const res = await postSetUserName(user02PrivateUserID, newUsername);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const userNameInfo = await getUsernameInfo(getHash(user02PrivateUserID));
|
||||
assert.notStrictEqual(userNameInfo.userName, newUsername);
|
||||
});
|
||||
|
||||
it("Should be able to change username", (done) => {
|
||||
it("Should be able to change username", async () => {
|
||||
const newUsername = "newUsername";
|
||||
postSetUserName(user03PrivateUserID, newUsername)
|
||||
.then(async () => {
|
||||
const usernameInfo = await getUsernameInfo(getHash(user03PrivateUserID));
|
||||
assert.strictEqual(usernameInfo.userName, newUsername, "Username should change");
|
||||
assert.notStrictEqual(usernameInfo.locked, 1, "Username should not be locked");
|
||||
testUserNameChangelog(user03PrivateUserID, newUsername, username03, false, done);
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
await postSetUserName(user03PrivateUserID, newUsername);
|
||||
const usernameInfo = await getUsernameInfo(getHash(user03PrivateUserID));
|
||||
assert.strictEqual(usernameInfo.userName, newUsername, "Username should change");
|
||||
assert.notStrictEqual(usernameInfo.locked, 1, "Username should not be locked");
|
||||
await testUserNameChangelog(user03PrivateUserID, newUsername, username03, false);
|
||||
});
|
||||
|
||||
it("Should not be able to change locked username", (done) => {
|
||||
it("Should not be able to change locked username", async () => {
|
||||
const newUsername = "newUsername";
|
||||
postSetUserName(user04PrivateUserID, newUsername)
|
||||
.then(async () => {
|
||||
const usernameInfo = await getUsernameInfo(getHash(user04PrivateUserID));
|
||||
assert.notStrictEqual(usernameInfo.userName, newUsername, "Username should not be changed");
|
||||
assert.strictEqual(usernameInfo.locked, 1, "username should be locked");
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
await postSetUserName(user04PrivateUserID, newUsername);
|
||||
const usernameInfo = await getUsernameInfo(getHash(user04PrivateUserID));
|
||||
assert.notStrictEqual(usernameInfo.userName, newUsername, "Username should not be changed");
|
||||
assert.strictEqual(usernameInfo.locked, 1, "username should be locked");
|
||||
});
|
||||
|
||||
it("Should filter out unicode control characters", (done) => {
|
||||
it("Should filter out unicode control characters", async () => {
|
||||
const newUsername = "This\nUsername+has\tInvalid+Characters";
|
||||
postSetUserName(user05PrivateUserID, newUsername)
|
||||
.then(async () => {
|
||||
const usernameInfo = await getUsernameInfo(getHash(user05PrivateUserID));
|
||||
assert.notStrictEqual(usernameInfo.userName, newUsername, "Username should not contain control characters");
|
||||
testUserNameChangelog(user05PrivateUserID, wellFormatUserName(newUsername), username05, false, done);
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
await postSetUserName(user05PrivateUserID, newUsername);
|
||||
const usernameInfo = await getUsernameInfo(getHash(user05PrivateUserID));
|
||||
assert.notStrictEqual(usernameInfo.userName, newUsername, "Username should not contain control characters");
|
||||
await testUserNameChangelog(user05PrivateUserID, wellFormatUserName(newUsername), username05, false);
|
||||
});
|
||||
|
||||
it("Incorrect adminUserID should return 403", (done) => {
|
||||
it("Incorrect adminUserID should return 403", async () => {
|
||||
const newUsername = "New Username";
|
||||
postSetUserNameAdmin(getHash(user06PrivateUserID), newUsername,"invalidAdminID")
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
const res = await postSetUserNameAdmin(getHash(user06PrivateUserID), newUsername,"invalidAdminID");
|
||||
assert.strictEqual(res.status, 403);
|
||||
});
|
||||
|
||||
it("Admin should be able to change username", (done) => {
|
||||
it("Admin should be able to change username", async () => {
|
||||
const newUsername = "New Username";
|
||||
postSetUserNameAdmin(getHash(user06PrivateUserID), newUsername, adminPrivateUserID)
|
||||
.then(async () => {
|
||||
const usernameInfo = await getUsernameInfo(getHash(user06PrivateUserID));
|
||||
assert.strictEqual(usernameInfo.userName, newUsername, "username should be changed");
|
||||
assert.strictEqual(usernameInfo.locked, 1, "Username should be locked");
|
||||
testUserNameChangelog(user06PrivateUserID, newUsername, username06, true, done);
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
await postSetUserNameAdmin(getHash(user06PrivateUserID), newUsername, adminPrivateUserID);
|
||||
const usernameInfo = await getUsernameInfo(getHash(user06PrivateUserID));
|
||||
assert.strictEqual(usernameInfo.userName, newUsername, "username should be changed");
|
||||
assert.strictEqual(usernameInfo.locked, 1, "Username should be locked");
|
||||
await testUserNameChangelog(user06PrivateUserID, newUsername, username06, true);
|
||||
});
|
||||
|
||||
it("Admin should be able to change locked username", (done) => {
|
||||
it("Admin should be able to change locked username", async () => {
|
||||
const newUsername = "New Username";
|
||||
postSetUserNameAdmin(getHash(user07PrivateUserID), newUsername, adminPrivateUserID)
|
||||
.then(async () => {
|
||||
const usernameInfo = await getUsernameInfo(getHash(user06PrivateUserID));
|
||||
assert.strictEqual(usernameInfo.userName, newUsername, "Username should be changed");
|
||||
assert.strictEqual(usernameInfo.locked, 1, "Username should be locked");
|
||||
testUserNameChangelog(user07PrivateUserID, newUsername, username07, true, done);
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
await postSetUserNameAdmin(getHash(user07PrivateUserID), newUsername, adminPrivateUserID);
|
||||
const usernameInfo = await getUsernameInfo(getHash(user06PrivateUserID));
|
||||
assert.strictEqual(usernameInfo.userName, newUsername, "Username should be changed");
|
||||
assert.strictEqual(usernameInfo.locked, 1, "Username should be locked");
|
||||
await testUserNameChangelog(user07PrivateUserID, newUsername, username07, true);
|
||||
});
|
||||
|
||||
it("Should delete existing username if new username is same as publicID", async () => {
|
||||
|
||||
@@ -59,71 +59,47 @@ describe("setUsernamePrivate tests", () => {
|
||||
before(() => sinon.stub(config, "minUserIDLength").value(USERID_LIMIT));
|
||||
after(() => sinon.restore());
|
||||
|
||||
it("Existing privateID = username under Limit should retreive successfully", (done) => {
|
||||
it("Existing privateID = username under Limit should retreive successfully", async () => {
|
||||
const privateID = preExisting_underLimit;
|
||||
hasSetUsername(getHash(privateID))
|
||||
.then((usernameInfo) => {
|
||||
assert.ok(usernameInfo);
|
||||
done();
|
||||
});
|
||||
assert.ok(await hasSetUsername(getHash(privateID)));
|
||||
});
|
||||
|
||||
it("Existing privateID = username over Limit should retreive successfully", (done) => {
|
||||
it("Existing privateID = username over Limit should retreive successfully", async () => {
|
||||
const privateID = preExisting_overLimit;
|
||||
hasSetUsername(getHash(privateID))
|
||||
.then((usernameInfo) => {
|
||||
assert.ok(usernameInfo);
|
||||
done();
|
||||
});
|
||||
assert.ok(await hasSetUsername(getHash(privateID)));
|
||||
});
|
||||
|
||||
it("Should return error if trying to set userID = username under limit", (done) => {
|
||||
it("Should return error if trying to set userID = username under limit", async () => {
|
||||
const privateID = newUser_underLimit;
|
||||
postSetUserName(privateID, privateID)
|
||||
.then(async (res) => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
const usernameInfo = await hasSetUsername(getHash(privateID));
|
||||
assert.ok(!usernameInfo);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
const res = await postSetUserName(privateID, privateID);
|
||||
assert.strictEqual(res.status, 400);
|
||||
const usernameInfo = await hasSetUsername(getHash(privateID));
|
||||
assert.ok(!usernameInfo);
|
||||
});
|
||||
|
||||
it("Should return error if trying to set username = other privateID over limit", (done) => {
|
||||
it("Should return error if trying to set username = other privateID over limit", async () => {
|
||||
const privateID = newUser_overLimit;
|
||||
postSetUserName(privateID, privateID)
|
||||
.then(async (res) => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
const usernameInfo = await hasSetUsername(getHash(privateID));
|
||||
assert.ok(!usernameInfo);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
const res = await postSetUserName(privateID, privateID);
|
||||
assert.strictEqual(res.status, 400);
|
||||
const usernameInfo = await hasSetUsername(getHash(privateID));
|
||||
assert.ok(!usernameInfo);
|
||||
});
|
||||
|
||||
it("Should return error if trying to set username = other privateID over limit", (done) => {
|
||||
it("Should return error if trying to set username = other privateID over limit", async () => {
|
||||
const privateID = otherUser;
|
||||
const otherUserPrivate = preExisting_overLimit;
|
||||
postSetUserName(privateID, otherUserPrivate)
|
||||
.then(async (res) => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
const usernameInfo = await hasSetUsername(getHash(privateID));
|
||||
assert.ok(!usernameInfo);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
const res = await postSetUserName(privateID, otherUserPrivate);
|
||||
assert.strictEqual(res.status, 400);
|
||||
const usernameInfo = await hasSetUsername(getHash(privateID));
|
||||
assert.ok(!usernameInfo);
|
||||
});
|
||||
|
||||
it("Should not return error if trying to set username = other privateID under limit", (done) => {
|
||||
it("Should not return error if trying to set username = other privateID under limit", async () => {
|
||||
const privateID = otherUser;
|
||||
const otherUserPrivate = preExisting_underLimit;
|
||||
postSetUserName(privateID, otherUserPrivate)
|
||||
.then(async (res) => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const usernameInfo = await hasSetUsername(getHash(privateID));
|
||||
assert.ok(usernameInfo);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
const res = await postSetUserName(privateID, otherUserPrivate);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const usernameInfo = await hasSetUsername(getHash(privateID));
|
||||
assert.ok(usernameInfo);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { db, privateDB } from "../../src/databases/databases";
|
||||
import { db } from "../../src/databases/databases";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import assert from "assert";
|
||||
import { Category, Service } from "../../src/types/segments.model";
|
||||
|
||||
@@ -68,191 +68,118 @@ describe("tempVIP test", function() {
|
||||
await redis.del(tempVIPKey(publicTempVIPOne));
|
||||
});
|
||||
|
||||
it("Should update db version when starting the application", () => {
|
||||
privateDB.prepare("get", "SELECT key, value FROM config where key = ?", ["version"])
|
||||
.then(row => {
|
||||
assert.ok(row.value >= 5, `Versions are not at least 5. private is ${row.value}`);
|
||||
});
|
||||
it("Should update db version when starting the application", async () => {
|
||||
const row = await privateDB.prepare("get", "SELECT key, value FROM config where key = ?", ["version"]);
|
||||
assert.ok(row.value >= 5, `Versions are not at least 5. private is ${row.value}`);
|
||||
});
|
||||
it("User should not already be temp VIP", (done) => {
|
||||
checkUserVIP(publicTempVIPOne)
|
||||
.then(result => {
|
||||
assert.ok(!result);
|
||||
})
|
||||
.then(async () => {
|
||||
const row = await privateDB.prepare("get", `SELECT * FROM "tempVipLog" WHERE "targetUserID" = ?`, [publicTempVIPOne]);
|
||||
assert.ok(!row?.enabled);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("User should not already be temp VIP", async () => {
|
||||
assert.ok(!await checkUserVIP(publicTempVIPOne));
|
||||
const row = await privateDB.prepare("get", `SELECT * FROM "tempVipLog" WHERE "targetUserID" = ?`, [publicTempVIPOne]);
|
||||
assert.ok(!row?.enabled);
|
||||
});
|
||||
it("Should be able to normal upvote as a user", (done) => {
|
||||
postVote(tempVIPOne, UUID0, 1)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID0);
|
||||
assert.strictEqual(row.votes, 1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should be able to normal upvote as a user", async () => {
|
||||
const res = await postVote(tempVIPOne, UUID0, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID0);
|
||||
assert.strictEqual(row.votes, 1);
|
||||
});
|
||||
it("Should be able to add tempVIP", (done) => {
|
||||
addTempVIP("true", permVIP1, publicTempVIPOne)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
// check redis
|
||||
const vip = await checkUserVIP(publicTempVIPOne);
|
||||
assert.strictEqual(vip, "ChannelID");
|
||||
assert.strictEqual(res.data, "Temp VIP added on channel ChannelAuthor");
|
||||
// check privateDB
|
||||
const row = await privateDB.prepare("get", `SELECT * FROM "tempVipLog" WHERE "targetUserID" = ?`, [publicTempVIPOne]);
|
||||
assert.ok(row.enabled);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should be able to add tempVIP", async () => {
|
||||
const res = await addTempVIP("true", permVIP1, publicTempVIPOne);
|
||||
assert.strictEqual(res.status, 200);
|
||||
// check redis
|
||||
const vip = await checkUserVIP(publicTempVIPOne);
|
||||
assert.strictEqual(vip, "ChannelID");
|
||||
assert.strictEqual(res.data, "Temp VIP added on channel ChannelAuthor");
|
||||
// check privateDB
|
||||
const row = await privateDB.prepare("get", `SELECT * FROM "tempVipLog" WHERE "targetUserID" = ?`, [publicTempVIPOne]);
|
||||
assert.ok(row.enabled);
|
||||
});
|
||||
it("Should be able to VIP downvote", (done) => {
|
||||
postVote(tempVIPOne, UUID0, 0)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID0);
|
||||
assert.strictEqual(row.votes, -2);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should be able to VIP downvote", async () => {
|
||||
const res = await postVote(tempVIPOne, UUID0, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID0);
|
||||
assert.strictEqual(row.votes, -2);
|
||||
});
|
||||
it("Should not be able to lock segment", (done) => {
|
||||
postVote(tempVIPOne, UUID0, 1)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID0);
|
||||
assert.strictEqual(row.votes, 1);
|
||||
assert.strictEqual(row.locked, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should not be able to lock segment", async () => {
|
||||
const res = await postVote(tempVIPOne, UUID0, 1);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID0);
|
||||
assert.strictEqual(row.votes, 1);
|
||||
assert.strictEqual(row.locked, 0);
|
||||
});
|
||||
it("Should be able to change category but not lock", (done) => {
|
||||
postVoteCategory(tempVIPOne, UUID0, "filler")
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID0);
|
||||
assert.strictEqual(row.category, "filler");
|
||||
assert.strictEqual(row.locked, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should be able to change category but not lock", async () => {
|
||||
const res = await postVoteCategory(tempVIPOne, UUID0, "filler");
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID0);
|
||||
assert.strictEqual(row.category, "filler");
|
||||
assert.strictEqual(row.locked, 0);
|
||||
});
|
||||
it("Should be able to remove tempVIP prematurely", (done) => {
|
||||
addTempVIP("false", permVIP1, publicTempVIPOne)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const vip = await checkUserVIP(publicTempVIPOne);
|
||||
assert.strictEqual(res.data, "Temp VIP removed");
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should be able to remove tempVIP prematurely", async () => {
|
||||
const res = await addTempVIP("false", permVIP1, publicTempVIPOne);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const vip = await checkUserVIP(publicTempVIPOne);
|
||||
assert.strictEqual(res.data, "Temp VIP removed");
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
});
|
||||
it("Should not be able to VIP downvote", (done) => {
|
||||
postVote(tempVIPOne, UUID1, 0)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID1);
|
||||
assert.strictEqual(row.votes, 0);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should not be able to VIP downvote", async () => {
|
||||
const res = await postVote(tempVIPOne, UUID1, 0);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID1);
|
||||
assert.strictEqual(row.votes, 0);
|
||||
});
|
||||
it("Should not be able to VIP change category", (done) => {
|
||||
postVoteCategory(tempVIPOne, UUID1, "filler")
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID1);
|
||||
assert.strictEqual(row.category, "sponsor");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should not be able to VIP change category", async () => {
|
||||
const res = await postVoteCategory(tempVIPOne, UUID1, "filler");
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await getSegment(UUID1);
|
||||
assert.strictEqual(row.category, "sponsor");
|
||||
});
|
||||
// error code testing
|
||||
it("Should be able to add tempVIP after removal", (done) => {
|
||||
addTempVIP("true", permVIP1, publicTempVIPOne)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const vip = await checkUserVIP(publicTempVIPOne);
|
||||
assert.strictEqual(vip, "ChannelID");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should be able to add tempVIP after removal", async () => {
|
||||
const res = await addTempVIP("true", permVIP1, publicTempVIPOne);
|
||||
assert.strictEqual(res.status, 200);
|
||||
const vip = await checkUserVIP(publicTempVIPOne);
|
||||
assert.strictEqual(vip, "ChannelID");
|
||||
});
|
||||
it("Should not be able to add VIP without existing VIP (403)", (done) => {
|
||||
it("Should not be able to add VIP without existing VIP (403)", async () => {
|
||||
const privateID = "non-vip-privateid";
|
||||
addTempVIP("true", privateID, publicTempVIPOne)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
const vip = await checkUserVIP(getHash(privateID) as HashedUserID);
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
const res = await addTempVIP("true", privateID, publicTempVIPOne);
|
||||
assert.strictEqual(res.status, 403);
|
||||
const vip = await checkUserVIP(getHash(privateID) as HashedUserID);
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
});
|
||||
it("Should not be able to add permanant VIP as temporary VIP (409)", (done) => {
|
||||
addTempVIP("true", permVIP1, publicPermVIP2)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 409);
|
||||
const vip = await checkUserVIP(publicPermVIP2);
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should not be able to add permanant VIP as temporary VIP (409)", async () => {
|
||||
const res = await addTempVIP("true", permVIP1, publicPermVIP2);
|
||||
assert.strictEqual(res.status, 409);
|
||||
const vip = await checkUserVIP(publicPermVIP2);
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
});
|
||||
it("Temp VIP should not be able to add another Temp VIP (403)", (done) => {
|
||||
it("Temp VIP should not be able to add another Temp VIP (403)", async () => {
|
||||
const privateID = "non-vip-privateid";
|
||||
const publicID = getHash(privateID) as HashedUserID;
|
||||
addTempVIP("true", tempVIPOne, publicID)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
const vip = await checkUserVIP(publicID);
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
const res = await addTempVIP("true", tempVIPOne, publicID);
|
||||
assert.strictEqual(res.status, 403);
|
||||
const vip = await checkUserVIP(publicID);
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
});
|
||||
// error 40X testing
|
||||
it("Should return 404 with invalid videoID", (done) => {
|
||||
it("Should return 404 with invalid videoID", async () => {
|
||||
const privateID = "non-vip-privateid";
|
||||
const publicID = getHash(privateID) as HashedUserID;
|
||||
addTempVIP("true", permVIP1, publicID, "knownWrongID")
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 404);
|
||||
const vip = await checkUserVIP(publicID);
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
const res = await addTempVIP("true", permVIP1, publicID, "knownWrongID");
|
||||
assert.strictEqual(res.status, 404);
|
||||
const vip = await checkUserVIP(publicID);
|
||||
assert.ok(!vip, "Should be no listed channelID");
|
||||
});
|
||||
it("Should return 400 with invalid userID", (done) => {
|
||||
addTempVIP("true", permVIP1, "" as HashedUserID, "knownWrongID")
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should return 400 with invalid userID", async () => {
|
||||
const res = await addTempVIP("true", permVIP1, "" as HashedUserID, "knownWrongID");
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
it("Should return 400 with invalid adminUserID", (done) => {
|
||||
addTempVIP("true", "", publicTempVIPOne)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should return 400 with invalid adminUserID", async () => {
|
||||
const res = await addTempVIP("true", "", publicTempVIPOne);
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
it("Should return 400 with invalid channelID", (done) => {
|
||||
addTempVIP("true", permVIP1, publicTempVIPOne, "")
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
it("Should return 400 with invalid channelID", async () => {
|
||||
const res = await addTempVIP("true", permVIP1, publicTempVIPOne, "");
|
||||
assert.strictEqual(res.status, 400);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,32 +16,24 @@ describe("tokenUtils test", function() {
|
||||
mock.onGet(/identity/).reply(200, patreon.activeIdentity);
|
||||
});
|
||||
|
||||
it("Should be able to create patreon token", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
tokenUtils.createAndSaveToken(tokenUtils.TokenType.patreon, "test_code").then((licenseKey) => {
|
||||
assert.ok(validateToken(licenseKey[0]));
|
||||
done();
|
||||
});
|
||||
it("Should be able to create patreon token", async function () {
|
||||
if (!config?.patreon) return this.skip();
|
||||
const licenseKey = await tokenUtils.createAndSaveToken(tokenUtils.TokenType.patreon, "test_code");
|
||||
assert.ok(validateToken(licenseKey[0]));
|
||||
});
|
||||
it("Should be able to create local token", (done) => {
|
||||
tokenUtils.createAndSaveToken(tokenUtils.TokenType.local).then((licenseKey) => {
|
||||
assert.ok(validateToken(licenseKey[0]));
|
||||
done();
|
||||
});
|
||||
it("Should be able to create local token", async () => {
|
||||
const licenseKey = await tokenUtils.createAndSaveToken(tokenUtils.TokenType.local);
|
||||
assert.ok(validateToken(licenseKey[0]));
|
||||
});
|
||||
it("Should be able to get patreon identity", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
tokenUtils.getPatreonIdentity("fake_access_token").then((result) => {
|
||||
assert.deepEqual(result, patreon.activeIdentity);
|
||||
done();
|
||||
});
|
||||
it("Should be able to get patreon identity", async function () {
|
||||
if (!config?.patreon) return this.skip();
|
||||
const result = await tokenUtils.getPatreonIdentity("fake_access_token");
|
||||
assert.deepEqual(result, patreon.activeIdentity);
|
||||
});
|
||||
it("Should be able to refresh token", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
tokenUtils.refreshToken(tokenUtils.TokenType.patreon, "fake-licence-Key", "fake_refresh_token").then((result) => {
|
||||
assert.strictEqual(result, true);
|
||||
done();
|
||||
});
|
||||
it("Should be able to refresh token", async function () {
|
||||
if (!config?.patreon) return this.skip();
|
||||
const result = await tokenUtils.refreshToken(tokenUtils.TokenType.patreon, "fake-licence-Key", "fake_refresh_token");
|
||||
assert.strictEqual(result, true);
|
||||
});
|
||||
|
||||
after(function () {
|
||||
@@ -56,20 +48,16 @@ describe("tokenUtils failing tests", function() {
|
||||
mock.onGet(/identity/).reply(204, patreon.activeIdentity);
|
||||
});
|
||||
|
||||
it("Should fail if patreon is not correctly stubbed", function (done) {
|
||||
tokenUtils.createAndSaveToken(tokenUtils.TokenType.patreon, "test_code").then((licenseKey) => {
|
||||
assert.strictEqual(licenseKey, null);
|
||||
done();
|
||||
});
|
||||
it("Should fail if patreon is not correctly stubbed", async () => {
|
||||
const licenseKey = await tokenUtils.createAndSaveToken(tokenUtils.TokenType.patreon, "test_code");
|
||||
assert.strictEqual(licenseKey, null);
|
||||
});
|
||||
it("Should fail if token type is invalid", (done) => {
|
||||
tokenUtils.createAndSaveToken("invalidTokenType" as tokenUtils.TokenType).then((licenseKey) => {
|
||||
assert.strictEqual(licenseKey, null);
|
||||
done();
|
||||
});
|
||||
it("Should fail if token type is invalid", async () => {
|
||||
const licenseKey = await tokenUtils.createAndSaveToken("invalidTokenType" as tokenUtils.TokenType);
|
||||
assert.strictEqual(licenseKey, null);
|
||||
});
|
||||
|
||||
after(function () {
|
||||
mock.restore();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -59,12 +59,13 @@ async function init() {
|
||||
mocha.run((failures) => {
|
||||
mockServer.close();
|
||||
server.close();
|
||||
redis.quit();
|
||||
process.exitCode = failures ? 1 : 0; // exit with non-zero status if there were failures
|
||||
process.exit();
|
||||
redis.quit().finally(() => {
|
||||
process.exitCode = failures ? 1 : 0; // exit with non-zero status if there were failures
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
void init();
|
||||
|
||||
51
test/utils/randomUsers.ts
Normal file
51
test/utils/randomUsers.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { HashedUserID, UserID } from "../../src/types/user.model";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import { genRandom } from "./getRandom";
|
||||
|
||||
export interface TestUser {
|
||||
private: UserID,
|
||||
public: HashedUserID,
|
||||
}
|
||||
|
||||
interface InternalTestUsers {
|
||||
map: Map<any, TestUser>,
|
||||
suiteName: string,
|
||||
}
|
||||
|
||||
const userMapHandler = {
|
||||
get(target: InternalTestUsers, property: string): TestUser {
|
||||
const suiteName = Reflect.get(target, "suiteName");
|
||||
const map = Reflect.get(target, "map");
|
||||
let user = map.get(property);
|
||||
if (user !== undefined) {
|
||||
return user;
|
||||
}
|
||||
|
||||
const priv = `${suiteName}-${property}-${genRandom}` as UserID;
|
||||
user = {
|
||||
private: priv,
|
||||
public: getHash(priv),
|
||||
};
|
||||
map.set(property, user);
|
||||
return user;
|
||||
},
|
||||
set: () => false, // nope
|
||||
deleteProperty: () => false, // nope
|
||||
has: () => true, // yep
|
||||
defineProperty: () => false, // nope
|
||||
preventExtensions: () => false, // nope
|
||||
setPrototypeOf: () => false, // nope
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an object that generates test private/public userID pairs on demand
|
||||
*
|
||||
* @param suiteName the suite name, used as a prefix for the private userID
|
||||
* @returns a proxy that generates & caches private/public userID pairs for each property access
|
||||
*/
|
||||
export function usersForSuite(suiteName: string): Record<any, TestUser> {
|
||||
return new Proxy({
|
||||
map: new Map<any, TestUser>(),
|
||||
suiteName,
|
||||
}, userMapHandler) as unknown as Record<any, TestUser>;
|
||||
}
|
||||
4
tsconfig.eslint.json
Normal file
4
tsconfig.eslint.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["**/*"],
|
||||
}
|
||||
Reference in New Issue
Block a user