From cebec73f6dd70c4858b3bc4d4fe3721d37866117 Mon Sep 17 00:00:00 2001 From: Sanidhya Singh Date: Tue, 23 Apr 2024 15:24:06 +0530 Subject: [PATCH] impr(backend): add ability to send report feedback to user about accepted and rejected reports (sanidhyas3s) (#5298) !nuf --- backend/src/api/controllers/admin.ts | 81 ++++++++++++++++++++++++++++ backend/src/api/routes/admin.ts | 43 +++++++++++++++ backend/src/dal/report.ts | 15 ++++++ 3 files changed, 139 insertions(+) diff --git a/backend/src/api/controllers/admin.ts b/backend/src/api/controllers/admin.ts index 0db718021329..da8e66f63fb7 100644 --- a/backend/src/api/controllers/admin.ts +++ b/backend/src/api/controllers/admin.ts @@ -1,5 +1,86 @@ import { MonkeyResponse } from "../../utils/monkey-response"; +import { buildMonkeyMail } from "../../utils/monkey-mail"; +import * as UserDAL from "../../dal/user"; +import * as ReportDAL from "../../dal/report"; export async function test(): Promise { return new MonkeyResponse("OK"); } + +export async function acceptReports( + req: MonkeyTypes.Request +): Promise { + return handleReports(req, true); +} + +export async function rejectReports( + req: MonkeyTypes.Request +): Promise { + return handleReports(req, false); +} + +export async function handleReports( + req: MonkeyTypes.Request, + accept: boolean +): Promise { + const { reports } = req.body; + const reportIds = reports.map(({ reportId }) => reportId); + + const reportsFromDb = await ReportDAL.getReports(reportIds); + const reportById = new Map(reportsFromDb.map((it) => [it.id, it])); + + const existingReportIds = reportsFromDb.map((report) => report.id); + const missingReportIds = reportIds.filter( + (reportId) => !existingReportIds.includes(reportId) + ); + + if (missingReportIds.length > 0) { + return new MonkeyResponse( + `Reports not found for some IDs`, + missingReportIds, + 404 + ); + } + + await ReportDAL.deleteReports(reportIds); + + for (const { reportId, reason } of reports) { + try { + const report = reportById.get(reportId); + if (!report) { + return new MonkeyResponse( + `Report not found for ID: ${reportId}`, + null, + 404 + ); + } + + let mailBody = ""; + if (accept) { + mailBody = `Your report regarding ${report.type} ${ + report.contentId + } (${report.reason.toLowerCase()}) has been approved. Thank you.`; + } else { + mailBody = `Sorry, but your report regarding ${report.type} ${ + report.contentId + } (${report.reason.toLowerCase()}) has been denied. ${ + reason !== undefined ? `\nReason: ${reason}` : "" + }`; + } + + const mailSubject = accept ? "Report approved" : "Report denied"; + const mail = buildMonkeyMail({ + subject: mailSubject, + body: mailBody, + }); + await UserDAL.addToInbox( + report.uid, + [mail], + req.ctx.configuration.users.inbox + ); + } catch (e) { + return new MonkeyResponse(e.message, null, e.status); + } + } + return new MonkeyResponse("Reports removed and users notified."); +} diff --git a/backend/src/api/routes/admin.ts b/backend/src/api/routes/admin.ts index 9097ace42c9c..2abf72e77114 100644 --- a/backend/src/api/routes/admin.ts +++ b/backend/src/api/routes/admin.ts @@ -48,4 +48,47 @@ router.post( asyncHandler(toggleBan) ); +router.post( + "/report/accept", + authenticateRequest({ + noCache: true, + }), + checkIfUserIsAdmin(), + validateRequest({ + body: { + reports: joi + .array() + .items( + joi.object({ + reportId: joi.string().required(), + }) + ) + .required(), + }, + }), + asyncHandler(AdminController.acceptReports) +); + +router.post( + "/report/reject", + authenticateRequest({ + noCache: true, + }), + checkIfUserIsAdmin(), + validateRequest({ + body: { + reports: joi + .array() + .items( + joi.object({ + reportId: joi.string().required(), + reason: joi.string().optional(), + }) + ) + .required(), + }, + }), + asyncHandler(AdminController.rejectReports) +); + export default router; diff --git a/backend/src/dal/report.ts b/backend/src/dal/report.ts index 8e2414085b02..7f746019c9d8 100644 --- a/backend/src/dal/report.ts +++ b/backend/src/dal/report.ts @@ -3,6 +3,21 @@ import * as db from "../init/db"; const COLLECTION_NAME = "reports"; +export async function getReports( + reportIds: string[] +): Promise { + const query = { id: { $in: reportIds } }; + return await db + .collection(COLLECTION_NAME) + .find(query) + .toArray(); +} + +export async function deleteReports(reportIds: string[]): Promise { + const query = { id: { $in: reportIds } }; + await db.collection(COLLECTION_NAME).deleteMany(query); +} + export async function createReport( report: MonkeyTypes.Report, maxReports: number,