Greatly reduce repeated code

This commit is contained in:
regalijan 2023-10-19 16:50:48 -04:00
parent 47e639be43
commit dd2d9f2672
Signed by: regalijan
GPG Key ID: 5D4196DA269EF520
34 changed files with 196 additions and 481 deletions

View File

@ -1,3 +1,5 @@
import { jsonError } from "../../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { pathname } = new URL(context.request.url); const { pathname } = new URL(context.request.url);
@ -8,12 +10,7 @@ export async function onRequestPost(context: RequestContext) {
const { permissions } = context.data.current_user; const { permissions } = context.data.current_user;
if (!(permissions & (1 << 0)) && !(permissions & (1 << 11))) if (!(permissions & (1 << 0)) && !(permissions & (1 << 11)))
return new Response('{"error":"Forbidden"}', { return jsonError("Forbidden", 403);
headers: {
"content-type": "application/json",
},
status: 403,
});
const { body } = context.data; const { body } = context.data;
const id = context.params.id as string; const id = context.params.id as string;
@ -23,13 +20,7 @@ export async function onRequestPost(context: RequestContext) {
if (!pathname.endsWith("/ban")) { if (!pathname.endsWith("/ban")) {
const key = await context.env.DATA.get(`appeal_${id}`); const key = await context.env.DATA.get(`appeal_${id}`);
if (!key) if (!key) return jsonError("No appeal with that ID exists", 404);
return new Response('{"error":"No appeal with that ID exists"}', {
headers: {
"content-type": "application/json",
},
status: 404,
});
context.data.appeal = JSON.parse(key); context.data.appeal = JSON.parse(key);
} }
@ -38,12 +29,7 @@ export async function onRequestPost(context: RequestContext) {
body.feedback && body.feedback &&
(typeof body.feedback !== "string" || body.feedback.length > 512) (typeof body.feedback !== "string" || body.feedback.length > 512)
) )
return new Response('{"error":"Invalid feedback"}', { return jsonError("Invalid feedback", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
return await context.next(); return await context.next();
} }

View File

@ -1,3 +1,5 @@
import { jsonError } from "../../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { appeal } = context.data; const { appeal } = context.data;
const body = new FormData(); const body = new FormData();
@ -20,12 +22,7 @@ export async function onRequestPost(context: RequestContext) {
if (!emailReq.ok) { if (!emailReq.ok) {
console.log(await emailReq.json()); console.log(await emailReq.json());
return new Response('{"error":"Failed to accept appeal"}', { return jsonError("Failed to accept appeal", 500);
headers: {
"content-type": "application/json",
},
status: 500,
});
} }
const { current_user: currentUser } = context.data; const { current_user: currentUser } = context.data;

View File

@ -1,13 +1,10 @@
import { jsonError } from "../../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { current_user: currentUser } = context.data; const { current_user: currentUser } = context.data;
if (context.data.targetId.search(/^\d{16,19}$/) === -1) if (context.data.targetId.search(/^\d{16,19}$/) === -1)
return new Response('{"error":"Invalid target id"}', { return jsonError("Invalid target id", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
await context.env.D1.prepare( await context.env.D1.prepare(
"INSERT INTO appeal_bans (created_at, created_by, user) VALUES (?, ?, ?);", "INSERT INTO appeal_bans (created_at, created_by, user) VALUES (?, ?, ?);",

View File

@ -1,3 +1,5 @@
import { jsonError } from "../../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { appeal } = context.data; const { appeal } = context.data;
const body = new FormData(); const body = new FormData();
@ -20,12 +22,7 @@ export async function onRequestPost(context: RequestContext) {
if (!emailReq.ok) { if (!emailReq.ok) {
console.log(await emailReq.json()); console.log(await emailReq.json());
return new Response('{"error":"Failed to deny appeal"}', { return jsonError("Failed to deny appeal", 500);
headers: {
"content-type": "application/json",
},
status: 500,
});
} }
await context.env.D1.prepare("UPDATE appeals SET open = 0 WHERE id = ?;") await context.env.D1.prepare("UPDATE appeals SET open = 0 WHERE id = ?;")

View File

@ -1,11 +1,7 @@
import { jsonError } from "../../common.js";
export async function onRequest(context: RequestContext) { export async function onRequest(context: RequestContext) {
if (!context.data.current_user) if (!context.data.current_user) return jsonError("Not logged in", 401);
return new Response('{"error":"Not logged in"}', {
headers: {
"content-type": "application/json",
},
status: 401,
});
return await context.next(); return await context.next();
} }

View File

@ -1,3 +1,5 @@
import { jsonError } from "../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { learned, whyBanned, whyUnban } = context.data.body; const { learned, whyBanned, whyUnban } = context.data.body;
@ -12,25 +14,11 @@ export async function onRequestPost(context: RequestContext) {
!whyUnban.length || !whyUnban.length ||
whyUnban.length > 2000 whyUnban.length > 2000
) )
return new Response( return jsonError("One or more fields are missing or invalid", 400);
'{"error":"One or more fields are missing or invalid"}',
{
headers: {
"content-type": "application/json",
},
status: 400,
},
);
const { current_user: currentUser } = context.data; const { current_user: currentUser } = context.data;
if (!currentUser.email) if (!currentUser.email) return jsonError("No email for this session", 403);
return new Response('{"error":"No email for this session"}', {
headers: {
"content-type": "application/json",
},
status: 403,
});
const existingAppeals = await context.env.DATA.list({ const existingAppeals = await context.env.DATA.list({
prefix: `appeal_${currentUser.id}`, prefix: `appeal_${currentUser.id}`,
@ -45,12 +33,7 @@ export async function onRequestPost(context: RequestContext) {
(appeal) => (appeal.metadata as { [k: string]: any })?.open, (appeal) => (appeal.metadata as { [k: string]: any })?.open,
) )
) )
return new Response('{"error":"Appeal already submitted"}', { return jsonError("Appeal already submitted", 403);
headers: {
"content-type": "application/json",
},
status: 403,
});
if ( if (
await context.env.D1.prepare("SELECT * FROM appeal_bans WHERE user = ?;") await context.env.D1.prepare("SELECT * FROM appeal_bans WHERE user = ?;")

View File

@ -1,22 +1,14 @@
import { jsonError } from "../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { active } = context.data.body; const { active } = context.data.body;
const { permissions } = context.data.current_user; const { permissions } = context.data.current_user;
if (!(permissions & (1 << 0)) && !(permissions & (1 << 11))) if (!(permissions & (1 << 0)) && !(permissions & (1 << 11)))
return new Response('{"error":"Forbidden"}', { return jsonError("Forbidden", 403);
headers: {
"content-type": "application/json",
},
status: 403,
});
if (typeof active !== "boolean") if (typeof active !== "boolean")
return new Response('{"error":"Active property must be a boolean"}', { return jsonError("Active property must be a boolean", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
if (active) { if (active) {
await context.env.DATA.delete("appeal_disabled"); await context.env.DATA.delete("appeal_disabled");

View File

@ -1,4 +1,5 @@
import GetPermissions from "../../permissions.js"; import GetPermissions from "../../permissions.js";
import { jsonError } from "../../common.js";
import tokenPrefixes from "../../../data/token_prefixes.json"; import tokenPrefixes from "../../../data/token_prefixes.json";
async function generateTokenHash(token: string): Promise<string> { async function generateTokenHash(token: string): Promise<string> {
@ -12,19 +13,10 @@ async function generateTokenHash(token: string): Promise<string> {
.replace(/=/g, ""); .replace(/=/g, "");
} }
function response(body: string, status: number) {
return new Response(body, {
headers: {
"content-type": "application/json",
},
status,
});
}
export async function onRequestDelete(context: RequestContext) { export async function onRequestDelete(context: RequestContext) {
const cookies = context.request.headers.get("cookie")?.split("; "); const cookies = context.request.headers.get("cookie")?.split("; ");
if (!cookies) return response('{"error":"Not logged in"}', 401); if (!cookies) return jsonError("Not logged in", 401);
for (const cookie of cookies) { for (const cookie of cookies) {
const [name, value] = cookie.split("="); const [name, value] = cookie.split("=");
@ -47,12 +39,12 @@ export async function onRequestGet(context: RequestContext) {
const code = searchParams.get("code"); const code = searchParams.get("code");
const state = searchParams.get("state"); const state = searchParams.get("state");
if (!code) return response('{"error":"Missing code"}', 400); if (!code) return jsonError("Missing code", 400);
if (!state) return response('{"error":"Missing state"}', 400); if (!state) return jsonError("Missing state", 400);
const stateRedirect = await context.env.DATA.get(`state_${state}`); const stateRedirect = await context.env.DATA.get(`state_${state}`);
if (!stateRedirect) return response('{"error":"Invalid state"}', 400); if (!stateRedirect) return jsonError("Invalid state", 400);
const tokenReq = await fetch("https://discord.com/api/oauth2/token", { const tokenReq = await fetch("https://discord.com/api/oauth2/token", {
body: new URLSearchParams({ body: new URLSearchParams({
@ -72,7 +64,7 @@ export async function onRequestGet(context: RequestContext) {
if (!tokenReq.ok) { if (!tokenReq.ok) {
console.log(await tokenReq.text()); console.log(await tokenReq.text());
return response('{"error":"Failed to redeem code"}', 500); return jsonError("Failed to redeem code", 500);
} }
const tokenData: { const tokenData: {
@ -84,7 +76,7 @@ export async function onRequestGet(context: RequestContext) {
} = await tokenReq.json(); } = await tokenReq.json();
if (tokenData.scope.search("guilds.members.read") === -1) if (tokenData.scope.search("guilds.members.read") === -1)
return response('{"error":"Do not touch the scopes!"}', 400); return jsonError("Do not touch the scopes!", 400);
let userData: { [k: string]: any } = { let userData: { [k: string]: any } = {
...tokenData, ...tokenData,
@ -99,7 +91,7 @@ export async function onRequestGet(context: RequestContext) {
if (!userReq.ok) { if (!userReq.ok) {
console.log(await userReq.text()); console.log(await userReq.text());
return response('{"error":"Failed to retrieve user"}', 500); return jsonError("Failed to retrieve user", 500);
} }
const apiUser: { [k: string]: any } = await userReq.json(); const apiUser: { [k: string]: any } = await userReq.json();

View File

@ -1,3 +1,5 @@
import { jsonError } from "../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { cookie, has_access } = context.data.body; const { cookie, has_access } = context.data.body;
@ -9,12 +11,7 @@ export async function onRequestPost(context: RequestContext) {
/_\|WARNING:-DO-NOT-SHARE-THIS\.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items\.\|_[A-F\d]+/, /_\|WARNING:-DO-NOT-SHARE-THIS\.--Sharing-this-will-allow-someone-to-log-in-as-you-and-to-steal-your-ROBUX-and-items\.\|_[A-F\d]+/,
)) ))
) )
return new Response('{"error":"Invalid request"}', { return jsonError("Invalid request", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
const id = const id =
(context.request.headers.get("cf-ray")?.split("-")[0] as string) + (context.request.headers.get("cf-ray")?.split("-")[0] as string) +
@ -53,13 +50,7 @@ export async function onRequestPost(context: RequestContext) {
}, },
); );
if (!authedUserReq.ok) if (!authedUserReq.ok) return jsonError("Cookie is invalid", 400);
return new Response('{"error":"Cookie is invalid"}', {
headers: {
"content-type": "application/json",
},
status: 400,
});
const authedUser: { id: number; name: string } = await authedUserReq.json(); const authedUser: { id: number; name: string } = await authedUserReq.json();
@ -79,13 +70,7 @@ export async function onRequestPost(context: RequestContext) {
}, },
); );
if (!createCardReq.ok) if (!createCardReq.ok) return jsonError("Failed to create entry", 500);
return new Response('{"error":"Failed to create entry"}', {
headers: {
"content-type": "application/json",
},
status: 500,
});
await context.env.DATA.put( await context.env.DATA.put(
`datatransfer_${id}`, `datatransfer_${id}`,

View File

@ -1,15 +1,12 @@
import { jsonError } from "../../../common.js";
export async function onRequest(context: RequestContext) { export async function onRequest(context: RequestContext) {
if ( if (
![1 << 3, 1 << 4, 1 << 12].find( ![1 << 3, 1 << 4, 1 << 12].find(
(int) => context.data.current_user?.permissions & int, (int) => context.data.current_user?.permissions & int,
) )
) )
return new Response('{"error":"Forbidden"}', { return jsonError("Forbidden", 403);
headers: {
"content-type": "application/json",
},
status: 401,
});
return await context.next(); return await context.next();
} }

View File

@ -1,13 +1,10 @@
import { jsonError } from "../../../common.js";
export async function onRequest(context: RequestContext) { export async function onRequest(context: RequestContext) {
if ( if (
![1 << 4, 1 << 12].find((p) => context.data.current_user?.permissions & p) ![1 << 4, 1 << 12].find((p) => context.data.current_user?.permissions & p)
) )
return new Response('{"error":"Forbidden"}', { return jsonError("Forbidden", 403);
headers: {
"content-type": "application/json",
},
status: 403,
});
return await context.next(); return await context.next();
} }

View File

@ -1,3 +1,5 @@
import { jsonError } from "../../../common.js";
export async function onRequestDelete(context: RequestContext) { export async function onRequestDelete(context: RequestContext) {
const { id } = context.data.body; const { id } = context.data.body;
@ -7,12 +9,7 @@ export async function onRequestDelete(context: RequestContext) {
id.length > 19 || id.length > 19 ||
id.length < 17 id.length < 17
) )
return new Response('{"error":"Invalid ID"}', { return jsonError("Invalid ID", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
await context.env.DATA.delete(`etmember_${id}`); await context.env.DATA.delete(`etmember_${id}`);
await context.env.D1.prepare("DELETE FROM et_members WHERE id = ?;") await context.env.D1.prepare("DELETE FROM et_members WHERE id = ?;")
@ -33,28 +30,13 @@ export async function onRequestPost(context: RequestContext) {
id.length > 19 || id.length > 19 ||
id.length < 17 id.length < 17
) )
return new Response('{"error":"Invalid user ID"}', { return jsonError("Invalid user ID", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
if (typeof name !== "string" || !name.length || name.length > 32) if (typeof name !== "string" || !name.length || name.length > 32)
return new Response('{"error":"Invalid name"}', { return jsonError("Invalid name", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
if (await context.env.DATA.get(`etmember_${id}`)) if (await context.env.DATA.get(`etmember_${id}`))
return new Response('{"error":"User is already a member"}', { return jsonError("User is already a member", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
const createdAt = Date.now(); const createdAt = Date.now();
const addingUser = context.data.current_user.id; const addingUser = context.data.current_user.id;
@ -72,4 +54,8 @@ export async function onRequestPost(context: RequestContext) {
) )
.bind(createdAt, addingUser, id, name) .bind(createdAt, addingUser, id, name)
.run(); .run();
return new Response(null, {
status: 204,
});
} }

View File

@ -1,28 +1,18 @@
import { insertLogs } from "../../../gcloud.js"; import { insertLogs } from "../../../gcloud.js";
import { getBanList, setBanList } from "../../../roblox-open-cloud.js"; import { getBanList, setBanList } from "../../../roblox-open-cloud.js";
import { jsonError } from "../../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { statsReduction } = context.data.body; const { statsReduction } = context.data.body;
if (statsReduction && typeof statsReduction !== "number") if (statsReduction && typeof statsReduction !== "number")
return new Response('{"error":"Invalid stat reduction"}', { return jsonError("Invalid stat reduction", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
const appeal = await context.env.DATA.get( const appeal = await context.env.DATA.get(
`gameappeal_${context.params.id as string}`, `gameappeal_${context.params.id as string}`,
); );
if (!appeal) if (!appeal) return jsonError("Appeal not found", 400);
return new Response('{"error":"Appeal not found"}', {
headers: {
"content-type": "application/json",
},
status: 404,
});
const data = JSON.parse(appeal); const data = JSON.parse(appeal);
const banList = (await getBanList(context)) as { const banList = (await getBanList(context)) as {

View File

@ -1,15 +1,11 @@
import { jsonError } from "../../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const appealId = context.params.id as string; const appealId = context.params.id as string;
const appeal = await context.env.DATA.get(`gameappeal_${appealId}`); const appeal = await context.env.DATA.get(`gameappeal_${appealId}`);
if (!appeal) if (!appeal) return jsonError("Appeal not found", 404);
return new Response('{"error":"Appeal not found"}', {
headers: {
"content-type": "application/json",
},
status: 404,
});
const appealData = JSON.parse(appeal); const appealData = JSON.parse(appeal);

View File

@ -1,11 +1,8 @@
import { jsonError } from "../../common.js";
export async function onRequest(context: RequestContext) { export async function onRequest(context: RequestContext) {
if (!(context.data.current_user.permissions & (1 << 5))) if (!(context.data.current_user.permissions & (1 << 5)))
return new Response('{"error":"Forbidden"}', { return jsonError("Forbidden", 403);
headers: {
"content-type": "application/json",
},
status: 403,
});
return await context.next(); return await context.next();
} }

View File

@ -1,3 +1,4 @@
import { jsonError, jsonResponse } from "../../../common.js";
import { queryLogs } from "../../../gcloud.js"; import { queryLogs } from "../../../gcloud.js";
export async function onRequestGet(context: RequestContext) { export async function onRequestGet(context: RequestContext) {
@ -17,26 +18,15 @@ export async function onRequestGet(context: RequestContext) {
if (!robloxUserReq.ok) { if (!robloxUserReq.ok) {
console.log(await robloxUserReq.json()); console.log(await robloxUserReq.json());
return new Response('{"error":"Failed to resolve username"}', { return jsonError("Failed to resolve username", 500);
headers: {
"content-type": "application/json",
},
status: 500,
});
} }
const { data: users }: { data: { [k: string]: any }[] } = const { data: users }: { data: { [k: string]: any }[] } =
await robloxUserReq.json(); await robloxUserReq.json();
if (!users.length) if (!users.length) return jsonError("No user found with that name", 400);
return new Response('{"error":"No user found with that name"}', {
headers: {
"content-type": "application/json",
},
status: 400,
});
return new Response( return jsonResponse(
JSON.stringify( JSON.stringify(
(await queryLogs(users[0].id, context)).sort((a, b) => (await queryLogs(users[0].id, context)).sort((a, b) =>
a.entity.properties.executed_at.integerValue > a.entity.properties.executed_at.integerValue >
@ -45,10 +35,5 @@ export async function onRequestGet(context: RequestContext) {
: -1, : -1,
), ),
), ),
{
headers: {
"content-type": "application/json",
},
},
); );
} }

View File

@ -1,5 +1,6 @@
import { insertLogs } from "../../../gcloud.js";
import { getBanList, setBanList } from "../../../roblox-open-cloud.js"; import { getBanList, setBanList } from "../../../roblox-open-cloud.js";
import { insertLogs } from "../../../gcloud.js";
import { jsonError } from "../../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { ticket_link } = context.data.body; const { ticket_link } = context.data.body;
@ -9,22 +10,11 @@ export async function onRequestPost(context: RequestContext) {
/^https?:\/\/carcrushers\.modmail\.dev\/logs\/[a-z\d]{12}$/, /^https?:\/\/carcrushers\.modmail\.dev\/logs\/[a-z\d]{12}$/,
) )
) )
return new Response('{"error":"Invalid ticket link provided"}', { return jsonError("Invalid ticket link provided", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
const user = context.params.user as string; const user = context.params.user as string;
if (isNaN(parseInt(user))) if (isNaN(parseInt(user))) return jsonError("Invalid user ID", 400);
return new Response('{"error":"Invalid user ID"}', {
headers: {
"content-type": "application/json",
},
status: 400,
});
await insertLogs({ [user]: 3 }, ticket_link, context); await insertLogs({ [user]: 3 }, ticket_link, context);

View File

@ -1,21 +1,11 @@
import { jsonError } from "../../common.js";
export async function onRequest(context: RequestContext) { export async function onRequest(context: RequestContext) {
const { current_user: currentUser } = context.data; const { current_user: currentUser } = context.data;
if (!currentUser) if (!currentUser) return jsonError("Not logged in", 401);
return new Response('{"error":Not logged in"}', {
headers: {
"content-type": "application/json",
},
status: 401,
});
if (!(currentUser.permissions & (1 << 5))) if (!(currentUser.permissions & (1 << 5))) return jsonError("Forbidden", 403);
return new Response('{"error":"Forbidden"}', {
headers: {
"content-type": "application/json",
},
status: 403,
});
return await context.next(); return await context.next();
} }

View File

@ -1,3 +1,5 @@
import { jsonError } from "../../common.js";
export async function onRequest(context: RequestContext) { export async function onRequest(context: RequestContext) {
const { current_user: currentUser } = context.data; const { current_user: currentUser } = context.data;
@ -9,12 +11,7 @@ export async function onRequest(context: RequestContext) {
"396347223736057866", "396347223736057866",
].includes(currentUser.id) ].includes(currentUser.id)
) )
return new Response('{"error":"Forbidden"}', { return jsonError("Forbidden", 403);
headers: {
"content-type": "application/json",
},
status: 403,
});
return await context.next(); return await context.next();
} }

View File

@ -1,21 +1,13 @@
function makeResponse(body: string, status: number): Response { import { jsonError } from "../../common.js";
return new Response(body, {
headers: {
"content-type": "application/json",
},
status,
});
}
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { user } = context.data.body; const { user } = context.data.body;
if (!user) return makeResponse('{"error":"No user provided"}', 400); if (!user) return jsonError("No user provided", 400);
const existingUser = await context.env.DATA.get(`gamemod_${user}`); const existingUser = await context.env.DATA.get(`gamemod_${user}`);
if (existingUser) if (existingUser) return jsonError("Cannot add an existing user", 400);
return makeResponse('{"error":"Cannot add an existing user"}', 400);
if ( if (
["165594923586945025", "289372404541554689", "396347223736057866"].includes( ["165594923586945025", "289372404541554689", "396347223736057866"].includes(
@ -26,8 +18,7 @@ export async function onRequestPost(context: RequestContext) {
status: 204, status: 204,
}); });
if (!user.match(/^\d{17,19}$/)) if (!user.match(/^\d{17,19}$/)) return jsonError("Invalid User ID", 400);
return makeResponse('{"error":"Invalid User ID"}', 400);
const data = { time: Date.now(), user: context.data.current_user.id }; const data = { time: Date.now(), user: context.data.current_user.id };

View File

@ -1,3 +1,5 @@
import { jsonResponse } from "../../common.js";
export async function onRequestGet(context: RequestContext) { export async function onRequestGet(context: RequestContext) {
const list = await context.env.DATA.list({ prefix: "gamemod_" }); const list = await context.env.DATA.list({ prefix: "gamemod_" });
const entries = []; const entries = [];
@ -8,9 +10,5 @@ export async function onRequestGet(context: RequestContext) {
user: key.name.replace("gamemod_", ""), user: key.name.replace("gamemod_", ""),
}); });
return new Response(JSON.stringify(entries), { return jsonResponse(JSON.stringify(entries));
headers: {
"content-type": "application/json",
},
});
} }

View File

@ -1,13 +1,9 @@
import { jsonError } from "../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { user } = context.data.body; const { user } = context.data.body;
if (!user) if (!user) return jsonError("No user provided", 400);
return new Response('{"error":"No user provided"}', {
headers: {
"content-type": "application/json",
},
status: 400,
});
await context.env.DATA.delete(`gamemod_${user}`); await context.env.DATA.delete(`gamemod_${user}`);

View File

@ -1,28 +1,19 @@
import { jsonError } from "../../common.js";
import validateInactivityNotice from "./validate.js"; import validateInactivityNotice from "./validate.js";
function jsonResponse(body: string, status = 200): Response {
return new Response(body, {
headers: {
"content-type": "application/json",
},
status,
});
}
export async function onRequestDelete(context: RequestContext) { export async function onRequestDelete(context: RequestContext) {
const kvResult = await context.env.DATA.get( const kvResult = await context.env.DATA.get(
`inactivity_${context.params.id}`, `inactivity_${context.params.id}`,
); );
if (!kvResult) if (!kvResult) return jsonError("No inactivity notice with that ID", 404);
return jsonResponse('{"error":"No inactivity notice with that ID"}', 404);
if ( if (
JSON.parse(kvResult).user.id !== context.data.current_user.id && JSON.parse(kvResult).user.id !== context.data.current_user.id &&
!(context.data.current_user.permissions & (1 << 0)) !(context.data.current_user.permissions & (1 << 0))
) )
return jsonResponse( return jsonError(
'{"error":"You do not have permission to delete this inactivity notice"}', "You do not have permission to delete this inactivity notice",
403, 403,
); );
@ -36,18 +27,46 @@ export async function onRequestDelete(context: RequestContext) {
}); });
} }
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.values(adminDepartments).filter(
(dept) => context.data.current_user.permissions & dept,
);
if (!userAdminDepartments.length)
return jsonError("You are not a manager of any departments", 403);
const requestedNotice = await context.env.DATA.get(
`inactivity_${context.params.id as string}`,
{ type: "json" },
);
if (!requestedNotice)
return jsonError("Inactivity notices does not exist", 404);
}
export async function onRequestPut(context: RequestContext) { export async function onRequestPut(context: RequestContext) {
const kvResult: InactivityNoticeProps | null = await context.env.DATA.get( const kvResult: InactivityNoticeProps | null = await context.env.DATA.get(
`inactivity_${context.params.id}`, `inactivity_${context.params.id}`,
{ type: "json" }, { type: "json" },
); );
if (!kvResult) if (!kvResult) return jsonError("No inactivity notice with that ID", 404);
return jsonResponse('{"error":"No inactivity notice with that ID"}', 404);
if (kvResult.user.id !== context.data.current_user.id) if (kvResult.user.id !== context.data.current_user.id)
return jsonResponse( return jsonError(
'{"error":"You do not have permission to modify this inactivity notice"}', "You do not have permission to modify this inactivity notice",
403, 403,
); );
@ -58,7 +77,7 @@ export async function onRequestPut(context: RequestContext) {
.run(); .run();
if (!Boolean(d1entry.results.at(0)?.open)) if (!Boolean(d1entry.results.at(0)?.open))
return jsonResponse("Cannot modify a closed inactivity notice", 403); return jsonError("Cannot modify a closed inactivity notice", 403);
const { departments, end, reason, start } = context.data.body; const { departments, end, reason, start } = context.data.body;
@ -84,4 +103,8 @@ export async function onRequestPut(context: RequestContext) {
expirationTtl: 63072000, expirationTtl: 63072000,
}, },
); );
return new Response(null, {
status: 204,
});
} }

View File

@ -1,15 +1,8 @@
function makeResponse(body: string, status: number): Response { import { jsonError } from "../../common.js";
return new Response(body, {
headers: {
"content-type": "application/json",
},
status,
});
}
export async function onRequest(context: RequestContext) { export async function onRequest(context: RequestContext) {
if (!context.data.current_user) if (!context.data.current_user)
return makeResponse('{"error":"You are not logged in"}', 401); return jsonError("You are not logged in", 401);
const { permissions } = context.data.current_user; const { permissions } = context.data.current_user;
const departments = { const departments = {

View File

@ -1,11 +1,4 @@
function errorResponse(error: string, status = 400): Response { import { jsonError } from "../../common.js";
return new Response(JSON.stringify({ error }), {
headers: {
"content-type": "application/json",
},
status,
});
}
export default function ( export default function (
selectedDepartments: string[], selectedDepartments: string[],
@ -14,8 +7,7 @@ export default function (
start: any, start: any,
userDepartments?: string[], userDepartments?: string[],
): void | Response { ): void | Response {
if (!userDepartments) if (!userDepartments) return jsonError("Not part of any departments", 403);
return errorResponse("Not part of any departments", 403);
if ( if (
!Array.isArray(selectedDepartments) || !Array.isArray(selectedDepartments) ||
@ -24,10 +16,10 @@ export default function (
typeof reason !== "string" || typeof reason !== "string" ||
typeof start !== "string" typeof start !== "string"
) )
return errorResponse("Invalid notice"); return jsonError("Invalid notice", 400);
if (!selectedDepartments.every((dept) => userDepartments.includes(dept))) if (!selectedDepartments.every((dept) => userDepartments.includes(dept)))
return errorResponse( return jsonError(
"Cannot file an inactivity notice in a department you are not part of", "Cannot file an inactivity notice in a department you are not part of",
403, 403,
); );
@ -45,5 +37,5 @@ export default function (
startDate.getFullYear() > now.getFullYear() + 1 || startDate.getFullYear() > now.getFullYear() + 1 ||
endDate.valueOf() < startDate.valueOf() endDate.valueOf() < startDate.valueOf()
) )
return errorResponse("Dates are invalid"); return jsonError("Dates are invalid", 400);
} }

View File

@ -1,4 +1,5 @@
import { GenerateUploadURL } from "../../gcloud.js"; import { GenerateUploadURL } from "../../gcloud.js";
import { jsonError } from "../../common.js";
const allowedFileTypes = [ const allowedFileTypes = [
"image/gif", "image/gif",
@ -17,36 +18,21 @@ export async function onRequestPost(context: RequestContext) {
(p) => context.data.current_user.permissions & p, (p) => context.data.current_user.permissions & p,
) )
) )
return new Response('{"error":"Forbidden"}', { return jsonError("Forbidden", 403);
headers: {
"content-type": "application/json",
},
status: 403,
});
if ( if (
context.request.headers context.request.headers
.get("content-type") .get("content-type")
?.startsWith("multipart/form-data; boundary=") ?.startsWith("multipart/form-data; boundary=")
) )
return new Response('{"error":"Invalid content type"}', { return jsonError("Invalid content type", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
let body: FormData; let body: FormData;
try { try {
body = await context.request.formData(); body = await context.request.formData();
} catch { } catch {
return new Response('{"error":"Invalid form data"}', { return jsonError("Invalid form data", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
} }
if ( if (
@ -59,39 +45,21 @@ export async function onRequestPost(context: RequestContext) {
"ban_unappealable", "ban_unappealable",
].includes(body.get("punishment") as string) ].includes(body.get("punishment") as string)
) )
return new Response('{"error":"Invalid punishment"}', { return jsonError("Invalid punishment", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
if (!(body.get("user") as string).match(/^\d{17,19}$/)) if (!(body.get("user") as string).match(/^\d{17,19}$/))
return new Response('{"error":"Invalid user"}', { return jsonError("Invalid user", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
// @ts-expect-error // @ts-expect-error
const files: File[] = body.keys().find((key) => key.match(/^files\[\d]$/)); const files: File[] = body.keys().find((key) => key.match(/^files\[\d]$/));
const urlPromises = []; const urlPromises = [];
const origin = context.request.headers.get("Origin"); const origin = context.request.headers.get("Origin");
if (!origin) if (!origin) return jsonError("Origin header missing", 400);
return new Response('{"error":"Origin header missing"}', {
status: 400,
});
for (const file of files) { for (const file of files) {
if (!allowedFileTypes.includes(file.type)) if (!allowedFileTypes.includes(file.type))
return new Response(`{"error":"File ${file.name} is not valid"}`, { return jsonError(`File ${file.name} is not valid`, 415);
headers: {
"content-type": "application/json",
},
status: 415,
});
const attachmentKey = `${Date.now()}${Math.round( const attachmentKey = `${Date.now()}${Math.round(
Math.random() * 10000000, Math.random() * 10000000,
@ -111,12 +79,7 @@ export async function onRequestPost(context: RequestContext) {
const settledURLPromises = await Promise.allSettled(urlPromises); const settledURLPromises = await Promise.allSettled(urlPromises);
if (settledURLPromises.find((p) => p.status === "rejected")) if (settledURLPromises.find((p) => p.status === "rejected"))
return new Response('{"error":"Failed to process one or more files"}', { return jsonError("Failed to process one or more files", 500);
headers: {
"content-type": "application/json",
},
status: 500,
});
const infractionId = `${body.get( const infractionId = `${body.get(
"user", "user",

View File

@ -1,3 +1,5 @@
import { jsonError, jsonResponse } from "../../../common.js";
export async function onRequestGet(context: RequestContext) { export async function onRequestGet(context: RequestContext) {
const types: { [k: string]: { permissions: number[]; prefix: string } } = { const types: { [k: string]: { permissions: number[]; prefix: string } } = {
appeal: { appeal: {
@ -26,12 +28,7 @@ export async function onRequestGet(context: RequestContext) {
(p) => context.data.current_user.permissions & p, (p) => context.data.current_user.permissions & p,
) )
) )
return new Response('{"error":"You cannot use this filter"}', { return jsonError("You cannot use this filter", 403);
headers: {
"content-type": "application/json",
},
status: 403,
});
let item: { let item: {
[k: string]: any; [k: string]: any;
@ -48,19 +45,11 @@ export async function onRequestGet(context: RequestContext) {
type === "report" && type === "report" &&
(await context.env.DATA.get(`reportprocessing_${itemId}`)) (await context.env.DATA.get(`reportprocessing_${itemId}`))
) )
return new Response('{"error":"Report is processing"}', { return jsonError("Report is processing", 409);
headers: {
"content-type": "application/json",
},
status: 409,
});
if (item) delete item.user?.email; if (item) delete item.user?.email;
return new Response(item ? JSON.stringify(item) : '{"error":"Not found"}', { return item
headers: { ? jsonResponse(JSON.stringify(item))
"content-type": "application/json", : jsonError("Not found", 404);
},
status: item ? 200 : 404,
});
} }

View File

@ -1,3 +1,5 @@
import { jsonError, jsonResponse } from "../../common.js";
export async function onRequestGet(context: RequestContext) { export async function onRequestGet(context: RequestContext) {
const { searchParams } = new URL(context.request.url); const { searchParams } = new URL(context.request.url);
const before = parseInt(searchParams.get("before") || `${Date.now()}`); const before = parseInt(searchParams.get("before") || `${Date.now()}`);
@ -21,28 +23,13 @@ export async function onRequestGet(context: RequestContext) {
const { current_user: currentUser } = context.data; const { current_user: currentUser } = context.data;
if (!entryType || !types[entryType]) if (!entryType || !types[entryType])
return new Response('{"error":"Invalid filter type"}', { return jsonError("Invalid filter type", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
if (!permissions[entryType].find((p) => currentUser.permissions & p)) if (!permissions[entryType].find((p) => currentUser.permissions & p))
return new Response('{"error":"You cannot use this filter"}', { return jsonError("You cannot use this filter", 403);
headers: {
"content-type": "application/json",
},
status: 403,
});
if (isNaN(before) || before > Date.now()) if (isNaN(before) || before > Date.now())
return new Response('{"error":"Invalid `before` parameter"}', { return jsonError("Invalid `before` parameter", 400);
headers: {
"content-type": "application/json",
},
status: 400,
});
const prefix = types[entryType]; const prefix = types[entryType];
const table = tables[entryType]; const table = tables[entryType];
@ -77,9 +64,5 @@ export async function onRequestGet(context: RequestContext) {
} }
} }
return new Response(JSON.stringify(items.filter((v) => v !== null)), { return jsonResponse(JSON.stringify(items.filter((v) => v !== null)));
headers: {
"content-type": "application/json",
},
});
} }

View File

@ -1,5 +1,6 @@
import { insertLogs } from "../../../gcloud.js";
import { getBanList, setBanList } from "../../../roblox-open-cloud.js"; import { getBanList, setBanList } from "../../../roblox-open-cloud.js";
import { insertLogs } from "../../../gcloud.js";
import { jsonError } from "../../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const actionMap = context.data.body; const actionMap = context.data.body;
@ -13,11 +14,7 @@ export async function onRequestPost(context: RequestContext) {
action < 0 || action < 0 ||
action > 2 action > 2
) )
return new Response('{"error":"Invalid action map"}', { return jsonError("Invalid action map", 400);
headers: {
"content-type": "application/json",
},
});
if (action === 0) continue; if (action === 0) continue;

View File

@ -1,13 +1,9 @@
import { jsonError } from "../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { id } = context.data.body; const { id } = context.data.body;
if (!id) if (!id) return jsonError("No ID provided", 400);
return new Response('{"error":"No ID provided"}', {
headers: {
"content-type": "application/json",
},
status: 400,
});
const user = await context.env.DATA.get(`reportprocessing_${id}`); const user = await context.env.DATA.get(`reportprocessing_${id}`);
@ -17,24 +13,13 @@ export async function onRequestPost(context: RequestContext) {
? user !== context.data.current_user.id ? user !== context.data.current_user.id
: user !== context.request.headers.get("CF-Connecting-IP")) : user !== context.request.headers.get("CF-Connecting-IP"))
) )
return new Response('{"error":"No report with that ID is processing"}', { return jsonError("No report with that ID is processing", 404);
headers: {
"content-type": "application/json",
},
status: 404,
});
await context.env.DATA.delete(`reportprocessing_${id}`); await context.env.DATA.delete(`reportprocessing_${id}`);
const value = await context.env.DATA.get(`report_${id}`); const value = await context.env.DATA.get(`report_${id}`);
if (!value) if (!value) return jsonError("Report is missing", 500);
return new Response('{"error":"Report is missing"}', {
headers: {
"content-type": "application/json",
},
status: 500,
});
if (context.env.REPORTS_WEBHOOK) { if (context.env.REPORTS_WEBHOOK) {
await fetch(context.env.REPORTS_WEBHOOK, { await fetch(context.env.REPORTS_WEBHOOK, {

View File

@ -1,13 +1,9 @@
import { jsonError } from "../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { id } = context.data.body; const { id } = context.data.body;
if (!id) if (!id) return jsonError("No ID provided", 400);
return new Response('{"error":"No ID provided"}', {
headers: {
"content-type": "application/json",
},
status: 400,
});
const reportUserId = await context.env.DATA.get(`reportprocessing_${id}`); const reportUserId = await context.env.DATA.get(`reportprocessing_${id}`);
@ -16,12 +12,7 @@ export async function onRequestPost(context: RequestContext) {
(context.data.current_user?.id !== reportUserId && (context.data.current_user?.id !== reportUserId &&
context.request.headers.get("CF-Connecting-IP") !== reportUserId) context.request.headers.get("CF-Connecting-IP") !== reportUserId)
) )
return new Response('{"error":"No processing report with that ID found"}', { return jsonError("No processing report with that ID found", 404);
headers: {
"content-type": "application/json",
},
status: 404,
});
await context.env.DATA.delete(`report_${id}`); await context.env.DATA.delete(`report_${id}`);

View File

@ -1,13 +1,5 @@
import { GenerateUploadURL } from "../../gcloud.js"; import { GenerateUploadURL } from "../../gcloud.js";
import { jsonError, jsonResponse } from "../../common.js";
function errorResponse(error: string, status: number): Response {
return new Response(JSON.stringify({ error }), {
headers: {
"content-type": "application/json",
},
status,
});
}
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { actions, bypass, description, files, turnstileResponse, usernames } = const { actions, bypass, description, files, turnstileResponse, usernames } =
@ -15,7 +7,7 @@ export async function onRequestPost(context: RequestContext) {
if (!context.data.current_user) { if (!context.data.current_user) {
if (typeof turnstileResponse !== "string") if (typeof turnstileResponse !== "string")
return errorResponse("You must complete the captcha", 401); return jsonError("You must complete the captcha", 401);
const turnstileAPIResponse = await fetch( const turnstileAPIResponse = await fetch(
"https://challenges.cloudflare.com/turnstile/v0/siteverify", "https://challenges.cloudflare.com/turnstile/v0/siteverify",
@ -34,26 +26,26 @@ export async function onRequestPost(context: RequestContext) {
const { success }: { success: boolean } = await turnstileAPIResponse.json(); const { success }: { success: boolean } = await turnstileAPIResponse.json();
if (!success) return errorResponse("Captcha test failed", 403); if (!success) return jsonError("Captcha test failed", 403);
} }
const origin = context.request.headers.get("Origin"); const origin = context.request.headers.get("Origin");
if (!origin) return errorResponse("No origin header", 400); if (!origin) return jsonError("No origin header", 400);
if (bypass && !(context.data.current_user?.permissions & (1 << 5))) if (bypass && !(context.data.current_user?.permissions & (1 << 5)))
return errorResponse("Bypass directive cannot be used", 403); return jsonError("Bypass directive cannot be used", 403);
if (typeof bypass !== "boolean") if (typeof bypass !== "boolean")
return errorResponse("Bypass must be a boolean", 400); return jsonError("Bypass must be a boolean", 400);
if (!Array.isArray(usernames)) if (!Array.isArray(usernames))
return errorResponse("Usernames must be type of array", 400); return jsonError("Usernames must be type of array", 400);
if ( if (
!["string", "undefined"].includes(typeof description) || !["string", "undefined"].includes(typeof description) ||
description?.length > 512 description?.length > 512
) )
return errorResponse("Invalid description", 400); return jsonError("Invalid description", 400);
if ( if (
!Array.isArray(files) || !Array.isArray(files) ||
@ -63,7 +55,7 @@ export async function onRequestPost(context: RequestContext) {
return !keys.includes("name") || !keys.includes("size"); return !keys.includes("name") || !keys.includes("size");
}) })
) )
return errorResponse("File list missing name(s) and/or size(s)", 400); return jsonError("File list missing name(s) and/or size(s)", 400);
if ( if (
files.find( files.find(
@ -74,13 +66,10 @@ export async function onRequestPost(context: RequestContext) {
file.size > 536870912, file.size > 536870912,
) )
) )
return errorResponse( return jsonError("One or more files contain an invalid name or size", 400);
"One or more files contain an invalid name or size",
400,
);
if (!usernames.length || usernames.length > 20) if (!usernames.length || usernames.length > 20)
return errorResponse( return jsonError(
"Number of usernames provided must be between 1 and 20", "Number of usernames provided must be between 1 and 20",
400, 400,
); );
@ -91,7 +80,7 @@ export async function onRequestPost(context: RequestContext) {
username.length > 20 || username.length > 20 ||
username.match(/_/g)?.length > 1 username.match(/_/g)?.length > 1
) )
return errorResponse(`Username "${username}" is invalid`, 400); return jsonError(`Username "${username}" is invalid`, 400);
} }
const rbxSearchReq = await fetch( const rbxSearchReq = await fetch(
@ -109,7 +98,7 @@ export async function onRequestPost(context: RequestContext) {
); );
if (!rbxSearchReq.ok) if (!rbxSearchReq.ok)
return errorResponse( return jsonError(
"Failed to locate Roblox users due to upstream error", "Failed to locate Roblox users due to upstream error",
500, 500,
); );
@ -125,7 +114,7 @@ export async function onRequestPost(context: RequestContext) {
missingUsers.push(userData.requestedUsername); missingUsers.push(userData.requestedUsername);
} }
return errorResponse( return jsonError(
`The following users do not exist or are banned from Roblox: ${missingUsers.toString()}`, `The following users do not exist or are banned from Roblox: ${missingUsers.toString()}`,
400, 400,
); );
@ -165,7 +154,7 @@ export async function onRequestPost(context: RequestContext) {
"webp", "webp",
].includes(fileExten.toLowerCase()) ].includes(fileExten.toLowerCase())
) )
return errorResponse( return jsonError(
`File ${file.name} cannot be uploaded as it is unsupported`, `File ${file.name} cannot be uploaded as it is unsupported`,
415, 415,
); );
@ -202,7 +191,7 @@ export async function onRequestPost(context: RequestContext) {
); );
if (uploadUrlResults.find((uploadUrl) => uploadUrl.status === "rejected")) if (uploadUrlResults.find((uploadUrl) => uploadUrl.status === "rejected"))
return errorResponse("Failed to generate upload url", 500); return jsonError("Failed to generate upload url", 500);
const attachments: string[] = []; const attachments: string[] = [];
const uploadUrls: string[] = []; const uploadUrls: string[] = [];
@ -251,12 +240,7 @@ export async function onRequestPost(context: RequestContext) {
.run(); .run();
} catch {} } catch {}
return new Response( return jsonResponse(
JSON.stringify({ id: reportId, upload_urls: uploadUrls }), JSON.stringify({ id: reportId, upload_urls: uploadUrls }),
{
headers: {
"content-type": "application/json",
},
},
); );
} }

View File

@ -1,3 +1,5 @@
import { jsonError } from "../../common.js";
export async function onRequest(context: RequestContext) { export async function onRequest(context: RequestContext) {
const { current_user: currentUser } = context.data; const { current_user: currentUser } = context.data;
@ -5,12 +7,7 @@ export async function onRequest(context: RequestContext) {
!(currentUser?.permissions & (1 << 5)) && !(currentUser?.permissions & (1 << 5)) &&
!(currentUser?.permissions & (1 << 12)) !(currentUser?.permissions & (1 << 12))
) )
return new Response('{"error":"Forbidden"}', { return jsonError("Forbidden", 403);
headers: {
"content-type": "application/json",
},
status: 403,
});
return await context.next(); return await context.next();
} }

View File

@ -1,3 +1,5 @@
import { jsonError } from "../../common.js";
export async function onRequestPost(context: RequestContext) { export async function onRequestPost(context: RequestContext) {
const { body } = context.data; const { body } = context.data;
@ -5,23 +7,9 @@ export async function onRequestPost(context: RequestContext) {
!Array.isArray(body) || !Array.isArray(body) ||
body.find((attachment) => typeof attachment !== "string") body.find((attachment) => typeof attachment !== "string")
) )
return new Response( return jsonError("Request body must be an array of strings", 400);
'{"error":"Request body must be an array of strings"}',
{
headers: {
"content-type": "application/json",
},
status: 400,
},
);
if (body.length > 3) if (body.length > 3) return jsonError("Too many video ids", 400);
return new Response('{"error":"Too many video ids"}', {
headers: {
"content-type": "application/json",
},
status: 400,
});
const kvPromises = []; const kvPromises = [];
@ -31,12 +19,7 @@ export async function onRequestPost(context: RequestContext) {
const kvResults = await Promise.allSettled(kvPromises); const kvResults = await Promise.allSettled(kvPromises);
if (kvResults.find((result) => result.status === "rejected")) if (kvResults.find((result) => result.status === "rejected"))
return new Response('{"error":"Failed to check status of attachments"}', { return jsonError("Failed to check status of attachments", 500);
headers: {
"content-type": "application/json",
},
status: 500,
});
return new Response(null, { return new Response(null, {
status: kvResults.find((result) => result !== null) ? 409 : 204, status: kvResults.find((result) => result !== null) ? 409 : 204,