KV to D1 migration (this is totally gonna break something)

This commit is contained in:
2024-05-12 01:25:46 -04:00
parent a2b3391bda
commit e00b7e8c55
24 changed files with 1835 additions and 669 deletions

View File

@ -1,17 +1,18 @@
import { jsonError } from "../../common.js";
import sendEmail from "../../email.js";
import { sendPushNotification } from "../../gcloud.js";
import validateInactivityNotice from "./validate.js";
export async function onRequestDelete(context: RequestContext) {
const kvResult = await context.env.DATA.get(
`inactivity_${context.params.id}`,
);
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 (!kvResult) return jsonError("No inactivity notice with that ID", 404);
if (!result) return jsonError("No inactivity notice with that ID", 404);
if (
JSON.parse(kvResult).user.id !== context.data.current_user.id &&
result.uid !== context.data.current_user.id &&
!(context.data.current_user.permissions & (1 << 0))
)
return jsonError(
@ -19,7 +20,6 @@ export async function onRequestDelete(context: RequestContext) {
403,
);
await context.env.DATA.delete(`inactivity_${context.params.id}`);
await context.env.D1.prepare("DELETE FROM inactivity_notices WHERE id = ?;")
.bind(context.params.id)
.run();
@ -50,40 +50,61 @@ export async function onRequestPost(context: RequestContext) {
return jsonError("You are not a manager of any departments", 403);
const requestedNotice: { [k: string]: any } | null =
await context.env.DATA.get(`inactivity_${context.params.id as string}`, {
type: "json",
});
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 } = {};
const decisions: { [dept: string]: boolean } = JSON.parse(
requestedNotice.decisions,
);
for (const department of userAdminDepartments)
decisions[department] = accepted;
requestedNotice.decisions = decisions;
const applicableDepartments = JSON.parse(requestedNotice.departments).length;
if (Object.values(decisions).length === requestedNotice.departments.length) {
requestedNotice.open = false;
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();
const approved = !Object.values(decisions).filter((d) => !d).length;
await context.env.D1.prepare(
"UPDATE inactivity_notices SET approved = ?, open = 0 WHERE id = ?;",
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(Number(approved), context.params.id)
.run();
.bind(context.params.id)
.first();
if (fcmTokenResult) {
let status = "Approved";
if (denied) status = "Denied";
else if (!approved) status = "Partially Approved";
if (requestedNotice.fcm_token) {
await sendPushNotification(
context.env,
`Inactivity Request ${approved ? "Approved" : "Denied"}`,
`Inactivity Request ${status}`,
accepted
? "Your inactivity request was approved."
: "Your inactivity request was denied, please reach out to management if you require more details.",
requestedNotice.fcm_token,
: `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,
@ -93,96 +114,8 @@ export async function onRequestPost(context: RequestContext) {
{ username: requestedNotice.user.username },
);
}
delete requestedNotice.fcm_token;
delete requestedNotice.user.email;
}
await context.env.DATA.put(
`inactivity_${context.params.id as string}`,
JSON.stringify(requestedNotice),
{ expirationTtl: 63072000 },
);
return new Response(null, {
status: 204,
});
}
export async function onRequestPut(context: RequestContext) {
const kvResult: InactivityNoticeProps | null = await context.env.DATA.get(
`inactivity_${context.params.id}`,
{ type: "json" },
);
if (!kvResult) return jsonError("No inactivity notice with that ID", 404);
if (kvResult.user.id !== context.data.current_user.id)
return jsonError(
"You do not have permission to modify this inactivity notice",
403,
);
const d1entry = await context.env.D1.prepare(
"SELECT open FROM inactivity_notices WHERE id = ?;",
)
.bind(context.params.id)
.first();
if (!Boolean(d1entry?.open))
return jsonError("Cannot modify a closed inactivity notice", 403);
const { departments, end, reason, start } = context.data.body;
const validationFailureResponse = validateInactivityNotice(
departments,
end,
reason,
start,
context.data.departments,
);
if (validationFailureResponse) return validationFailureResponse;
kvResult.departments = departments;
kvResult.end = end;
kvResult.reason = reason;
kvResult.start = start;
await context.env.DATA.put(
`inactivity_${context.params.id}`,
JSON.stringify(kvResult),
{
expirationTtl: 63072000,
},
);
const departmentWebhooks = [];
for (const department of departments)
departmentWebhooks.push(context.env[`${department}_INACTIVITY_WEBHOOK`]);
const webhookPromises = [];
for (const webhook of departmentWebhooks)
webhookPromises.push(
fetch(webhook, {
body: JSON.stringify({
embeds: [
{
title: "Inactivity Notice Modified",
color: 37562560,
description: `View the updated notice at https://carcrushers.cc/mod-queue?id=${context.params.id}&type=inactivity`,
},
],
}),
headers: {
"content-type": "application/json",
},
method: "POST",
}),
);
await Promise.allSettled(webhookPromises);
return new Response(null, {
status: 204,
});

View File

@ -20,34 +20,33 @@ export async function onRequestPost(context: RequestContext) {
(context.request.headers.get("cf-ray") as string).split("-")[0] +
Date.now().toString();
await context.env.DATA.put(
`inactivity_${inactivityId}`,
JSON.stringify({
created_at: Date.now(),
departments,
await context.env.D1.prepare(
"INSERT INTO inactivity_notices (created_at, departments, end, hiatus, id, reason, start, user) VALUES (?, ?, ?, ?, ?, ?, ?, ?);",
)
.bind(
Date.now(),
JSON.stringify(departments),
end,
fcm_token: typeof senderTokenId === "string" ? senderTokenId : undefined,
hiatus,
open: true,
Number(hiatus),
inactivityId,
reason,
start,
user: {
JSON.stringify({
id: context.data.current_user.id,
email: context.data.current_user.email,
username: context.data.current_user.username,
},
}),
{
expirationTtl: 63072000,
},
);
await context.env.D1.prepare(
"INSERT INTO inactivity_notices (created_at, id, user) VALUES (?, ?, ?);",
)
.bind(Date.now(), inactivityId, context.data.current_user.id)
}),
)
.run();
if (typeof senderTokenId === "string") {
await context.env.D1.prepare(
"INSERT INTO push_notifications (created_at, event_id, event_type) VALUES (?, ?, ?);",
)
.bind(Date.now(), inactivityId, "inactivity")
.run();
}
const departmentsToNotify = [];
const departmentRoles = [];
const { env } = context;