Compare commits
6 Commits
930128c0d4
...
5c17f87f89
| Author | SHA1 | Date | |
|---|---|---|---|
|
5c17f87f89
|
|||
|
48631e32be
|
|||
|
b60f211d7b
|
|||
|
1a891e5898
|
|||
|
7b72f815b0
|
|||
|
4860288d11
|
@@ -40,13 +40,15 @@ export async function loader({ context }: { context: RequestContext }) {
|
|||||||
status: 403,
|
status: 403,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { results } = await context.env.D1.prepare(
|
return await context.data.prisma.shortLink.findMany({
|
||||||
"SELECT destination, path FROM short_links WHERE user = ?;",
|
select: {
|
||||||
)
|
destination: true,
|
||||||
.bind(userId)
|
path: true,
|
||||||
.all();
|
},
|
||||||
|
where: {
|
||||||
return results as Record<string, string>[];
|
user: userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { jsonError } from "../../../common.js";
|
import { jsonError } from "../../../common.js";
|
||||||
|
import {
|
||||||
|
Appeal,
|
||||||
|
PushNotification,
|
||||||
|
} from "../../../../generated/prisma/client.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);
|
||||||
@@ -20,22 +24,23 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
context.data.targetId = id;
|
context.data.targetId = id;
|
||||||
|
|
||||||
if (!pathname.endsWith("/ban")) {
|
if (!pathname.endsWith("/ban")) {
|
||||||
const appeal: Record<string, any> | null = await context.env.D1.prepare(
|
const appeal: Appeal | null = await context.data.prisma.appeal.findUnique({
|
||||||
"SELECT * FROM appeals WHERE id = ?;",
|
where: {
|
||||||
)
|
id: id,
|
||||||
.bind(id)
|
},
|
||||||
.first();
|
});
|
||||||
|
|
||||||
if (!appeal) return jsonError("No appeal with that ID exists", 404);
|
if (!appeal) return jsonError("No appeal with that ID exists", 404);
|
||||||
|
|
||||||
appeal.user = JSON.parse(appeal.user);
|
|
||||||
context.data.appeal = appeal;
|
context.data.appeal = appeal;
|
||||||
|
|
||||||
const pushNotificationData = await context.env.D1.prepare(
|
const pushNotificationData: PushNotification | null =
|
||||||
"SELECT token FROM push_notifications WHERE event_id = ? AND event_type = 'appeal';",
|
await context.data.prisma.pushNotification.findUnique({
|
||||||
)
|
where: {
|
||||||
.bind(id)
|
event_id: id,
|
||||||
.first();
|
event_type: "appeal",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (pushNotificationData)
|
if (pushNotificationData)
|
||||||
context.data.fcm_token = pushNotificationData.token;
|
context.data.fcm_token = pushNotificationData.token;
|
||||||
|
|||||||
@@ -13,11 +13,12 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
fcm_token,
|
fcm_token,
|
||||||
);
|
);
|
||||||
|
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.pushNotification.delete({
|
||||||
"DELETE FROM push_notifications WHERE event_id = ? AND event_type = 'appeal';",
|
where: {
|
||||||
)
|
event_id: appeal.id,
|
||||||
.bind(appeal.id)
|
event_type: "appeal",
|
||||||
.run();
|
},
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
const emailResponse = await sendEmail(
|
const emailResponse = await sendEmail(
|
||||||
appeal.user.email,
|
appeal.user.email,
|
||||||
@@ -37,11 +38,8 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
|
|
||||||
const { current_user: currentUser } = context.data;
|
const { current_user: currentUser } = context.data;
|
||||||
|
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma
|
||||||
"UPDATE appeals SET approved = 1, user = json_remove(user, '$.email') WHERE id = ?;",
|
.$executeRaw`UPDATE appeals SET approved = TRUE, user = json_remove(user, '$.id') WHERE id = ${appeal.id};`;
|
||||||
)
|
|
||||||
.bind(context.params.id)
|
|
||||||
.run();
|
|
||||||
|
|
||||||
await fetch(
|
await fetch(
|
||||||
`https://discord.com/api/v10/guilds/242263977986359297/bans/${appeal.user.id}`,
|
`https://discord.com/api/v10/guilds/242263977986359297/bans/${appeal.user.id}`,
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ export async function onRequestDelete(context: RequestContext) {
|
|||||||
if (targetId.search(/^\d{16.19}$/) === -1)
|
if (targetId.search(/^\d{16.19}$/) === -1)
|
||||||
return jsonError("Invalid target id", 400);
|
return jsonError("Invalid target id", 400);
|
||||||
|
|
||||||
await context.env.D1.prepare("DELETE FROM appeal_bans WHERE user = ?;")
|
await context.data.prisma.appealBan.delete({
|
||||||
.bind(targetId)
|
where: {
|
||||||
.run();
|
user: targetId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const { current_user: currentUser } = context.data;
|
const { current_user: currentUser } = context.data;
|
||||||
|
|
||||||
@@ -46,11 +48,12 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
if (targetId.search(/^\d{16,19}$/) === -1)
|
if (targetId.search(/^\d{16,19}$/) === -1)
|
||||||
return jsonError("Invalid target id", 400);
|
return jsonError("Invalid target id", 400);
|
||||||
|
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.appealBan.create({
|
||||||
"INSERT INTO appeal_bans (created_at, created_by, user) VALUES (?, ?, ?);",
|
data: {
|
||||||
)
|
created_by: context.data.current_user.id,
|
||||||
.bind(Date.now(), context.data.current_user.id, targetId)
|
user: targetId,
|
||||||
.run();
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await fetch(context.env.APPEALS_WEBHOOK, {
|
await fetch(context.env.APPEALS_WEBHOOK, {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
|||||||
@@ -6,11 +6,12 @@ export async function onRequestGet(context: RequestContext) {
|
|||||||
if (
|
if (
|
||||||
!currentUser.email ||
|
!currentUser.email ||
|
||||||
(await context.env.DATA.get("appeal_disabled")) ||
|
(await context.env.DATA.get("appeal_disabled")) ||
|
||||||
(await context.env.D1.prepare(
|
(await context.data.prisma.appeal.findFirst({
|
||||||
"SELECT id FROM appeals WHERE open = 1 AND user = ?;",
|
where: {
|
||||||
)
|
approved: null,
|
||||||
.bind(currentUser.id)
|
user: currentUser.id,
|
||||||
.first()) ||
|
},
|
||||||
|
})) ||
|
||||||
(await context.env.DATA.get(`blockedappeal_${currentUser.id}`))
|
(await context.env.DATA.get(`blockedappeal_${currentUser.id}`))
|
||||||
)
|
)
|
||||||
return jsonResponse('{"can_appeal":false}');
|
return jsonResponse('{"can_appeal":false}');
|
||||||
@@ -47,18 +48,24 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
existingBlockedAppeal ||
|
existingBlockedAppeal ||
|
||||||
(await context.env.D1.prepare(
|
(await context.data.prisma.appeal.findFirst({
|
||||||
"SELECT approved FROM appeals WHERE approved IS NULL AND json_extract(user, '$.id') = ?;",
|
where: {
|
||||||
)
|
approved: null,
|
||||||
.bind(currentUser.id)
|
user: {
|
||||||
.first())
|
path: "id",
|
||||||
|
equals: currentUser.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}))
|
||||||
)
|
)
|
||||||
return jsonError("Appeal already submitted", 403);
|
return jsonError("Appeal already submitted", 403);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
await context.env.D1.prepare("SELECT * FROM appeal_bans WHERE user = ?;")
|
await context.data.prisma.appealBan.findUnique({
|
||||||
.bind(currentUser.id)
|
where: {
|
||||||
.first()
|
user: currentUser.id,
|
||||||
|
},
|
||||||
|
})
|
||||||
) {
|
) {
|
||||||
await context.env.DATA.put(`blockedappeal_${currentUser.id}`, "1", {
|
await context.env.DATA.put(`blockedappeal_${currentUser.id}`, "1", {
|
||||||
metadata: { email: currentUser.email },
|
metadata: { email: currentUser.email },
|
||||||
@@ -73,29 +80,28 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
.randomUUID()
|
.randomUUID()
|
||||||
.replaceAll("-", "")}`;
|
.replaceAll("-", "")}`;
|
||||||
|
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.appeal.create({
|
||||||
"INSERT INTO appeals (ban_reason, created_at, id, learned, reason_for_unban, user) VALUES (?, ?, ?, ?, ?, ?);",
|
data: {
|
||||||
)
|
ban_reason: whyBanned,
|
||||||
.bind(
|
id: appealId,
|
||||||
whyBanned,
|
|
||||||
Date.now(),
|
|
||||||
appealId,
|
|
||||||
learned,
|
learned,
|
||||||
whyUnban,
|
reason_for_unban: whyUnban,
|
||||||
JSON.stringify({
|
user: {
|
||||||
email: currentUser.email,
|
email: currentUser.email,
|
||||||
id: currentUser.id,
|
id: currentUser.id,
|
||||||
username: currentUser.username,
|
username: currentUser.username,
|
||||||
}),
|
},
|
||||||
)
|
},
|
||||||
.run();
|
});
|
||||||
|
|
||||||
if (typeof senderTokenId === "string") {
|
if (typeof senderTokenId === "string") {
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.pushNotification.create({
|
||||||
"INSERT INTO push_notifications (created_at, event_id, event_type, token) VALUES (?, ?, 'appeal', ?)",
|
data: {
|
||||||
)
|
event_id: appealId,
|
||||||
.bind(Date.now(), appealId, senderTokenId)
|
event_type: "appeal",
|
||||||
.run();
|
token: senderTokenId,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await fetch(context.env.APPEALS_WEBHOOK, {
|
await fetch(context.env.APPEALS_WEBHOOK, {
|
||||||
|
|||||||
@@ -14,13 +14,27 @@ export async function onRequestGet(context: RequestContext) {
|
|||||||
if (currentYear < year || (currentYear === year && currentMonth < month))
|
if (currentYear < year || (currentYear === year && currentMonth < month))
|
||||||
return jsonError("Cannot get events for a time in the future", 400);
|
return jsonError("Cannot get events for a time in the future", 400);
|
||||||
|
|
||||||
const eventRecords = await context.env.D1.prepare(
|
const eventRecords = await context.data.prisma.event.findMany({
|
||||||
"SELECT answer, approved, created_by, day, details, month, pending, performed_at, type, year FROM events WHERE month = ? AND year = ? ORDER BY day ASC;",
|
select: {
|
||||||
)
|
answer: true,
|
||||||
.bind(month, year)
|
approved: true,
|
||||||
.all();
|
created_by: true,
|
||||||
|
day: true,
|
||||||
|
details: true,
|
||||||
|
month: true,
|
||||||
|
pending: true,
|
||||||
|
performed_at: true,
|
||||||
|
type: true,
|
||||||
|
year: true,
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
month: month,
|
||||||
|
year: year,
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
day: "asc",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (!eventRecords.success) return jsonError("Failed to retrieve events", 400);
|
return jsonResponse(JSON.stringify(eventRecords));
|
||||||
|
|
||||||
return jsonResponse(JSON.stringify(eventRecords.results));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,19 +7,25 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
if (statsReduction && typeof statsReduction !== "number")
|
if (statsReduction && typeof statsReduction !== "number")
|
||||||
return jsonError("Invalid stat reduction", 400);
|
return jsonError("Invalid stat reduction", 400);
|
||||||
|
|
||||||
const appeal: Record<string, any> | null = await context.env.D1.prepare(
|
const appeal = await context.data.prisma.gameAppeal.findUnique({
|
||||||
"SELECT * FROM game_appeals WHERE id = ?;",
|
select: {
|
||||||
)
|
roblox_id: true,
|
||||||
.bind(context.params.id)
|
type: true,
|
||||||
.first();
|
},
|
||||||
|
where: {
|
||||||
|
id: context.params.id as string,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (!appeal) return jsonError("Appeal not found", 400);
|
if (!appeal) return jsonError("Appeal not found", 400);
|
||||||
|
|
||||||
const { etag, value: banList } = await getBanList(context);
|
const { etag, value: banList } = await getBanList(context);
|
||||||
|
|
||||||
await context.env.D1.prepare("DELETE FROM game_appeals WHERE id = ?;")
|
await context.data.prisma.gameAppeal.delete({
|
||||||
.bind(context.params.id)
|
where: {
|
||||||
.run();
|
id: context.params.id as string,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (!banList[appeal.roblox_id]?.BanType)
|
if (!banList[appeal.roblox_id]?.BanType)
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
@@ -46,18 +52,15 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.gameModLog.create({
|
||||||
"INSERT INTO game_mod_logs (action, evidence, executed_at, executor, id, target) VALUES (?, ?, ?, ?, ?, ?);",
|
data: {
|
||||||
)
|
action: `accept appeal | ${banList[appeal.roblox_id]?.BanType === 2 ? "ban" : appeal.type}`,
|
||||||
.bind(
|
evidence: `https://carcrushers.cc/mod-queue?id=${context.params.id}&type=gma`,
|
||||||
`accept appeal | ${banList[appeal.roblox_id]?.BanType === 2 ? "ban" : appeal.type}`,
|
executor: context.data.current_user.id,
|
||||||
`https://carcrushers.cc/mod-queue?id=${context.params.id}&type=gma`,
|
id: crypto.randomUUID(),
|
||||||
Date.now(),
|
target: appeal.roblox_id,
|
||||||
context.data.current_user.id,
|
},
|
||||||
crypto.randomUUID(),
|
});
|
||||||
appeal.roblox_id,
|
|
||||||
)
|
|
||||||
.run();
|
|
||||||
|
|
||||||
await setBanList(context, banList, etag);
|
await setBanList(context, banList, etag);
|
||||||
|
|
||||||
|
|||||||
@@ -2,18 +2,22 @@ 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.data.prisma.gameAppeal.findUnique({
|
||||||
const appeal = await context.env.D1.prepare(
|
select: {
|
||||||
"SELECT * FROM game_appeals WHERE id = ?;",
|
roblox_id: true,
|
||||||
)
|
},
|
||||||
.bind(appealId)
|
where: {
|
||||||
.first();
|
id: appealId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (!appeal) return jsonError("Appeal not found", 404);
|
if (!appeal) return jsonError("Appeal not found", 404);
|
||||||
|
|
||||||
await context.env.D1.prepare("DELETE FROM game_appeals WHERE id = ?;")
|
await context.data.prisma.gameAppeal.delete({
|
||||||
.bind(appealId)
|
where: {
|
||||||
.run();
|
id: appealId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await context.env.DATA.put(
|
await context.env.DATA.put(
|
||||||
`gameappealblock_${appeal.roblox_id}`,
|
`gameappealblock_${appeal.roblox_id}`,
|
||||||
|
|||||||
@@ -10,11 +10,14 @@ export default async function (
|
|||||||
types?: string[];
|
types?: string[];
|
||||||
}> {
|
}> {
|
||||||
if (
|
if (
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.gameAppeal.findFirst({
|
||||||
"SELECT * FROM game_appeals WHERE roblox_id = ?;",
|
select: {
|
||||||
)
|
id: true,
|
||||||
.bind(user)
|
},
|
||||||
.first()
|
where: {
|
||||||
|
roblox_id: user,
|
||||||
|
},
|
||||||
|
})
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
can_appeal: false,
|
can_appeal: false,
|
||||||
@@ -47,22 +50,20 @@ export default async function (
|
|||||||
).toLocaleString()} to submit another appeal`,
|
).toLocaleString()} to submit another appeal`,
|
||||||
};
|
};
|
||||||
|
|
||||||
const userLogs = await context.env.D1.prepare(
|
const userLogs = await context.data.prisma.gameModLog.findMany({
|
||||||
"SELECT action, executed_at FROM game_mod_logs WHERE target = ? ORDER BY executed_at DESC;",
|
select: {
|
||||||
)
|
action: true,
|
||||||
.bind(user)
|
executed_at: true,
|
||||||
.all();
|
},
|
||||||
|
where: {
|
||||||
if (userLogs.error)
|
target: user,
|
||||||
return {
|
},
|
||||||
error: "Could not determine your eligibility",
|
});
|
||||||
};
|
|
||||||
|
|
||||||
// Legacy bans
|
// Legacy bans
|
||||||
if (!userLogs.results.length)
|
if (!userLogs.length) return { can_appeal: true, reason: "", types: ["ban"] };
|
||||||
return { can_appeal: true, reason: "", types: ["ban"] };
|
|
||||||
|
|
||||||
const allowedTime = (userLogs.results[0].executed_at as number) + 2592000000;
|
const allowedTime = new Date(userLogs[0].executed_at).getTime() + 2592000000;
|
||||||
|
|
||||||
if (Date.now() < allowedTime)
|
if (Date.now() < allowedTime)
|
||||||
return {
|
return {
|
||||||
@@ -72,11 +73,7 @@ export default async function (
|
|||||||
).toLocaleString()} to submit an appeal`,
|
).toLocaleString()} to submit an appeal`,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (userLogs.find((r) => r.action.startsWith("accept appeal")))
|
||||||
userLogs.results.find((r: Record<string, any>) =>
|
|
||||||
r.action.startsWith("accept appeal"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return {
|
return {
|
||||||
can_appeal: false,
|
can_appeal: false,
|
||||||
reason: "We do not accept appeals from repeat offenders",
|
reason: "We do not accept appeals from repeat offenders",
|
||||||
|
|||||||
@@ -52,19 +52,16 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
context.request.headers.get("cf-ray")?.split("-")[0]
|
context.request.headers.get("cf-ray")?.split("-")[0]
|
||||||
}${Date.now()}`;
|
}${Date.now()}`;
|
||||||
|
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.gameAppeal.create({
|
||||||
"INSERT INTO game_appeals (created_at, id, reason_for_unban, roblox_id, roblox_username, type, what_happened) VALUES (?, ?, ?, ?, ?, ?, ?);",
|
data: {
|
||||||
)
|
id: appealId,
|
||||||
.bind(
|
reason_for_unban: reasonForUnban,
|
||||||
Date.now(),
|
roblox_id: id,
|
||||||
appealId,
|
roblox_username: username,
|
||||||
reasonForUnban,
|
|
||||||
id,
|
|
||||||
username,
|
|
||||||
type,
|
type,
|
||||||
whatHappened,
|
what_happened: whatHappened,
|
||||||
)
|
},
|
||||||
.run();
|
});
|
||||||
|
|
||||||
await fetch(context.env.REPORTS_WEBHOOK, {
|
await fetch(context.env.REPORTS_WEBHOOK, {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
|||||||
@@ -58,13 +58,14 @@ export async function onRequestGet(context: RequestContext) {
|
|||||||
} else if (banData.BanType === 2) current_status = "Banned";
|
} else if (banData.BanType === 2) current_status = "Banned";
|
||||||
|
|
||||||
const response = {
|
const response = {
|
||||||
history: (
|
history: await context.data.prisma.gameModLog.findMany({
|
||||||
await context.env.D1.prepare(
|
orderBy: {
|
||||||
"SELECT * FROM game_mod_logs WHERE target = ? ORDER BY executed_at DESC;",
|
executed_at: "desc",
|
||||||
)
|
},
|
||||||
.bind(users[0].id)
|
where: {
|
||||||
.all()
|
target: users[0].id,
|
||||||
).results,
|
},
|
||||||
|
}),
|
||||||
user: {
|
user: {
|
||||||
avatar: thumbnailRequest.ok
|
avatar: thumbnailRequest.ok
|
||||||
? (
|
? (
|
||||||
|
|||||||
@@ -18,18 +18,15 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
|
|
||||||
if (isNaN(parseInt(user))) return jsonError("Invalid user ID", 400);
|
if (isNaN(parseInt(user))) return jsonError("Invalid user ID", 400);
|
||||||
|
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.gameModLog.create({
|
||||||
"INSERT INTO game_mod_logs (action, evidence, executed_at, executor, id, target) VALUES (?, ?, ?, ?, ?, ?);",
|
data: {
|
||||||
)
|
action: "revoke",
|
||||||
.bind(
|
evidence: ticket_link,
|
||||||
"revoke",
|
executor: context.data.current_user.id,
|
||||||
ticket_link,
|
id: crypto.randomUUID(),
|
||||||
Date.now(),
|
target: parseInt(user),
|
||||||
context.data.current_user.id,
|
},
|
||||||
crypto.randomUUID(),
|
});
|
||||||
parseInt(user),
|
|
||||||
)
|
|
||||||
.run();
|
|
||||||
|
|
||||||
const { etag, value: banList } = await getBanList(context);
|
const { etag, value: banList } = await getBanList(context);
|
||||||
|
|
||||||
|
|||||||
@@ -2,38 +2,50 @@ import { jsonError, jsonResponse } from "../../../common.js";
|
|||||||
|
|
||||||
export async function onRequestDelete(context: RequestContext) {
|
export async function onRequestDelete(context: RequestContext) {
|
||||||
const noteId = context.params.id as string;
|
const noteId = context.params.id as string;
|
||||||
const creatorIdResult: null | Record<string, string> =
|
const creatorIdResult = await context.data.prisma.gameModNote.findUnique({
|
||||||
await context.env.D1.prepare(
|
select: {
|
||||||
"SELECT created_by FROM game_mod_logs WHERE id = ?;",
|
created_by: true,
|
||||||
)
|
},
|
||||||
.bind(noteId)
|
where: {
|
||||||
.first();
|
id: noteId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (creatorIdResult?.created_by !== context.data.current_user.id)
|
try {
|
||||||
|
await context.data.prisma.gameModNote.delete({
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
created_by: context.data.current_user.id,
|
||||||
|
id: noteId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
return jsonError("Cannot delete notes that are not your own", 403);
|
return jsonError("Cannot delete notes that are not your own", 403);
|
||||||
|
}
|
||||||
await context.env.D1.prepare("DELETE FROM game_mod_logs WHERE id = ?;")
|
|
||||||
.bind(noteId)
|
|
||||||
.first();
|
|
||||||
|
|
||||||
return new Response(null, { status: 204 });
|
return new Response(null, { status: 204 });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function onRequestGet(context: RequestContext) {
|
export async function onRequestGet(context: RequestContext) {
|
||||||
const noteId = context.params.id as string;
|
const noteId = context.params.id as string;
|
||||||
const result = await context.env.D1.prepare(
|
const result = await context.data.prisma.gameModNote.findUnique({
|
||||||
"SELECT * FROM game_mod_notes WHERE id = ?;",
|
where: {
|
||||||
)
|
id: noteId,
|
||||||
.bind(noteId)
|
},
|
||||||
.first();
|
});
|
||||||
|
|
||||||
if (!result) return jsonError("Note not found", 404);
|
if (!result) return jsonError("Note not found", 404);
|
||||||
|
|
||||||
const noteData = structuredClone(result);
|
let noteData = structuredClone(result);
|
||||||
const gmeEntry: null | { time: number; user: string; name: string } =
|
const gmeEntry: null | { time: number; user: string; name: string } =
|
||||||
await context.env.DATA.get(`gamemod_${result.created_by}`, "json");
|
await context.env.DATA.get(`gamemod_${result.created_by}`, "json");
|
||||||
|
|
||||||
if (gmeEntry) noteData.creator_name = gmeEntry.name;
|
if (gmeEntry)
|
||||||
|
noteData = Object.defineProperty(noteData, "creator_name", {
|
||||||
|
value: gmeEntry.name,
|
||||||
|
});
|
||||||
|
|
||||||
return jsonResponse(JSON.stringify(noteData));
|
return jsonResponse(JSON.stringify(noteData));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
import { jsonError, jsonResponse } from "../../common.js";
|
import { jsonError, jsonResponse } from "../../common.js";
|
||||||
import sendEmail from "../../email.js";
|
import sendEmail from "../../email.js";
|
||||||
import { sendPushNotification } from "../../gcloud.js";
|
import { sendPushNotification } from "../../gcloud.js";
|
||||||
|
import { type JsonArray, type JsonObject } from "@prisma/client/runtime/client";
|
||||||
|
|
||||||
export async function onRequestDelete(context: RequestContext) {
|
export async function onRequestDelete(context: RequestContext) {
|
||||||
const result = await context.env.D1.prepare(
|
const result = await context.data.prisma.inactivityNotice.findUnique({
|
||||||
"SELECT json_extract(user, '*.id') AS uid FROM inactivity_notices WHERE id = ?;",
|
select: {
|
||||||
)
|
user: true,
|
||||||
.bind(context.params.id)
|
},
|
||||||
.first();
|
where: {
|
||||||
|
id: context.params.id as string,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (!result) return jsonError("No inactivity notice with that ID", 404);
|
if (!result) return jsonError("No inactivity notice with that ID", 404);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
result.uid !== context.data.current_user.id &&
|
(result.user as JsonObject).id !== context.data.current_user.id &&
|
||||||
!(context.data.current_user.permissions & (1 << 0))
|
!(context.data.current_user.permissions & (1 << 0))
|
||||||
)
|
)
|
||||||
return jsonError(
|
return jsonError(
|
||||||
@@ -39,26 +43,17 @@ export async function onRequestGet(context: RequestContext) {
|
|||||||
)
|
)
|
||||||
return jsonError("Forbidden", 403);
|
return jsonError("Forbidden", 403);
|
||||||
|
|
||||||
const result: Record<
|
const result = await context.data.prisma.inactivityNotice.findUnique({
|
||||||
string,
|
where: {
|
||||||
string | number | { [k: string]: string }
|
id: context.params.id as 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));
|
return jsonResponse(JSON.stringify(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function onRequestPost(context: RequestContext) {
|
export async function onRequestPost(context: RequestContext) {
|
||||||
const { accepted }: { accepted?: boolean } = context.data.body;
|
const { accepted }: { accepted?: any } = context.data.body;
|
||||||
|
|
||||||
if (typeof accepted !== "boolean")
|
if (typeof accepted !== "boolean")
|
||||||
return jsonError("'accepted' must be a boolean", 400);
|
return jsonError("'accepted' must be a boolean", 400);
|
||||||
@@ -77,32 +72,45 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
if (!userAdminDepartments.length)
|
if (!userAdminDepartments.length)
|
||||||
return jsonError("You are not a manager of any departments", 403);
|
return jsonError("You are not a manager of any departments", 403);
|
||||||
|
|
||||||
const requestedNotice: { [k: string]: any } | null =
|
const requestedNotice = await context.data.prisma.inactivityNotice.findUnique(
|
||||||
await context.env.D1.prepare(
|
{
|
||||||
"SELECT decisions, departments, user FROM inactivity_notices WHERE id = ?;",
|
select: {
|
||||||
)
|
decisions: true,
|
||||||
.bind(context.params.id)
|
departments: true,
|
||||||
.first();
|
user: true,
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
id: context.params.id as string,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
if (!requestedNotice)
|
if (!requestedNotice)
|
||||||
return jsonError("Inactivity notices does not exist", 404);
|
return jsonError("Inactivity notices does not exist", 404);
|
||||||
|
|
||||||
const decisions: { [dept: string]: boolean } = JSON.parse(
|
const decisions = requestedNotice.decisions as { [k: string]: boolean };
|
||||||
requestedNotice.decisions,
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const department of userAdminDepartments) {
|
for (const department of userAdminDepartments) {
|
||||||
if (!JSON.parse(requestedNotice.departments).includes(department)) continue;
|
if (!(requestedNotice.departments as JsonArray).includes(department))
|
||||||
|
continue;
|
||||||
decisions[department] = accepted;
|
decisions[department] = accepted;
|
||||||
}
|
}
|
||||||
|
|
||||||
const applicableDepartments = JSON.parse(requestedNotice.departments).length;
|
const applicableDepartments = (requestedNotice.departments as JsonArray)
|
||||||
|
.length;
|
||||||
|
const user = requestedNotice.user as JsonObject;
|
||||||
|
|
||||||
await context.env.D1.prepare(
|
delete user.email;
|
||||||
"UPDATE inactivity_notices SET decisions = ?, user = json_remove(user, '$.email') WHERE id = ?;",
|
|
||||||
)
|
await context.data.prisma.inactivityNotice.update({
|
||||||
.bind(JSON.stringify(decisions), context.params.id)
|
data: {
|
||||||
.run();
|
decisions,
|
||||||
|
user,
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
id: context.params.id as string,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (Object.values(decisions).length === applicableDepartments) {
|
if (Object.values(decisions).length === applicableDepartments) {
|
||||||
const approved =
|
const approved =
|
||||||
@@ -111,11 +119,16 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
const denied =
|
const denied =
|
||||||
Object.values(decisions).filter((d) => !d).length !==
|
Object.values(decisions).filter((d) => !d).length !==
|
||||||
applicableDepartments;
|
applicableDepartments;
|
||||||
const fcmTokenResult: FCMTokenResult | null = await context.env.D1.prepare(
|
const fcmTokenResult =
|
||||||
"SELECT token FROM push_notifications WHERE event_id = ? AND event_type = 'inactivity';",
|
await context.data.prisma.pushNotification.findUnique({
|
||||||
)
|
select: {
|
||||||
.bind(context.params.id)
|
token: true,
|
||||||
.first();
|
},
|
||||||
|
where: {
|
||||||
|
event_id: context.params.id as string,
|
||||||
|
event_type: "inactivity",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (fcmTokenResult) {
|
if (fcmTokenResult) {
|
||||||
let status = "Approved";
|
let status = "Approved";
|
||||||
@@ -132,16 +145,19 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
fcmTokenResult.token,
|
fcmTokenResult.token,
|
||||||
);
|
);
|
||||||
|
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.pushNotification.delete({
|
||||||
"DELETE FROM push_notifications WHERE event_id = ? AND event_type = 'inactivity';",
|
where: {
|
||||||
).bind(context.params.id);
|
event_id: context.params.id as string,
|
||||||
|
event_type: "inactivity",
|
||||||
|
},
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
await sendEmail(
|
await sendEmail(
|
||||||
requestedNotice.user.email,
|
(requestedNotice.user as JsonObject).email as string,
|
||||||
context.env.MAILGUN_API_KEY,
|
context.env.MAILGUN_API_KEY,
|
||||||
`Inactivity Request ${approved ? "Approved" : "Denied"}`,
|
`Inactivity Request ${approved ? "Approved" : "Denied"}`,
|
||||||
`inactivity_${approved ? "approved" : "denied"}`,
|
`inactivity_${approved ? "approved" : "denied"}`,
|
||||||
{ username: requestedNotice.user.username },
|
{ username: (requestedNotice.user as JsonObject).username as string },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,31 +20,31 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
(context.request.headers.get("cf-ray") as string).split("-")[0] +
|
(context.request.headers.get("cf-ray") as string).split("-")[0] +
|
||||||
Date.now().toString();
|
Date.now().toString();
|
||||||
|
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.inactivityNotice.create({
|
||||||
"INSERT INTO inactivity_notices (created_at, departments, end, hiatus, id, reason, start, user) VALUES (?, ?, ?, ?, ?, ?, ?, ?);",
|
data: {
|
||||||
)
|
decisions: {},
|
||||||
.bind(
|
departments,
|
||||||
Date.now(),
|
|
||||||
JSON.stringify(departments),
|
|
||||||
end,
|
end,
|
||||||
typeof hiatus === "boolean" ? Number(hiatus) : 0,
|
hiatus,
|
||||||
inactivityId,
|
id: inactivityId,
|
||||||
reason,
|
reason,
|
||||||
start,
|
start,
|
||||||
JSON.stringify({
|
user: {
|
||||||
id: context.data.current_user.id,
|
id: context.data.current_user.id,
|
||||||
email: context.data.current_user.email,
|
email: context.data.current_user.email,
|
||||||
username: context.data.current_user.username,
|
username: context.data.current_user.username,
|
||||||
}),
|
},
|
||||||
)
|
},
|
||||||
.run();
|
});
|
||||||
|
|
||||||
if (typeof senderTokenId === "string") {
|
if (typeof senderTokenId === "string") {
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.pushNotification.create({
|
||||||
"INSERT INTO push_notifications (created_at, event_id, event_type) VALUES (?, ?, ?);",
|
data: {
|
||||||
)
|
event_id: inactivityId,
|
||||||
.bind(Date.now(), inactivityId, "inactivity")
|
event_type: "inactivity",
|
||||||
.run();
|
token: senderTokenId,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const departmentsToNotify = [];
|
const departmentsToNotify = [];
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
import { jsonError, jsonResponse } from "../../common.js";
|
import { jsonResponse } from "../../common.js";
|
||||||
|
|
||||||
export async function onRequestGet(context: RequestContext) {
|
export async function onRequestGet(context: RequestContext) {
|
||||||
const {
|
return jsonResponse(
|
||||||
results,
|
JSON.stringify(
|
||||||
success,
|
await context.data.prisma.report.findMany({
|
||||||
}: {
|
select: {
|
||||||
results: { id: string }[];
|
created_at: true,
|
||||||
success: boolean;
|
id: true,
|
||||||
} = await context.env.D1.prepare(
|
open: true,
|
||||||
"SELECT created_at, id, open, target_usernames FROM reports WHERE json_extract(user, '$.id') = ? ORDER BY created_at LIMIT 50;",
|
target_usernames: true,
|
||||||
)
|
},
|
||||||
.bind(context.data.current_user.id)
|
where: {
|
||||||
.all();
|
user: {
|
||||||
|
path: "id",
|
||||||
if (!success) return jsonError("Failed to retrieve reports", 500);
|
equals: context.data.current_user.id,
|
||||||
|
},
|
||||||
return jsonResponse(JSON.stringify(results));
|
},
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,10 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
|
|
||||||
await context.env.DATA.delete(`reportprocessing_${id}`);
|
await context.env.DATA.delete(`reportprocessing_${id}`);
|
||||||
|
|
||||||
const value = await context.env.D1.prepare(
|
const value = await context.data.prisma.report.findUnique({
|
||||||
"SELECT id FROM reports WHERE id = ?;",
|
select: { id: true },
|
||||||
)
|
where: { id },
|
||||||
.bind(id)
|
});
|
||||||
.first();
|
|
||||||
|
|
||||||
if (!value) return jsonError("Report is missing", 500);
|
if (!value) return jsonError("Report is missing", 500);
|
||||||
|
|
||||||
|
|||||||
@@ -15,26 +15,27 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
)
|
)
|
||||||
return jsonError("No processing report with that ID found", 404);
|
return jsonError("No processing report with that ID found", 404);
|
||||||
|
|
||||||
const data: Record<string, any> | null = await context.env.D1.prepare(
|
const data = await context.data.prisma.report.findUnique({
|
||||||
"SELECT attachments FROM reports WHERE id = ?;",
|
select: {
|
||||||
)
|
attachments: true,
|
||||||
.bind(id)
|
},
|
||||||
.first();
|
where: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (!data) return jsonError("No report with that ID found", 404);
|
if (!data) return jsonError("No report with that ID found", 404);
|
||||||
|
|
||||||
data.attachments = JSON.parse(data.attachments);
|
|
||||||
|
|
||||||
const accessToken = await GetAccessToken(context.env);
|
const accessToken = await GetAccessToken(context.env);
|
||||||
const attachmentDeletePromises = [];
|
const attachmentDeletePromises = [];
|
||||||
const existingAttachments = [...data.attachments];
|
const existingAttachments = [...(data.attachments as string[])];
|
||||||
|
|
||||||
for (const attachment of existingAttachments) {
|
for (let i = 0; i < existingAttachments.length; i++) {
|
||||||
if (!attachment.startsWith("t/")) data.attachments.push(`t/${attachment}`);
|
if (!existingAttachments[i].startsWith("t/"))
|
||||||
else data.attachments.push(attachment.replace("t/", ""));
|
existingAttachments[i] = existingAttachments[i].replace("t/", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const attachment of data.attachments)
|
for (const attachment of existingAttachments)
|
||||||
attachmentDeletePromises.push(
|
attachmentDeletePromises.push(
|
||||||
fetch(
|
fetch(
|
||||||
`https://storage.googleapis.com/storage/v1/b/portal-carcrushers-cc/o/${encodeURIComponent(
|
`https://storage.googleapis.com/storage/v1/b/portal-carcrushers-cc/o/${encodeURIComponent(
|
||||||
@@ -50,9 +51,11 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await Promise.allSettled(attachmentDeletePromises);
|
await Promise.allSettled(attachmentDeletePromises);
|
||||||
await context.env.D1.prepare("DELETE FROM reports WHERE id = ?;")
|
await context.data.prisma.report.delete({
|
||||||
.bind(id)
|
where: {
|
||||||
.run();
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: 204,
|
status: 204,
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
import { jsonResponse } from "../../common.js";
|
import { jsonResponse } from "../../common.js";
|
||||||
|
|
||||||
export async function onRequestGet(context: RequestContext) {
|
export async function onRequestGet(context: RequestContext) {
|
||||||
const { results } = await context.env.D1.prepare(
|
return jsonResponse(
|
||||||
"SELECT created_at, destination, path FROM short_links WHERE user = ?;",
|
JSON.stringify(
|
||||||
)
|
await context.data.prisma.shortLink.findMany({
|
||||||
.bind(context.data.current_user.id)
|
select: {
|
||||||
.all();
|
created_at: true,
|
||||||
|
destination: true,
|
||||||
return jsonResponse(JSON.stringify(results));
|
path: true,
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
user: context.data.current_user.id,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,14 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
if (typeof path !== "string" || path.length > 256)
|
if (typeof path !== "string" || path.length > 256)
|
||||||
return jsonError("Invalid path", 400);
|
return jsonError("Invalid path", 400);
|
||||||
|
|
||||||
const result = await context.env.D1.prepare(
|
const result = await context.data.prisma.shortLink.findUnique({
|
||||||
"SELECT path FROM short_links WHERE path = ?;",
|
select: {
|
||||||
)
|
path: true,
|
||||||
.bind(path)
|
},
|
||||||
.first();
|
where: {
|
||||||
|
path,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
return jsonError(
|
return jsonError(
|
||||||
@@ -78,11 +81,13 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
400,
|
400,
|
||||||
);
|
);
|
||||||
|
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.shortLink.create({
|
||||||
"INSERT INTO short_links (created_at, destination, path, user) VALUES (?, ?, ?, ?);",
|
data: {
|
||||||
)
|
destination,
|
||||||
.bind(Date.now(), destination, path, context.data.current_user.id)
|
path,
|
||||||
.run();
|
user: context.data.current_user.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: 204,
|
status: 204,
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ model Report {
|
|||||||
model ShortLink {
|
model ShortLink {
|
||||||
created_at DateTime @default(now())
|
created_at DateTime @default(now())
|
||||||
destination String
|
destination String
|
||||||
path String @unique
|
path String @id @unique
|
||||||
user String
|
user String
|
||||||
|
|
||||||
@@map("short_links")
|
@@map("short_links")
|
||||||
|
|||||||
Reference in New Issue
Block a user