import { jsonError, jsonResponse } from "../../common.js"; import sendEmail from "../../email.js"; import { sendPushNotification } from "../../gcloud.js"; export async function onRequestDelete(context: RequestContext) { const result = await context.env.D1.prepare( "SELECT json_extract(user, '*.id') AS uid FROM inactivity_notices WHERE id = ?;", ) .bind(context.params.id) .first(); if (!result) return jsonError("No inactivity notice with that ID", 404); if ( result.uid !== context.data.current_user.id && !(context.data.current_user.permissions & (1 << 0)) ) return jsonError( "You do not have permission to delete this inactivity notice", 403, ); await context.env.D1.prepare("DELETE FROM inactivity_notices WHERE id = ?;") .bind(context.params.id) .run(); return new Response(null, { status: 204, }); } export async function onRequestGet(context: RequestContext) { const { current_user: currentUser } = context.data; if ( ![1 << 0, 1 << 2, 1 << 3, 1 << 9, 1 << 10].find( (p) => currentUser.permissions & p, ) ) return jsonError("Forbidden", 403); const result: Record< string, string | number | { [k: string]: string } > | null = await context.env.D1.prepare( "SELECT * FROM inactivity_notices WHERE id = ?;", ) .bind(context.params.id) .first(); if (!result) return jsonError("Inactivity notice does not exist", 404); result.decisions = JSON.parse(result.decisions as string); result.departments = JSON.parse(result.departments as string); result.user = JSON.parse(result.user as string); return jsonResponse(JSON.stringify(result)); } export async function onRequestPost(context: RequestContext) { const { accepted }: { accepted?: boolean } = context.data.body; if (typeof accepted !== "boolean") return jsonError("'accepted' must be a boolean", 400); const adminDepartments: { [k: string]: number } = { DM: 1 << 11, ET: 1 << 4, FM: 1 << 7, WM: 1 << 6, }; const userAdminDepartments = Object.keys(adminDepartments).filter( (dept) => context.data.current_user.permissions & adminDepartments[dept], ); if (!userAdminDepartments.length) return jsonError("You are not a manager of any departments", 403); const requestedNotice: { [k: string]: any } | null = await context.env.D1.prepare( "SELECT decisions, departments, user FROM inactivity_notices WHERE id = ?;", ) .bind(context.params.id) .first(); if (!requestedNotice) return jsonError("Inactivity notices does not exist", 404); const decisions: { [dept: string]: boolean } = JSON.parse( requestedNotice.decisions, ); for (const department of userAdminDepartments) decisions[department] = accepted; const applicableDepartments = JSON.parse(requestedNotice.departments).length; await context.env.D1.prepare( "UPDATE inactivity_notices SET decisions = ?, user = json_remove(user, '$.email') WHERE id = ?;", ) .bind(JSON.stringify(decisions), context.params.id) .run(); if (Object.values(decisions).length === applicableDepartments) { const approved = Object.values(decisions).filter((d) => d).length === applicableDepartments; const denied = Object.values(decisions).filter((d) => !d).length !== applicableDepartments; const fcmTokenResult: FCMTokenResult | null = await context.env.D1.prepare( "SELECT token FROM push_notifications WHERE event_id = ? AND event_type = 'inactivity';", ) .bind(context.params.id) .first(); if (fcmTokenResult) { let status = "Approved"; if (denied) status = "Denied"; else if (!approved) status = "Partially Approved"; await sendPushNotification( context.env, `Inactivity Request ${status}`, accepted ? "Your inactivity request was approved." : `Your inactivity request was ${denied ? "denied" : "partially approved"}, please reach out to management if you require more details.`, fcmTokenResult.token, ); await context.env.D1.prepare( "DELETE FROM push_notifications WHERE event_id = ? AND event_type = 'inactivity';", ).bind(context.params.id); } else { await sendEmail( requestedNotice.user.email, context.env.MAILGUN_API_KEY, `Inactivity Request ${approved ? "Approved" : "Denied"}`, `inactivity_${approved ? "approved" : "denied"}`, { username: requestedNotice.user.username }, ); } } return new Response(null, { status: 204, }); }