From 5ad7c6a3ba1f5e3202ab9f1ad03aebb51bf236f8 Mon Sep 17 00:00:00 2001 From: Michael C Date: Fri, 6 Aug 2021 00:14:54 -0400 Subject: [PATCH] catch all error in endpoint --- src/app.ts | 2 +- src/routes/getUserInfo.ts | 60 +++++++++++++++++++----------------- test/cases/getSegmentInfo.ts | 2 +- test/cases/getUserInfo.ts | 33 +++++++++++++++++++- 4 files changed, 65 insertions(+), 32 deletions(-) diff --git a/src/app.ts b/src/app.ts index 827f767..5e97f05 100644 --- a/src/app.ts +++ b/src/app.ts @@ -7,7 +7,7 @@ import {postWarning} from "./routes/postWarning"; import {getIsUserVIP} from "./routes/getIsUserVIP"; import {deleteLockCategoriesEndpoint} from "./routes/deleteLockCategories"; import {postLockCategories} from "./routes/postLockCategories"; -import {getUserInfo} from "./routes/getUserInfo"; +import {endpoint as getUserInfo} from "./routes/getUserInfo"; import {getDaysSavedFormatted} from "./routes/getDaysSavedFormatted"; import {getTotalStats} from "./routes/getTotalStats"; import {getTopUsers} from "./routes/getTopUsers"; diff --git a/src/routes/getUserInfo.ts b/src/routes/getUserInfo.ts index ac2b925..594ef57 100644 --- a/src/routes/getUserInfo.ts +++ b/src/routes/getUserInfo.ts @@ -8,23 +8,19 @@ import { getReputation } from "../utils/reputation"; import { SegmentUUID } from "../types/segments.model"; async function dbGetSubmittedSegmentSummary(userID: HashedUserID): Promise<{ minutesSaved: number, segmentCount: number }> { - try { - const row = await db.prepare("get", `SELECT SUM((("endTime" - "startTime") / 60) * "views") as "minutesSaved", - count(*) as "segmentCount" FROM "sponsorTimes" - WHERE "userID" = ? AND "votes" > -2 AND "shadowHidden" != 1`, [userID]); - if (row.minutesSaved != null) { - return { - minutesSaved: row.minutesSaved, - segmentCount: row.segmentCount, - }; - } else { - return { - minutesSaved: 0, - segmentCount: 0, - }; - } - } catch (err) { - return null; + const row = await db.prepare("get", `SELECT SUM((("endTime" - "startTime") / 60) * "views") as "minutesSaved", + count(*) as "segmentCount" FROM "sponsorTimes" + WHERE "userID" = ? AND "votes" > -2 AND "shadowHidden" != 1`, [userID]); + if (row.minutesSaved != null) { + return { + minutesSaved: row.minutesSaved, + segmentCount: row.segmentCount, + }; + } else { + return { + minutesSaved: 0, + segmentCount: 0, + }; } } @@ -134,7 +130,7 @@ const dbGetValue = async (userID: HashedUserID, property: string): Promise { +async function getUserInfo(req: Request, res: Response): Promise { const userID = req.query.userID as UserID; const hashedUserID: HashedUserID = userID ? getHash(userID) : req.query.publicUserID as HashedUserID; const defaultProperties: string[] = ["userID", "userName", "minutesSaved", "segmentCount", "ignoredSegmentCount", @@ -149,7 +145,7 @@ export async function getUserInfo(req: Request, res: Response): Promise allProperties.includes(param)); @@ -165,15 +161,21 @@ export async function getUserInfo(req: Request, res: Response): Promise; - if (segmentsSummary) { - for (const property of paramValues) { - responseObj[property] = await dbGetValue(hashedUserID, property); - } - // add minutesSaved and segmentCount after to avoid getting overwritten - if (paramValues.includes("minutesSaved")) { responseObj["minutesSaved"] = segmentsSummary.minutesSaved; } - if (paramValues.includes("segmentCount")) responseObj["segmentCount"] = segmentsSummary.segmentCount; - res.send(responseObj); - } else { - return res.sendStatus(404); + for (const property of paramValues) { + responseObj[property] = await dbGetValue(hashedUserID, property); } + // add minutesSaved and segmentCount after to avoid getting overwritten + if (paramValues.includes("minutesSaved")) { responseObj["minutesSaved"] = segmentsSummary.minutesSaved; } + if (paramValues.includes("segmentCount")) responseObj["segmentCount"] = segmentsSummary.segmentCount; + return res.send(responseObj); } + +export async function endpoint(req: Request, res: Response): Promise { + try { + return await getUserInfo(req, res); + } catch (err) { + if (err instanceof SyntaxError) { // catch JSON.parse error + return res.status(400).send("Invalid values JSON"); + } else return res.sendStatus(500); + } +} \ No newline at end of file diff --git a/test/cases/getSegmentInfo.ts b/test/cases/getSegmentInfo.ts index 20545f4..b398665 100644 --- a/test/cases/getSegmentInfo.ts +++ b/test/cases/getSegmentInfo.ts @@ -146,7 +146,7 @@ describe("getSegmentInfo", () => { }); it("Should be able to retreive hidden segment", (done: Done) => { - fetch(`${getbaseURL() }/api/segmentInfo?UUID=${hiddenID}`) + fetch(`${getbaseURL()}/api/segmentInfo?UUID=${hiddenID}`) .then(async res => { assert.strictEqual(res.status, 200); const data = await res.json(); diff --git a/test/cases/getUserInfo.ts b/test/cases/getUserInfo.ts index 8d9ff79..c48d734 100644 --- a/test/cases/getUserInfo.ts +++ b/test/cases/getUserInfo.ts @@ -250,7 +250,7 @@ describe("getUserInfo", () => { .catch(err => done(err)); }); - it("Should get ban data for unbanned user (only appears when specifically requested)", (done: Done) => { + it("Should get ban data for unbanned user (only appears when specifically requested)", (done: Done) => { fetch(`${getbaseURL()}/api/userInfo?userID=getuserinfo_notban_01&value=banned`) .then(async res => { assert.strictEqual(res.status, 200); @@ -263,4 +263,35 @@ describe("getUserInfo", () => { }) .catch(err => done(err)); }); + + it("Should throw 400 on bad json in values", (done: Done) => { + fetch(`${getbaseURL()}/api/userInfo?userID=x&values=[userID]`) + .then(async res => { + assert.strictEqual(res.status, 400); + done(); // pass + }) + .catch(err => done(err)); + }); + + it("Should return 200 on userID not found", (done: Done) => { + fetch(`${getbaseURL()}/api/userInfo?userID=notused-userid`) + .then(async res => { + assert.strictEqual(res.status, 200); + const data = await res.json(); + const expected = { + minutesSaved: 0, + segmentCount: 0, + ignoredSegmentCount: 0, + viewCount: 0, + ignoredViewCount: 0, + warnings: 0, + warningReason: "", + reputation: 0, + vip: false, + }; + assert.ok(partialDeepEquals(data, expected)); + done(); // pass + }) + .catch(err => done(err)); + }); });