Compare commits
45 Commits
930128c0d4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
73b6c85171
|
|||
|
037eb7fcac
|
|||
|
abc1389dbb
|
|||
|
cd566248fd
|
|||
|
3d7e499ec1
|
|||
|
40dd0b5a5c
|
|||
|
229398e401
|
|||
|
a9863f5680
|
|||
|
2e76bd9f28
|
|||
|
171240bc7d
|
|||
|
ffce17d7aa
|
|||
|
06fdfe9d10
|
|||
|
ba643bf986
|
|||
|
12f91dca7d
|
|||
|
b6de1aa462
|
|||
|
b65b62dac5
|
|||
|
0ec5399726
|
|||
|
f0c4e178aa
|
|||
|
6ad4fa0514
|
|||
|
42275fcb0f
|
|||
|
0854d72449
|
|||
|
cb0be09c0d
|
|||
|
16ecab6881
|
|||
|
7d5ec1183c
|
|||
|
96d221be2a
|
|||
|
f5e3e3cca6
|
|||
|
2d9f03c394
|
|||
|
c51b29ce57
|
|||
|
546842c4dd
|
|||
|
1f2a8770a1
|
|||
|
4b15c65092
|
|||
|
b671aefd6e
|
|||
|
f32a7912b4
|
|||
|
da0ce2b188
|
|||
|
6da49d191a
|
|||
|
5457898ff9
|
|||
|
fe206e2fbd
|
|||
|
02cac814da
|
|||
|
f184389ffd
|
|||
|
5c17f87f89
|
|||
|
48631e32be
|
|||
|
b60f211d7b
|
|||
|
1a891e5898
|
|||
|
7b72f815b0
|
|||
|
4860288d11
|
@@ -56,7 +56,7 @@ jobs:
|
|||||||
}'
|
}'
|
||||||
|
|
||||||
- name: Deploy
|
- name: Deploy
|
||||||
run: wrangler pages deploy public --project-name $CLOUDFLARE_PROJECT_NAME
|
run: wrangler pages deploy public --upload-source-maps --project-name $CLOUDFLARE_PROJECT_NAME
|
||||||
|
|
||||||
Sentry-Release:
|
Sentry-Release:
|
||||||
name: Create Sentry Release
|
name: Create Sentry Release
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -37,5 +37,7 @@ public/build
|
|||||||
|
|
||||||
# Wrangler data
|
# Wrangler data
|
||||||
.wrangler
|
.wrangler
|
||||||
|
wrangler.jsonc
|
||||||
|
wrangler.toml
|
||||||
|
|
||||||
/generated/prisma
|
/generated/prisma
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v24.14.0
|
v24.15.0
|
||||||
@@ -40,11 +40,18 @@ export async function loader({ context }: { context: RequestContext }) {
|
|||||||
!Boolean(disabled) &&
|
!Boolean(disabled) &&
|
||||||
!Boolean(await dataKV.get(`blockedappeal_${currentUser.id}`)) &&
|
!Boolean(await dataKV.get(`blockedappeal_${currentUser.id}`)) &&
|
||||||
!Boolean(
|
!Boolean(
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma.appeal.findFirst({
|
||||||
"SELECT * FROM appeals WHERE approved IS NULL AND json_extract(user, '$.id') = ? LIMIT 1;",
|
select: {
|
||||||
)
|
id: true,
|
||||||
.bind(currentUser.id)
|
},
|
||||||
.first(),
|
where: {
|
||||||
|
approved: null,
|
||||||
|
user: {
|
||||||
|
path: "id",
|
||||||
|
equals: currentUser.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
can_toggle:
|
can_toggle:
|
||||||
currentUser.permissions & (1 << 0) || currentUser.permissions & (1 << 11),
|
currentUser.permissions & (1 << 0) || currentUser.permissions & (1 << 11),
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export default function () {
|
|||||||
const [eventType, setEventType] = useState("");
|
const [eventType, setEventType] = useState("");
|
||||||
const [riddleAnswer, setRiddleAnswer] = useState("");
|
const [riddleAnswer, setRiddleAnswer] = useState("");
|
||||||
const [submitSuccess, setSubmitSuccess] = useState(false);
|
const [submitSuccess, setSubmitSuccess] = useState(false);
|
||||||
|
const [disableSubmit, setDisableSubmit] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDatePickerMin(`${new Date().toISOString().split("T").at(0)}`);
|
setDatePickerMin(`${new Date().toISOString().split("T").at(0)}`);
|
||||||
@@ -53,6 +54,7 @@ export default function () {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
async function submit() {
|
async function submit() {
|
||||||
|
setDisableSubmit(true);
|
||||||
let eventResp: Response;
|
let eventResp: Response;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -69,6 +71,7 @@ export default function () {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
});
|
});
|
||||||
} catch {
|
} catch {
|
||||||
|
setDisableSubmit(false);
|
||||||
toast({
|
toast({
|
||||||
description: "Please check your internet and try again",
|
description: "Please check your internet and try again",
|
||||||
isClosable: true,
|
isClosable: true,
|
||||||
@@ -86,6 +89,7 @@ export default function () {
|
|||||||
errorMessage = ((await eventResp.json()) as { error: string }).error;
|
errorMessage = ((await eventResp.json()) as { error: string }).error;
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
|
setDisableSubmit(false);
|
||||||
toast({
|
toast({
|
||||||
description: errorMessage,
|
description: errorMessage,
|
||||||
isClosable: true,
|
isClosable: true,
|
||||||
@@ -150,7 +154,11 @@ export default function () {
|
|||||||
onChange={(e) => setRiddleAnswer(e.target.value)}
|
onChange={(e) => setRiddleAnswer(e.target.value)}
|
||||||
placeholder="Riddle answer"
|
placeholder="Riddle answer"
|
||||||
/>
|
/>
|
||||||
<Button mt="16px" onClick={async () => await submit()}>
|
<Button
|
||||||
|
disabled={disableSubmit}
|
||||||
|
mt="16px"
|
||||||
|
onClick={async () => await submit()}
|
||||||
|
>
|
||||||
Book
|
Book
|
||||||
</Button>
|
</Button>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
import { Button, Container, Heading, Text } from "@chakra-ui/react";
|
|
||||||
|
|
||||||
export default function () {
|
|
||||||
return (
|
|
||||||
<Container maxW="container.md">
|
|
||||||
<Heading size="lg">Transfer your Save Data</Heading>
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<Text>Lost your account? Want to shake off a stalker?</Text>
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<Text size="lg">We can help!</Text>
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<Text>Some information you should know:</Text>
|
|
||||||
<br />
|
|
||||||
<Text>
|
|
||||||
We might require your .ROBLOSECURITY cookie, depending on your
|
|
||||||
circumstances. This is because Roblox does not allow terminated accounts
|
|
||||||
to utilize OAuth. Normally this would be a very bad idea, and we don't
|
|
||||||
like doing this either, but it may be the only option. Security is also
|
|
||||||
less of a concern for terminated accounts as they are blocked from
|
|
||||||
accessing almost all Roblox API endpoints (the exceptions being login,
|
|
||||||
logout, and creating support tickets - and only the logout endpoint
|
|
||||||
doesn't require completing a captcha). If you are concerned about your
|
|
||||||
account's security, we suggest logging in to your terminated account in
|
|
||||||
a private/incognito window, copying the .ROBLOSECURITY cookie from
|
|
||||||
there, and logging out once we have verified your old account (which
|
|
||||||
normally only takes a few seconds). The ultra paranoid may also consider
|
|
||||||
resetting their password. If you are not convinced or still have
|
|
||||||
questions, join our Discord server (link is on the about page) and open
|
|
||||||
a ticket with ModMail for us to verify you manually (no cookie
|
|
||||||
required).
|
|
||||||
</Text>
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<Button as="a" href="/data-transfer/start" colorScheme="blue">
|
|
||||||
Start my Transfer
|
|
||||||
</Button>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import Success from "../../components/Success.js";
|
|
||||||
|
|
||||||
export default function () {
|
|
||||||
return (
|
|
||||||
<Success
|
|
||||||
heading="Data Transfer Submitted"
|
|
||||||
message="Your request is now being processed; this normally takes 1-2 weeks."
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import { Button, Card, Container, Heading, VStack } from "@chakra-ui/react";
|
|
||||||
import { useLoaderData } from "@remix-run/react";
|
|
||||||
|
|
||||||
export async function loader({ context }: { context: RequestContext }) {
|
|
||||||
const { host, protocol } = new URL(context.request.url);
|
|
||||||
|
|
||||||
return { client_id: context.env.ROBLOX_OAUTH_CLIENT_ID, host, protocol };
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function () {
|
|
||||||
const loaderData = useLoaderData<typeof loader>();
|
|
||||||
return (
|
|
||||||
<Container pt="16vh">
|
|
||||||
<Card borderRadius="32px" p="4vh">
|
|
||||||
<VStack alignContent="center" gap="2vh">
|
|
||||||
<Heading>Verify your new Roblox account</Heading>
|
|
||||||
<br />
|
|
||||||
<Button
|
|
||||||
as="a"
|
|
||||||
borderRadius="24px"
|
|
||||||
colorScheme="blue"
|
|
||||||
href={`https://apis.roblox.com/oauth/v1/authorize?client_id=${
|
|
||||||
loaderData.client_id
|
|
||||||
}&redirect_uri=${encodeURIComponent(
|
|
||||||
`${loaderData.protocol}//${loaderData.host}/api/data-transfers/verify`,
|
|
||||||
)}&response_type=code&scope=openid%20profile`}
|
|
||||||
>
|
|
||||||
Verify
|
|
||||||
</Button>
|
|
||||||
</VStack>
|
|
||||||
</Card>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
import {
|
|
||||||
Button,
|
|
||||||
Container,
|
|
||||||
Heading,
|
|
||||||
HStack,
|
|
||||||
Radio,
|
|
||||||
RadioGroup,
|
|
||||||
Text,
|
|
||||||
Textarea,
|
|
||||||
useToast,
|
|
||||||
} from "@chakra-ui/react";
|
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
export default function () {
|
|
||||||
const [showCookieBox, setShowCookieBox] = useState(false);
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
return (
|
|
||||||
<Container maxW="container.md">
|
|
||||||
<Heading pt="36px">Let's get started</Heading>
|
|
||||||
<Text pt="128px">Is your old Roblox account banned?</Text>
|
|
||||||
<RadioGroup onChange={(val) => setShowCookieBox(JSON.parse(val))}>
|
|
||||||
<HStack>
|
|
||||||
<Radio value="false">No</Radio>
|
|
||||||
<Radio value="true">Yes</Radio>
|
|
||||||
</HStack>
|
|
||||||
</RadioGroup>
|
|
||||||
<Textarea
|
|
||||||
id="cookie-box"
|
|
||||||
placeholder="Paste your .ROBLOSECURITY cookie here"
|
|
||||||
mt="16px"
|
|
||||||
style={{ display: showCookieBox ? "initial" : "none" }}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
colorScheme="blue"
|
|
||||||
isLoading={loading}
|
|
||||||
loadingText="Processing..."
|
|
||||||
mt="16px"
|
|
||||||
onClick={async () => {
|
|
||||||
setLoading(true);
|
|
||||||
const createTransferReq = await fetch("/api/data-transfers/create", {
|
|
||||||
body: JSON.stringify({
|
|
||||||
can_access: !showCookieBox,
|
|
||||||
cookie: (
|
|
||||||
document.getElementById("cookie-box") as HTMLInputElement
|
|
||||||
).value,
|
|
||||||
}),
|
|
||||||
headers: {
|
|
||||||
"content-type": "application/json",
|
|
||||||
},
|
|
||||||
method: "POST",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!createTransferReq.ok) {
|
|
||||||
setLoading(false);
|
|
||||||
useToast()({
|
|
||||||
description: (
|
|
||||||
(await createTransferReq.json()) as { error: string }
|
|
||||||
).error,
|
|
||||||
isClosable: true,
|
|
||||||
status: "error",
|
|
||||||
title: "Failed to create transfer request",
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
location.assign(
|
|
||||||
((await createTransferReq.json()) as { url: string }).url,
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Continue
|
|
||||||
</Button>
|
|
||||||
<br />
|
|
||||||
<Text pt="16px">
|
|
||||||
If you cannot login at all, please visit the support page and join our
|
|
||||||
server.
|
|
||||||
</Text>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -271,7 +271,7 @@ export default function () {
|
|||||||
|
|
||||||
// Technically this won't be the same as the time in the db, but that doesn't matter since this is just to hide the button
|
// Technically this won't be the same as the time in the db, but that doesn't matter since this is just to hide the button
|
||||||
newEventData[eventData.findIndex((e) => e.id === eventId)].performed_at =
|
newEventData[eventData.findIndex((e) => e.id === eventId)].performed_at =
|
||||||
Date.now();
|
new Date().toISOString();
|
||||||
|
|
||||||
setEventData([...newEventData]);
|
setEventData([...newEventData]);
|
||||||
setSelectedEvent("");
|
setSelectedEvent("");
|
||||||
@@ -313,7 +313,8 @@ export default function () {
|
|||||||
|
|
||||||
const newEventData = eventData;
|
const newEventData = eventData;
|
||||||
|
|
||||||
newEventData[eventData.findIndex((e) => e.id === eventId)].performed_at = 0;
|
newEventData[eventData.findIndex((e) => e.id === eventId)].performed_at =
|
||||||
|
new Date(0).toISOString();
|
||||||
setEventData([...newEventData]);
|
setEventData([...newEventData]);
|
||||||
setSelectedEvent("");
|
setSelectedEvent("");
|
||||||
setDisableClicks(false);
|
setDisableClicks(false);
|
||||||
@@ -664,9 +665,7 @@ export default function () {
|
|||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
{can_approve &&
|
{can_approve && !event.pending && !event.performed_at ? (
|
||||||
!event.pending &&
|
|
||||||
typeof event.performed_at !== "number" ? (
|
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
colorScheme="blue"
|
colorScheme="blue"
|
||||||
|
|||||||
@@ -268,6 +268,7 @@ export default function () {
|
|||||||
element: (
|
element: (
|
||||||
<AppealCard
|
<AppealCard
|
||||||
{...(entry as AppealCardProps & { port?: MessagePort })}
|
{...(entry as AppealCardProps & { port?: MessagePort })}
|
||||||
|
key={`appeal_${entry.id}`}
|
||||||
port={messageChannel.current?.port2}
|
port={messageChannel.current?.port2}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -281,6 +282,7 @@ export default function () {
|
|||||||
element: (
|
element: (
|
||||||
<GameAppealCard
|
<GameAppealCard
|
||||||
{...(entry as GameAppealProps & { port?: MessagePort })}
|
{...(entry as GameAppealProps & { port?: MessagePort })}
|
||||||
|
key={`gma_${entry.id}`}
|
||||||
port={messageChannel.current?.port2}
|
port={messageChannel.current?.port2}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -294,6 +296,7 @@ export default function () {
|
|||||||
element: (
|
element: (
|
||||||
<InactivityNoticeCard
|
<InactivityNoticeCard
|
||||||
{...(entry as InactivityNoticeProps & { port?: MessagePort })}
|
{...(entry as InactivityNoticeProps & { port?: MessagePort })}
|
||||||
|
key={`inactivity_${entry.id}`}
|
||||||
port={messageChannel.current?.port2}
|
port={messageChannel.current?.port2}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -307,6 +310,7 @@ export default function () {
|
|||||||
element: (
|
element: (
|
||||||
<ReportCard
|
<ReportCard
|
||||||
{...(entry as ReportCardProps & { port?: MessagePort })}
|
{...(entry as ReportCardProps & { port?: MessagePort })}
|
||||||
|
key={`report_${entry.id}`}
|
||||||
port={messageChannel.current?.port2}
|
port={messageChannel.current?.port2}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
Textarea,
|
Textarea,
|
||||||
|
useMultiStyleConfig,
|
||||||
useToast,
|
useToast,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
@@ -50,6 +51,9 @@ export default function () {
|
|||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const [uploading, setUploading] = useState(false);
|
const [uploading, setUploading] = useState(false);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const inputSelectorProps = useMultiStyleConfig("Button", {
|
||||||
|
colorScheme: "blue",
|
||||||
|
});
|
||||||
const fileTypes: { [k: string]: string } = {
|
const fileTypes: { [k: string]: string } = {
|
||||||
avif: "image/avif",
|
avif: "image/avif",
|
||||||
gif: "image/gif",
|
gif: "image/gif",
|
||||||
@@ -112,9 +116,9 @@ export default function () {
|
|||||||
if (!logged_in) {
|
if (!logged_in) {
|
||||||
const tokenElem = document
|
const tokenElem = document
|
||||||
.getElementsByName("cf-turnstile-response")
|
.getElementsByName("cf-turnstile-response")
|
||||||
.item(0) as HTMLInputElement;
|
.item(0) as HTMLInputElement | null;
|
||||||
|
|
||||||
if (!tokenElem.value) {
|
if (!tokenElem?.value) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return toast({
|
return toast({
|
||||||
description: "Please complete the captcha and try again",
|
description: "Please complete the captcha and try again",
|
||||||
@@ -250,8 +254,8 @@ export default function () {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
});
|
});
|
||||||
|
|
||||||
setShowSuccess(true);
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
setShowSuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -304,14 +308,19 @@ export default function () {
|
|||||||
<br />
|
<br />
|
||||||
<FormControl isRequired>
|
<FormControl isRequired>
|
||||||
<FormLabel>Your Evidence (Max size per file: 512MB)</FormLabel>
|
<FormLabel>Your Evidence (Max size per file: 512MB)</FormLabel>
|
||||||
<Button
|
<Input
|
||||||
colorScheme="blue"
|
border="none"
|
||||||
mr="8px"
|
id="evidence"
|
||||||
onClick={() => document.getElementById("evidence")?.click()}
|
sx={{
|
||||||
>
|
"::file-selector-button": {
|
||||||
Select File
|
border: "none",
|
||||||
</Button>
|
outline: "none",
|
||||||
<input id="evidence" multiple type="file" />
|
...inputSelectorProps,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
multiple={true}
|
||||||
|
type="file"
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<br />
|
<br />
|
||||||
<FormControl>
|
<FormControl>
|
||||||
|
|||||||
@@ -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 () {
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export default function (props: { isOpen: boolean; onClose: () => void }) {
|
|||||||
</Thead>
|
</Thead>
|
||||||
<Tbody>
|
<Tbody>
|
||||||
{entries.map((entry) => (
|
{entries.map((entry) => (
|
||||||
<Tr>
|
<Tr key={`appealban_${entry.user}`}>
|
||||||
<Td>{entry.user}</Td>
|
<Td>{entry.user}</Td>
|
||||||
<Td>{entry.created_by}</Td>
|
<Td>{entry.created_by}</Td>
|
||||||
<Td>{new Date(entry.created_at).toUTCString()}</Td>
|
<Td>{new Date(entry.created_at).toUTCString()}</Td>
|
||||||
|
|||||||
@@ -173,7 +173,6 @@ export default function (props: {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
@@ -223,7 +222,6 @@ export default function (props: {
|
|||||||
{data.id ? data.username : ""}
|
{data.id ? data.username : ""}
|
||||||
</Text>
|
</Text>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
|
|||||||
@@ -17,13 +17,7 @@ export default function ({
|
|||||||
>
|
>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
<svg
|
<svg width="128" height="128" fill="currentColor" viewBox="0 0 16 16">
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="128"
|
|
||||||
height="128"
|
|
||||||
fill="currentColor"
|
|
||||||
viewBox="0 0 16 16"
|
|
||||||
>
|
|
||||||
<path d="M2.5 8a5.5 5.5 0 0 1 8.25-4.764.5.5 0 0 0 .5-.866A6.5 6.5 0 1 0 14.5 8a.5.5 0 0 0-1 0 5.5 5.5 0 1 1-11 0z" />
|
<path d="M2.5 8a5.5 5.5 0 0 1 8.25-4.764.5.5 0 0 0 .5-.866A6.5 6.5 0 1 0 14.5 8a.5.5 0 0 0-1 0 5.5 5.5 0 1 1-11 0z" />
|
||||||
<path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l7-7z" />
|
<path d="M15.354 3.354a.5.5 0 0 0-.708-.708L8 9.293 5.354 6.646a.5.5 0 1 0-.708.708l3 3a.5.5 0 0 0 .708 0l7-7z" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
@@ -14,11 +14,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,
|
||||||
@@ -36,11 +37,8 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.env.D1.prepare(
|
await context.data.prisma
|
||||||
"UPDATE appeals SET approved = 0, user = json_remove(user, '$.email') WHERE id = ?;",
|
.$executeRaw`UPDATE appeals SET approved = FALSE, user = json_remove(user, '$.id') WHERE id = ${appeal.id};`;
|
||||||
)
|
|
||||||
.bind(context.params.id)
|
|
||||||
.run();
|
|
||||||
|
|
||||||
const { current_user: currentUser } = context.data;
|
const { current_user: currentUser } = context.data;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
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(
|
const results = await context.data.prisma.appealBan.findMany({
|
||||||
"SELECT * FROM appeal_bans ORDER BY created_by DESC;",
|
orderBy: {
|
||||||
).all();
|
created_at: "desc",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return jsonResponse(JSON.stringify(results));
|
return jsonResponse(JSON.stringify(results));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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, {
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
export async function onRequest(context: RequestContext) {
|
|
||||||
const cookies = context.request.headers.get("cookie");
|
|
||||||
|
|
||||||
if (!cookies) return await context.next();
|
|
||||||
|
|
||||||
const cookieList = cookies.split("; ").map((cookie: string) => {
|
|
||||||
const [name, value] = cookie.split("=");
|
|
||||||
|
|
||||||
return { name, value };
|
|
||||||
});
|
|
||||||
|
|
||||||
const transferId = cookieList.find(
|
|
||||||
(cookie: { name: string; value: string }) => cookie.name === "__dtid",
|
|
||||||
);
|
|
||||||
|
|
||||||
if (transferId) context.data.data_transfer_id = transferId;
|
|
||||||
|
|
||||||
return await context.next();
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
import { jsonError } from "../../common.js";
|
|
||||||
|
|
||||||
export async function onRequestPost(context: RequestContext) {
|
|
||||||
const { cookie, is_banned } = context.data.body;
|
|
||||||
|
|
||||||
if (
|
|
||||||
typeof is_banned !== "boolean" ||
|
|
||||||
(is_banned && typeof cookie !== "string") ||
|
|
||||||
(is_banned &&
|
|
||||||
!cookie.match(
|
|
||||||
/_\|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 jsonError("Invalid request", 400);
|
|
||||||
|
|
||||||
const id =
|
|
||||||
(context.request.headers.get("cf-ray")?.split("-")[0] as string) +
|
|
||||||
Date.now().toString() +
|
|
||||||
crypto.randomUUID().replaceAll("-", "");
|
|
||||||
|
|
||||||
if (!is_banned) {
|
|
||||||
await context.env.DATA.put(`datatransfer_${id}`, "{}", {
|
|
||||||
expirationTtl: 3600,
|
|
||||||
});
|
|
||||||
|
|
||||||
const host = context.request.headers.get("Host") as string;
|
|
||||||
|
|
||||||
return new Response(
|
|
||||||
`{"url":"https://apis.roblox.com/oauth/v1/authorize?client_id=${
|
|
||||||
context.env.ROBLOX_OAUTH_CLIENT_ID
|
|
||||||
}&redirect_uri=${encodeURIComponent(
|
|
||||||
`http${host.startsWith(
|
|
||||||
"localhost" ? "" : "s",
|
|
||||||
)}://${host}/api/data-transfers/verify`,
|
|
||||||
)}"}`,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"set-cookie": `__dtid=${id}; HttpOnly; Max-Age=3600; Path=/; SameSite=Lax; Secure`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const authedUserReq = await fetch(
|
|
||||||
"https://users.roblox.com/v1/users/authenticated",
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
cookie: `.ROBLOSECURITY=${cookie}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!authedUserReq.ok) return jsonError("Cookie is invalid", 400);
|
|
||||||
|
|
||||||
const authedUser: { id: number; name: string } = await authedUserReq.json();
|
|
||||||
|
|
||||||
await context.env.DATA.put(
|
|
||||||
`datatransfer_${id}`,
|
|
||||||
JSON.stringify({
|
|
||||||
oldUser: authedUser,
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
expirationTtl: 3600,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return new Response(null, {
|
|
||||||
headers: {
|
|
||||||
location: "/data-transfer/destination-account",
|
|
||||||
"set-cookie": `__dtid=${id}; HttpOnly; Max-Age=3600; Path=/; SameSite=Lax; Secure`,
|
|
||||||
},
|
|
||||||
status: 201,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
import { jsonError } from "../../common.js";
|
|
||||||
import { getBanList } from "../../roblox-open-cloud.js";
|
|
||||||
|
|
||||||
export async function onRequestGet(context: RequestContext) {
|
|
||||||
const code = new URL(context.request.url).searchParams.get("code");
|
|
||||||
|
|
||||||
if (!code) return jsonError("Missing code", 400);
|
|
||||||
|
|
||||||
const dataTransferData = (await context.env.DATA.get(
|
|
||||||
`datatransfer_${context.data.data_transfer_id}`,
|
|
||||||
{ type: "json" },
|
|
||||||
)) as { [k: string]: any } | null;
|
|
||||||
|
|
||||||
if (!dataTransferData)
|
|
||||||
return jsonError("No transfer exists with that ID", 404);
|
|
||||||
|
|
||||||
const exchangeReq = await fetch("https://apis.roblox.com/oauth/v1/token", {
|
|
||||||
body: `code=${code}&grant_type=authorization_code`,
|
|
||||||
headers: {
|
|
||||||
authorization: `Basic ${
|
|
||||||
btoa(context.env.ROBLOX_OAUTH_ID) +
|
|
||||||
":" +
|
|
||||||
context.env.ROBLOX_OAUTH_SECRET
|
|
||||||
}`,
|
|
||||||
"content-type": "application/x-www-form-urlencoded",
|
|
||||||
},
|
|
||||||
method: "POST",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!exchangeReq.ok) return jsonError("Failed to redeem code", 500);
|
|
||||||
|
|
||||||
const { id_token } = (await exchangeReq.json()) as { id_token: string };
|
|
||||||
|
|
||||||
const { name, preferred_username, sub } = JSON.parse(
|
|
||||||
atob(id_token.replaceAll("-", "+").replaceAll("_", "/")),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!preferred_username) return jsonError("Username missing", 500);
|
|
||||||
|
|
||||||
const userObj = {
|
|
||||||
displayName: name,
|
|
||||||
id: parseInt(sub),
|
|
||||||
name: preferred_username,
|
|
||||||
};
|
|
||||||
|
|
||||||
let redirectLocation = "/data-transfer/complete";
|
|
||||||
|
|
||||||
if (dataTransferData.oldUser) {
|
|
||||||
let banList;
|
|
||||||
|
|
||||||
try {
|
|
||||||
banList = (await getBanList(context)).value;
|
|
||||||
} catch {
|
|
||||||
return jsonError("Failed to create data transfer request", 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (banList[userObj.id].BanType)
|
|
||||||
return new Response(null, {
|
|
||||||
headers: {
|
|
||||||
location: redirectLocation,
|
|
||||||
},
|
|
||||||
status: 302,
|
|
||||||
});
|
|
||||||
|
|
||||||
dataTransferData.newUser = userObj;
|
|
||||||
|
|
||||||
await fetch(
|
|
||||||
`https://api.trello.com/1/cards?key=${context.env.TRELLO_API_KEY}&token=${context.env.TRELLO_API_TOKEN}`,
|
|
||||||
{
|
|
||||||
body: JSON.stringify({
|
|
||||||
desc: `${dataTransferData.oldUser.name} -> ${userObj.name}\n${dataTransferData.oldUser.id} -> ${userObj.id}\nNO MODMAIL TICKET - WEBSITE FORM SUBMISSION`,
|
|
||||||
idList: context.env.TRELLO_LIST_ID,
|
|
||||||
name: `${dataTransferData.oldUser.name} | Data Transfer`,
|
|
||||||
}),
|
|
||||||
headers: {
|
|
||||||
"content-type": "application/json",
|
|
||||||
},
|
|
||||||
method: "POST",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
dataTransferData.oldUser = userObj;
|
|
||||||
redirectLocation = "/data-transfer/destination-account";
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Response(null, {
|
|
||||||
headers: {
|
|
||||||
location: redirectLocation,
|
|
||||||
},
|
|
||||||
status: 302,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -23,7 +23,7 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
await D1.batch([
|
await D1.batch([
|
||||||
D1.prepare(
|
D1.prepare(
|
||||||
"UPDATE events SET performed_at = CURRENT_TIMESTAMP WHERE id = ?;",
|
"UPDATE events SET performed_at = CURRENT_TIMESTAMP WHERE id = ?;",
|
||||||
).bind(Date.now(), event.id),
|
).bind(event.id),
|
||||||
D1.prepare(
|
D1.prepare(
|
||||||
"UPDATE et_members SET points = points + 10 WHERE id = ?;",
|
"UPDATE et_members SET points = points + 10 WHERE id = ?;",
|
||||||
).bind(event.created_by),
|
).bind(event.created_by),
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,37 @@
|
|||||||
import { jsonError } from "../../../common.js";
|
import { jsonError } from "../../../common.js";
|
||||||
|
import { getBanList } from "../../../roblox-open-cloud.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,
|
||||||
)
|
type: true,
|
||||||
.bind(appealId)
|
},
|
||||||
.first();
|
where: {
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { value: banList } = await getBanList(context);
|
||||||
|
|
||||||
|
await context.data.prisma.gameModLog.create({
|
||||||
|
data: {
|
||||||
|
action: `deny appeal | ${banList[appeal.roblox_id]?.BanType === 2 ? "ban" : appeal.type}`,
|
||||||
|
evidence: `https://carcrushers.cc/mod-queue?id=${context.params.id}&type=gma`,
|
||||||
|
executor: context.data.current_user.id,
|
||||||
|
id: crypto.randomUUID(),
|
||||||
|
target: appeal.roblox_id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
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({
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export async function onRequestGet(context: RequestContext) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!robloxUserReq.ok) {
|
if (!robloxUserReq.ok) {
|
||||||
console.log(await robloxUserReq.json());
|
console.log(await robloxUserReq.text());
|
||||||
return jsonError("Failed to resolve username", 500);
|
return jsonError("Failed to resolve username", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,20 +1,20 @@
|
|||||||
import { jsonError, jsonResponse } from "../../common.js";
|
import { jsonResponse } from "../../common.js";
|
||||||
|
|
||||||
export async function onRequestGet(context: RequestContext) {
|
export async function onRequestGet(context: RequestContext) {
|
||||||
const { results, success } = await context.env.D1.prepare(
|
|
||||||
"SELECT approved, created_at, id, open FROM appeals WHERE user = ?;",
|
|
||||||
)
|
|
||||||
.bind(context.data.current_user.id)
|
|
||||||
.all();
|
|
||||||
|
|
||||||
if (!success) return jsonError("Unable to retrieve appeals", 500);
|
|
||||||
|
|
||||||
return jsonResponse(
|
return jsonResponse(
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
results.map((result) => {
|
await context.data.prisma.appeal.findMany({
|
||||||
result.user = JSON.parse(result.user as string);
|
select: {
|
||||||
|
approved: true,
|
||||||
return result;
|
created_at: true,
|
||||||
|
id: true,
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
user: {
|
||||||
|
path: "id",
|
||||||
|
equals: context.data.current_user.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { jsonError, jsonResponse } from "../../../../common.js";
|
import { jsonError, jsonResponse } from "../../../../common.js";
|
||||||
|
import {
|
||||||
|
type JsonArray,
|
||||||
|
type JsonObject,
|
||||||
|
} from "../../../../../generated/prisma/internal/prismaNamespace.js";
|
||||||
|
|
||||||
export async function onRequestGet(context: RequestContext) {
|
export async function onRequestGet(context: RequestContext) {
|
||||||
const { id, type } = context.params;
|
const { id, type } = context.params;
|
||||||
@@ -6,57 +10,68 @@ export async function onRequestGet(context: RequestContext) {
|
|||||||
if (!["appeal", "inactivity", "report"].includes(type as string))
|
if (!["appeal", "inactivity", "report"].includes(type as string))
|
||||||
return jsonError("Invalid type", 400);
|
return jsonError("Invalid type", 400);
|
||||||
|
|
||||||
const tables: { [k: string]: string } = {
|
const { prisma } = context.data;
|
||||||
appeal: "appeals",
|
let item;
|
||||||
inactivity: "inactivity_notices",
|
|
||||||
report: "reports",
|
|
||||||
};
|
|
||||||
|
|
||||||
const data: Record<string, any> | null = await context.env.D1.prepare(
|
switch (type as string) {
|
||||||
`SELECT *
|
case "appeal":
|
||||||
FROM ${tables[type as string]}
|
item = await prisma.appeal.findUnique({
|
||||||
WHERE id = ?;`,
|
where: {
|
||||||
|
id: id as string,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "inactivity":
|
||||||
|
item = await prisma.inactivityNotice.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id as string,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "report":
|
||||||
|
item = await prisma.report.findUnique({
|
||||||
|
where: {
|
||||||
|
id: id as string,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!item) break;
|
||||||
|
|
||||||
|
const { AwsClient } = await import("aws4fetch");
|
||||||
|
const aws = new AwsClient({
|
||||||
|
accessKeyId: context.env.R2_ACCESS_KEY,
|
||||||
|
secretAccessKey: context.env.R2_SECRET_KEY,
|
||||||
|
});
|
||||||
|
let urlPromises = [];
|
||||||
|
for (const attachment of item.attachments as JsonArray) {
|
||||||
|
urlPromises.push(
|
||||||
|
aws.sign(
|
||||||
|
`https://car-crushers.${context.env.R2_ZONE}.r2.cloudflarestorage.com/${attachment}?X-Amz-Expires=1800`,
|
||||||
|
{
|
||||||
|
aws: {
|
||||||
|
signQuery: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const urls = (await Promise.all(urlPromises)).map((p) => p.url);
|
||||||
|
item = { ...item, resolved_attachments: urls };
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!item ||
|
||||||
|
(item.user as JsonObject | undefined)?.id !== context.data.current_user.id
|
||||||
)
|
)
|
||||||
.bind(id)
|
|
||||||
.first();
|
|
||||||
|
|
||||||
if (data?.user) data.user = JSON.parse(data.user);
|
|
||||||
|
|
||||||
if (!data || data.user?.id !== context.data.current_user.id)
|
|
||||||
return jsonError("Item does not exist", 404);
|
return jsonError("Item does not exist", 404);
|
||||||
|
|
||||||
if (type === "inactivity") {
|
return jsonResponse(JSON.stringify(item));
|
||||||
data.decisions = JSON.parse(data.decisions);
|
|
||||||
data.departments = JSON.parse(data.departments);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === "report") {
|
|
||||||
data.attachments = JSON.parse(data.attachments);
|
|
||||||
data.target_ids = JSON.parse(data.target_ids);
|
|
||||||
data.target_usernames = JSON.parse(data.target_usernames);
|
|
||||||
const { AwsClient } = await import("aws4fetch");
|
|
||||||
const aws = new AwsClient({
|
|
||||||
accessKeyId: context.env.R2_ACCESS_KEY,
|
|
||||||
secretAccessKey: context.env.R2_SECRET_KEY,
|
|
||||||
});
|
|
||||||
|
|
||||||
let urls = [];
|
|
||||||
|
|
||||||
for (const attachment of data.attachments) {
|
|
||||||
const { url } = await aws.sign(
|
|
||||||
`https://car-crushers.${context.env.R2_ZONE}.r2.cloudflarestorage.com/${attachment}?X-Amz-Expires=1800`,
|
|
||||||
{
|
|
||||||
aws: {
|
|
||||||
signQuery: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
urls.push(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
data.resolved_attachments = urls;
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsonResponse(JSON.stringify(data));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
},
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +1,71 @@
|
|||||||
import { jsonError, jsonResponse } from "../../../common.js";
|
import { jsonError, jsonResponse } from "../../../common.js";
|
||||||
|
import { type JsonObject } from "../../../../generated/prisma/internal/prismaNamespace.js";
|
||||||
|
|
||||||
export async function onRequestGet(context: RequestContext) {
|
export async function onRequestGet(context: RequestContext) {
|
||||||
const types: {
|
const types: { [k: string]: number[] } = {
|
||||||
[k: string]: { permissions: number[]; table: string };
|
appeal: [1 << 0, 1 << 11],
|
||||||
} = {
|
gma: [1 << 5],
|
||||||
appeal: {
|
inactivity: [1 << 0, 1 << 4, 1 << 6, 1 << 7, 1 << 11],
|
||||||
permissions: [1 << 0, 1 << 11],
|
report: [1 << 5],
|
||||||
table: "appeals",
|
|
||||||
},
|
|
||||||
gma: {
|
|
||||||
permissions: [1 << 5],
|
|
||||||
table: "game_appeals",
|
|
||||||
},
|
|
||||||
inactivity: {
|
|
||||||
permissions: [1 << 0, 1 << 4, 1 << 6, 1 << 7, 1 << 11],
|
|
||||||
table: "inactivity_notices",
|
|
||||||
},
|
|
||||||
report: {
|
|
||||||
permissions: [1 << 5],
|
|
||||||
table: "reports",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const type = context.params.type as string;
|
const type = context.params.type as string;
|
||||||
const itemId = context.params.id as string;
|
const itemId = context.params.id as string;
|
||||||
|
|
||||||
if (
|
if (!types[type]?.find((p) => context.data.current_user.permissions & p))
|
||||||
!types[type]?.permissions.find(
|
|
||||||
(p) => context.data.current_user.permissions & p,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return jsonError("You cannot use this filter", 403);
|
return jsonError("You cannot use this filter", 403);
|
||||||
|
|
||||||
const item: Record<string, any> | null = await context.env.D1.prepare(
|
let item;
|
||||||
`SELECT *
|
|
||||||
FROM ${types[type].table}
|
switch (type) {
|
||||||
WHERE id = ?;`,
|
case "appeal":
|
||||||
)
|
item = await context.data.prisma.appeal.findUnique({
|
||||||
.bind(itemId)
|
where: {
|
||||||
.first();
|
id: itemId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (item) delete (item.user as JsonObject).email;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "gma":
|
||||||
|
item = await context.data.prisma.gameAppeal.findUnique({
|
||||||
|
where: {
|
||||||
|
id: itemId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "inactivity":
|
||||||
|
item = await context.data.prisma.inactivityNotice.findUnique({
|
||||||
|
where: {
|
||||||
|
id: itemId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (item) delete (item.user as JsonObject).email;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "report":
|
||||||
|
item = await context.data.prisma.report.findUnique({
|
||||||
|
where: {
|
||||||
|
id: itemId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (item) delete (item.user as JsonObject | null)?.email;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return jsonError("Unknown filter", 400);
|
||||||
|
}
|
||||||
|
|
||||||
if (!item) return jsonError("Item not found", 404);
|
if (!item) return jsonError("Item not found", 404);
|
||||||
|
|
||||||
if (type === "report") {
|
if (type === "report") {
|
||||||
if (await context.env.DATA.get(`reportprocessing_${itemId}`))
|
if (await context.env.DATA.get(`reportprocessing_${itemId}`))
|
||||||
return jsonError("Report is processing", 409);
|
return jsonError("Report is processing", 409);
|
||||||
|
|
||||||
item.attachments = JSON.parse(item.attachments);
|
|
||||||
item.target_ids = JSON.parse(item.target_ids);
|
|
||||||
item.target_usernames = JSON.parse(item.target_usernames);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.user) {
|
return jsonResponse(JSON.stringify(item));
|
||||||
item.user = JSON.parse(item.user);
|
|
||||||
|
|
||||||
delete item.user.email;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === "inactivity") {
|
|
||||||
item.decisions = JSON.parse(item.decisions);
|
|
||||||
item.departments = JSON.parse(item.departments);
|
|
||||||
}
|
|
||||||
|
|
||||||
return item
|
|
||||||
? jsonResponse(JSON.stringify(item))
|
|
||||||
: jsonError("Not found", 404);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import { jsonError, jsonResponse } from "../../../common.js";
|
import { jsonError, jsonResponse } from "../../../common.js";
|
||||||
|
import { InactivityNotice } from "../../../../generated/prisma/client.js";
|
||||||
|
import {
|
||||||
|
JsonObject,
|
||||||
|
raw,
|
||||||
|
} from "../../../../generated/prisma/internal/prismaNamespace.js";
|
||||||
|
|
||||||
export async function onRequestGet(context: RequestContext): Promise<any> {
|
export async function onRequestGet(context: RequestContext): Promise<any> {
|
||||||
const type = context.params.type as string;
|
const type = context.params.type as string;
|
||||||
|
const { prisma } = context.data;
|
||||||
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()}`);
|
||||||
const showClosed = searchParams.get("showClosed") === "true";
|
const showClosed = searchParams.get("showClosed") === "true";
|
||||||
@@ -26,73 +32,77 @@ export async function onRequestGet(context: RequestContext): Promise<any> {
|
|||||||
|
|
||||||
if (isNaN(before)) return jsonError("Invalid `before` parameter", 400);
|
if (isNaN(before)) return jsonError("Invalid `before` parameter", 400);
|
||||||
|
|
||||||
let rows: D1Result<Record<string, any>>;
|
let rows;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "appeal":
|
case "appeal":
|
||||||
rows = await context.env.D1.prepare(
|
rows = await prisma.appeal.findMany({
|
||||||
`SELECT *
|
orderBy: {
|
||||||
FROM appeals
|
created_at: "desc",
|
||||||
WHERE created_at < ?
|
},
|
||||||
AND approved ${showClosed ? "IS NOT" : "IS"} NULL
|
take: 25,
|
||||||
ORDER BY created_at DESC LIMIT 25;`,
|
where: {
|
||||||
)
|
created_at: {
|
||||||
.bind(before)
|
lt: new Date(before),
|
||||||
.all();
|
},
|
||||||
rows.results = rows.results.map((r) => {
|
approved: showClosed ? { not: null } : null,
|
||||||
r.user = JSON.parse(r.user);
|
},
|
||||||
delete r.user.email;
|
});
|
||||||
|
rows.map((r) => {
|
||||||
|
delete (r.user as JsonObject).email;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "gma":
|
case "gma":
|
||||||
rows = await context.env.D1.prepare(
|
rows = await prisma.gameAppeal.findMany({
|
||||||
"SELECT * FROM game_appeals WHERE created_at < ? ORDER BY created_at DESC LIMIT 25;",
|
orderBy: {
|
||||||
)
|
created_at: "desc",
|
||||||
.bind(before)
|
},
|
||||||
.all();
|
take: 25,
|
||||||
|
where: {
|
||||||
|
created_at: {
|
||||||
|
lt: new Date(before),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "inactivity":
|
case "inactivity":
|
||||||
rows = await context.env.D1.prepare(
|
rows = await prisma.$queryRaw<
|
||||||
`SELECT *,
|
InactivityNotice[] & { decision_count: number }[]
|
||||||
(SELECT COUNT(*) FROM json_each(decisions)) as decision_count
|
>`
|
||||||
FROM inactivity_notices
|
SELECT *, (SELECT COUNT(*) FROM json_each(decisions)) AS decision_count FROM inactivity_notices WHERE created_at < datetime(${before} / 1000, 'unixepoch') AND decision_count ${showClosed ? raw("=") : raw("!=")} json_array_length(departments);`;
|
||||||
WHERE created_at < ?
|
|
||||||
AND decision_count ${showClosed ? "=" : "!="} json_array_length(departments)`,
|
|
||||||
)
|
|
||||||
.bind(before)
|
|
||||||
.all();
|
|
||||||
|
|
||||||
rows.results.map((r) => {
|
rows.map((r) => {
|
||||||
r.decisions = JSON.parse(r.decisions);
|
// These come back as strings when using $queryRaw
|
||||||
r.departments = JSON.parse(r.departments);
|
r.decisions = JSON.parse(r.decisions as string);
|
||||||
r.user = JSON.parse(r.user);
|
r.departments = JSON.parse(r.departments as string);
|
||||||
|
r.user = JSON.parse(r.user as string);
|
||||||
|
|
||||||
delete r.user.email;
|
delete (r.user as JsonObject).email;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "report":
|
case "report":
|
||||||
rows = await context.env.D1.prepare(
|
rows = await prisma.report.findMany({
|
||||||
"SELECT * FROM reports WHERE created_at < ? AND open = ? ORDER BY created_at DESC LIMIT 25;",
|
orderBy: {
|
||||||
)
|
created_at: "desc",
|
||||||
.bind(before, !Number(showClosed))
|
},
|
||||||
.all();
|
take: 25,
|
||||||
|
where: {
|
||||||
|
created_at: {
|
||||||
|
lt: new Date(before),
|
||||||
|
},
|
||||||
|
open: !showClosed,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
rows.results = rows.results.map((r) => {
|
rows.map((r) => {
|
||||||
r.attachments = JSON.parse(r.attachments);
|
delete (r.user as JsonObject | null)?.email;
|
||||||
r.target_ids = JSON.parse(r.target_ids);
|
|
||||||
r.target_usernames = JSON.parse(r.target_usernames);
|
|
||||||
|
|
||||||
if (r.user) {
|
|
||||||
r.user = JSON.parse(r.user);
|
|
||||||
delete r.user.email;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
});
|
});
|
||||||
@@ -103,5 +113,5 @@ export async function onRequestGet(context: RequestContext): Promise<any> {
|
|||||||
return jsonError("Unknown filter error", 500);
|
return jsonError("Unknown filter error", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonResponse(JSON.stringify(rows.results));
|
return jsonResponse(JSON.stringify(rows));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import sendEmail from "../../../email.js";
|
|||||||
import { sendPushNotification } from "../../../gcloud.js";
|
import { sendPushNotification } from "../../../gcloud.js";
|
||||||
|
|
||||||
export async function onRequestPost(context: RequestContext) {
|
export async function onRequestPost(context: RequestContext) {
|
||||||
|
const { prisma } = context.data;
|
||||||
const reportId = context.params.id as string;
|
const reportId = context.params.id as string;
|
||||||
const report: {
|
const report: {
|
||||||
[k: string]: any;
|
[k: string]: any;
|
||||||
@@ -83,12 +84,15 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
await setBanList(context, Object.assign(banList, newActions), etag);
|
await setBanList(context, Object.assign(banList, newActions), etag);
|
||||||
}
|
}
|
||||||
|
|
||||||
const pushNotificationData: Record<string, string> | null =
|
const pushNotificationData = await prisma.pushNotification.findUnique({
|
||||||
await context.env.D1.prepare(
|
select: {
|
||||||
"SELECT token FROM push_notifications WHERE event_id = ? AND event_type = 'report';",
|
token: true,
|
||||||
)
|
},
|
||||||
.bind(reportId)
|
where: {
|
||||||
.first();
|
event_id: reportId,
|
||||||
|
event_type: "report",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (user?.email)
|
if (user?.email)
|
||||||
await sendEmail(
|
await sendEmail(
|
||||||
@@ -100,26 +104,33 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
username: user.username as string,
|
username: user.username as string,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
else if (pushNotificationData)
|
else if (pushNotificationData) {
|
||||||
await sendPushNotification(
|
await sendPushNotification(
|
||||||
context.env,
|
context.env,
|
||||||
"Report Processed",
|
"Report Processed",
|
||||||
`Your report for ${JSON.parse(report.target_usernames).toString()} has been reviewed.`,
|
`Your report for ${JSON.parse(report.target_usernames).toString()} has been reviewed.`,
|
||||||
pushNotificationData.token,
|
pushNotificationData.token,
|
||||||
);
|
);
|
||||||
|
await prisma.pushNotification.delete({
|
||||||
|
where: {
|
||||||
|
event_id: reportId,
|
||||||
|
event_type: "report",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
delete (report.user as { email?: string; id: string; username: string })
|
delete (report.user as { email?: string; id: string; username: string })
|
||||||
?.email;
|
?.email;
|
||||||
|
|
||||||
await context.env.D1.prepare("UPDATE reports SET open = 0 WHERE id = ?;")
|
await prisma.report.update({
|
||||||
.bind(reportId)
|
data: {
|
||||||
.run();
|
open: false,
|
||||||
|
user: report.user,
|
||||||
await context.env.D1.prepare(
|
},
|
||||||
"DELETE FROM push_notifications WHERE event_id = ? AND event_type = 'report';",
|
where: {
|
||||||
)
|
id: reportId,
|
||||||
.bind(reportId)
|
},
|
||||||
.run();
|
});
|
||||||
|
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: 204,
|
status: 204,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
const DATASTORE_URL =
|
const DATASTORE_URL =
|
||||||
"https://apis.roblox.com/cloud/v2/universes/274816972/data-stores/BanData/entries/CloudBanList";
|
"https://apis.roblox.com/cloud/v2/universes/274816972/data-stores/BanData/entries/CloudBanList";
|
||||||
|
|
||||||
|
const MESSAGING_SERVICE_URL =
|
||||||
|
"https://apis.roblox.com/cloud/v2/universes/274816972:publishMessage";
|
||||||
|
|
||||||
const SAVE_DATA_URL =
|
const SAVE_DATA_URL =
|
||||||
"https://apis.roblox.com/cloud/v2/universes/274816972/data-stores/RealData/entries";
|
"https://apis.roblox.com/cloud/v2/universes/274816972/data-stores/RealData/entries";
|
||||||
|
|
||||||
@@ -31,6 +34,28 @@ export async function getBanList(context: RequestContext) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function publishMessage(
|
||||||
|
context: RequestContext,
|
||||||
|
topic: string,
|
||||||
|
message: string,
|
||||||
|
) {
|
||||||
|
const response = await fetch(MESSAGING_SERVICE_URL, {
|
||||||
|
body: JSON.stringify({
|
||||||
|
message,
|
||||||
|
topic,
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"x-api-key": context.env.ROBLOX_OPENCLOUD_KEY,
|
||||||
|
},
|
||||||
|
method: "POST",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to publish message\n" + (await response.text()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function getSaveData(
|
export async function getSaveData(
|
||||||
context: RequestContext,
|
context: RequestContext,
|
||||||
user: number,
|
user: number,
|
||||||
|
|||||||
@@ -70,10 +70,6 @@ button:focus-visible {
|
|||||||
padding: 2em;
|
padding: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
::file-selector-button {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktop-nav {
|
.desktop-nav {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|||||||
186
migrations/0001_initialize.sql
Normal file
186
migrations/0001_initialize.sql
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "appeals" (
|
||||||
|
"approved" BOOLEAN,
|
||||||
|
"ban_reason" TEXT NOT NULL,
|
||||||
|
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"learned" TEXT NOT NULL,
|
||||||
|
"reason_for_unban" TEXT NOT NULL,
|
||||||
|
"user" JSONB NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "appeal_bans" (
|
||||||
|
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"created_by" TEXT NOT NULL,
|
||||||
|
"user" TEXT NOT NULL PRIMARY KEY
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "et_members" (
|
||||||
|
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"created_by" TEXT NOT NULL,
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"is_management" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"name" TEXT NOT NULL,
|
||||||
|
"points" INTEGER NOT NULL DEFAULT 0,
|
||||||
|
"roblox_id" INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "et_strikes" (
|
||||||
|
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"created_by" TEXT NOT NULL,
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"reason" TEXT NOT NULL,
|
||||||
|
"user" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "events" (
|
||||||
|
"answer" TEXT,
|
||||||
|
"answered_at" DATETIME,
|
||||||
|
"approved" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"created_by" TEXT NOT NULL,
|
||||||
|
"day" INTEGER NOT NULL,
|
||||||
|
"details" TEXT NOT NULL,
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"month" INTEGER NOT NULL,
|
||||||
|
"pending" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"performed_at" DATETIME,
|
||||||
|
"reached_minimum_player_count" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"type" TEXT NOT NULL,
|
||||||
|
"year" INTEGER NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "game_appeals" (
|
||||||
|
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"reason_for_unban" TEXT NOT NULL,
|
||||||
|
"roblox_id" INTEGER NOT NULL,
|
||||||
|
"roblox_username" TEXT NOT NULL,
|
||||||
|
"type" TEXT NOT NULL,
|
||||||
|
"what_happened" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "game_mod_logs" (
|
||||||
|
"action" TEXT NOT NULL,
|
||||||
|
"evidence" TEXT NOT NULL,
|
||||||
|
"executed_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"executor" TEXT NOT NULL,
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"target" INTEGER NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "game_mod_notes" (
|
||||||
|
"content" TEXT NOT NULL,
|
||||||
|
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"created_by" TEXT NOT NULL,
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"target" INTEGER NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "inactivity_notices" (
|
||||||
|
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"decisions" JSONB NOT NULL,
|
||||||
|
"departments" JSONB NOT NULL DEFAULT [],
|
||||||
|
"end" TEXT NOT NULL,
|
||||||
|
"hiatus" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"reason" TEXT NOT NULL,
|
||||||
|
"start" TEXT NOT NULL,
|
||||||
|
"user" JSONB NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "push_notifications" (
|
||||||
|
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"event_id" TEXT NOT NULL,
|
||||||
|
"event_type" TEXT NOT NULL,
|
||||||
|
"token" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "reports" (
|
||||||
|
"attachments" JSONB NOT NULL DEFAULT [],
|
||||||
|
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"open" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"target_ids" JSONB NOT NULL DEFAULT [],
|
||||||
|
"target_usernames" JSONB NOT NULL DEFAULT [],
|
||||||
|
"type" TEXT NOT NULL DEFAULT 'exploit',
|
||||||
|
"user" JSONB
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "short_links" (
|
||||||
|
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"destination" TEXT NOT NULL,
|
||||||
|
"path" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"user" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "appeals_id_key" ON "appeals"("id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "idx_appeals_approved_created_at" ON "appeals"("approved", "created_at");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "appeal_bans_user_key" ON "appeal_bans"("user");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "et_members_id_key" ON "et_members"("id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "idx_et_members_id_name" ON "et_members"("id", "name");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "et_strikes_id_key" ON "et_strikes"("id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "events_id_key" ON "events"("id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "idx_events_month_year" ON "events"("month", "year");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "game_appeals_id_key" ON "game_appeals"("id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "idx_game_appeals_created_at" ON "game_appeals"("created_at");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "game_mod_logs_id_key" ON "game_mod_logs"("id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "idx_game_mod_logs_target" ON "game_mod_logs"("target");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "game_mod_notes_id_key" ON "game_mod_notes"("id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "idx_game_mod_notes_target" ON "game_mod_notes"("target");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "inactivity_notices_id_key" ON "inactivity_notices"("id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "idx_inactivity_notices_end_start" ON "inactivity_notices"("end", "start");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "push_notifications_event_id_key" ON "push_notifications"("event_id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "reports_id_key" ON "reports"("id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "idx_reports_created_at_open" ON "reports"("created_at", "open");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "short_links_path_key" ON "short_links"("path");
|
||||||
15
migrations/0002_create_data_request_table.sql
Normal file
15
migrations/0002_create_data_request_table.sql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "data_requests" (
|
||||||
|
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"originating_user" INTEGER,
|
||||||
|
"status" TEXT NOT NULL,
|
||||||
|
"target_user" INTEGER NOT NULL,
|
||||||
|
"type" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "data_requests_id_key" ON "data_requests"("id");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "idx_data_requests_created_at" ON "data_requests"("created_at");
|
||||||
538
package-lock.json
generated
538
package-lock.json
generated
@@ -12,13 +12,13 @@
|
|||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.1",
|
"@emotion/styled": "^11.14.1",
|
||||||
"@fontsource-variable/plus-jakarta-sans": "^5.2.8",
|
"@fontsource-variable/plus-jakarta-sans": "^5.2.8",
|
||||||
"@prisma/adapter-d1": "^7.7.0",
|
"@prisma/adapter-d1": "^7.8.0",
|
||||||
"@prisma/client": "^7.7.0",
|
"@prisma/client": "^7.8.0",
|
||||||
"@remix-run/cloudflare": "^2.17.4",
|
"@remix-run/cloudflare": "^2.17.4",
|
||||||
"@remix-run/cloudflare-pages": "^2.17.4",
|
"@remix-run/cloudflare-pages": "^2.17.4",
|
||||||
"@remix-run/react": "^2.17.4",
|
"@remix-run/react": "^2.17.4",
|
||||||
"@sentry/cloudflare": "^10.48.0",
|
"@sentry/cloudflare": "^10.52.0",
|
||||||
"@sentry/remix": "^10.48.0",
|
"@sentry/remix": "^10.52.0",
|
||||||
"aws4fetch": "^1.0.20",
|
"aws4fetch": "^1.0.20",
|
||||||
"dayjs": "^1.11.20",
|
"dayjs": "^1.11.20",
|
||||||
"framer-motion": "^12.38.0",
|
"framer-motion": "^12.38.0",
|
||||||
@@ -28,13 +28,13 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@remix-run/dev": "^2.17.4",
|
"@remix-run/dev": "^2.17.4",
|
||||||
"@types/node": "^24.12.2",
|
"@types/node": "^24.12.3",
|
||||||
"@types/react": "^18.3.28",
|
"@types/react": "^18.3.28",
|
||||||
"@types/react-big-calendar": "^1.16.3",
|
"@types/react-big-calendar": "^1.16.3",
|
||||||
"@types/react-dom": "^18.3.7",
|
"@types/react-dom": "^18.3.7",
|
||||||
"dotenv": "^17.4.1",
|
"dotenv": "^17.4.1",
|
||||||
"prettier": "^3.8.2",
|
"prettier": "^3.8.3",
|
||||||
"prisma": "^7.7.0",
|
"prisma": "^7.8.0",
|
||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -569,9 +569,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cloudflare/workers-types": {
|
"node_modules/@cloudflare/workers-types": {
|
||||||
"version": "4.20260329.1",
|
"version": "4.20260511.1",
|
||||||
"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260329.1.tgz",
|
"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260511.1.tgz",
|
||||||
"integrity": "sha512-LxBHrYYI/AZ6OCbUzRqRgg6Rt1qev2KxN2NNd3saye41AO2g52cYvHV+ohts5oPnrIUD7YRjbgN/J3NU7e7m5A==",
|
"integrity": "sha512-FA+si7cOq9i/gtCHhIc0XJL0l1F/ApF+m00752Aj7WZFJrj3ZulT2T8/+rT3BabMT0QEnqFEGIqCgrmqhgEfMg==",
|
||||||
"license": "MIT OR Apache-2.0"
|
"license": "MIT OR Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/@electric-sql/pglite": {
|
"node_modules/@electric-sql/pglite": {
|
||||||
@@ -1177,9 +1177,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@fastify/otel/node_modules/brace-expansion": {
|
"node_modules/@fastify/otel/node_modules/brace-expansion": {
|
||||||
"version": "5.0.5",
|
"version": "5.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
|
||||||
"integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
|
"integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^4.0.2"
|
"balanced-match": "^4.0.2"
|
||||||
@@ -1413,22 +1413,10 @@
|
|||||||
"node": ">=8.0.0"
|
"node": ">=8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@opentelemetry/context-async-hooks": {
|
|
||||||
"version": "2.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.6.1.tgz",
|
|
||||||
"integrity": "sha512-XHzhwRNkBpeP8Fs/qjGrAf9r9PRv67wkJQ/7ZPaBQQ68DYlTBBx5MF9LvPx7mhuXcDessKK2b+DcxqwpgkcivQ==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.19.0 || >=20.6.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@opentelemetry/api": ">=1.0.0 <1.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@opentelemetry/core": {
|
"node_modules/@opentelemetry/core": {
|
||||||
"version": "2.6.1",
|
"version": "2.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.7.1.tgz",
|
||||||
"integrity": "sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g==",
|
"integrity": "sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opentelemetry/semantic-conventions": "^1.29.0"
|
"@opentelemetry/semantic-conventions": "^1.29.0"
|
||||||
@@ -1588,21 +1576,19 @@
|
|||||||
"@opentelemetry/api": "^1.3.0"
|
"@opentelemetry/api": "^1.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@opentelemetry/instrumentation-ioredis": {
|
"node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/core": {
|
||||||
"version": "0.62.0",
|
"version": "2.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.62.0.tgz",
|
"resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.6.1.tgz",
|
||||||
"integrity": "sha512-ZYt//zcPve8qklaZX+5Z4MkU7UpEkFRrxsf2cnaKYBitqDnsCN69CPAuuMOX6NYdW2rG9sFy7V/QWtBlP5XiNQ==",
|
"integrity": "sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opentelemetry/instrumentation": "^0.214.0",
|
"@opentelemetry/semantic-conventions": "^1.29.0"
|
||||||
"@opentelemetry/redis-common": "^0.38.2",
|
|
||||||
"@opentelemetry/semantic-conventions": "^1.33.0"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.19.0 || >=20.6.0"
|
"node": "^18.19.0 || >=20.6.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@opentelemetry/api": "^1.3.0"
|
"@opentelemetry/api": ">=1.0.0 <1.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@opentelemetry/instrumentation-kafkajs": {
|
"node_modules/@opentelemetry/instrumentation-kafkajs": {
|
||||||
@@ -1756,23 +1742,6 @@
|
|||||||
"@opentelemetry/api": "^1.3.0"
|
"@opentelemetry/api": "^1.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@opentelemetry/instrumentation-redis": {
|
|
||||||
"version": "0.62.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.62.0.tgz",
|
|
||||||
"integrity": "sha512-y3pPpot7WzR/8JtHcYlTYsyY8g+pbFhAqbwAuG5bLPnR6v6pt1rQc0DpH0OlGP/9CZbWBP+Zhwp9yFoygf/ZXQ==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@opentelemetry/instrumentation": "^0.214.0",
|
|
||||||
"@opentelemetry/redis-common": "^0.38.2",
|
|
||||||
"@opentelemetry/semantic-conventions": "^1.27.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.19.0 || >=20.6.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@opentelemetry/api": "^1.3.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@opentelemetry/instrumentation-tedious": {
|
"node_modules/@opentelemetry/instrumentation-tedious": {
|
||||||
"version": "0.33.0",
|
"version": "0.33.0",
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.33.0.tgz",
|
||||||
@@ -1790,39 +1759,13 @@
|
|||||||
"@opentelemetry/api": "^1.3.0"
|
"@opentelemetry/api": "^1.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@opentelemetry/instrumentation-undici": {
|
|
||||||
"version": "0.24.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.24.0.tgz",
|
|
||||||
"integrity": "sha512-oKzZ3uvqP17sV0EsoQcJgjEfIp0kiZRbYu/eD8p13Cbahumf8lb/xpYeNr/hfAJ4owzEtIDcGIjprfLcYbIKBQ==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@opentelemetry/core": "^2.0.0",
|
|
||||||
"@opentelemetry/instrumentation": "^0.214.0",
|
|
||||||
"@opentelemetry/semantic-conventions": "^1.24.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.19.0 || >=20.6.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@opentelemetry/api": "^1.7.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@opentelemetry/redis-common": {
|
|
||||||
"version": "0.38.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz",
|
|
||||||
"integrity": "sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.19.0 || >=20.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@opentelemetry/resources": {
|
"node_modules/@opentelemetry/resources": {
|
||||||
"version": "2.6.1",
|
"version": "2.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.1.tgz",
|
||||||
"integrity": "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA==",
|
"integrity": "sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opentelemetry/core": "2.6.1",
|
"@opentelemetry/core": "2.7.1",
|
||||||
"@opentelemetry/semantic-conventions": "^1.29.0"
|
"@opentelemetry/semantic-conventions": "^1.29.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1833,13 +1776,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@opentelemetry/sdk-trace-base": {
|
"node_modules/@opentelemetry/sdk-trace-base": {
|
||||||
"version": "2.6.1",
|
"version": "2.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz",
|
||||||
"integrity": "sha512-r86ut4T1e8vNwB35CqCcKd45yzqH6/6Wzvpk2/cZB8PsPLlZFTvrh8yfOS3CYZYcUmAx4hHTZJ8AO8Dj8nrdhw==",
|
"integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opentelemetry/core": "2.6.1",
|
"@opentelemetry/core": "2.7.1",
|
||||||
"@opentelemetry/resources": "2.6.1",
|
"@opentelemetry/resources": "2.7.1",
|
||||||
"@opentelemetry/semantic-conventions": "^1.29.0"
|
"@opentelemetry/semantic-conventions": "^1.29.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1891,23 +1834,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/adapter-d1": {
|
"node_modules/@prisma/adapter-d1": {
|
||||||
"version": "7.7.0",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/adapter-d1/-/adapter-d1-7.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/adapter-d1/-/adapter-d1-7.8.0.tgz",
|
||||||
"integrity": "sha512-0+lJsHqm+TXxXdGCCMFouNcJMVE029g6td/vRM7EhWoJYtvakwCzdzJqCQEaGPjCAPi6lzar4DAtEi7z04qjIA==",
|
"integrity": "sha512-JLmmuDKnPltHicr8+W0xOt4ozbTlAiaPEDe8YGAJIEgHmflOF7sr4Dsd8d+saRBKOARnODz/yxx+y+QMRm/e/g==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cloudflare/workers-types": "^4.20251014.0",
|
"@cloudflare/workers-types": "^4.20251014.0",
|
||||||
"@prisma/driver-adapter-utils": "7.7.0",
|
"@prisma/driver-adapter-utils": "7.8.0",
|
||||||
"ky": "1.7.5"
|
"ky": "1.7.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/client": {
|
"node_modules/@prisma/client": {
|
||||||
"version": "7.7.0",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-7.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-7.8.0.tgz",
|
||||||
"integrity": "sha512-5Ar4OsZpJ54s21sy5oDNNW9gQtd4NuxCaiM7+JDTOU07D6VvlpLjYzAVCMB1+JzokN+08dAVomlx+b7bhJd3ww==",
|
"integrity": "sha512-HFp3Dawv/3sU3JtlPha90IB+48lS7zHiH4LKZPjmcE8YH5P9DOXGPvo8dqOtO7MqLDd1p2hOWMcFlRT1DMblHw==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client-runtime-utils": "7.7.0"
|
"@prisma/client-runtime-utils": "7.8.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^20.19 || ^22.12 || >=24.0"
|
"node": "^20.19 || ^22.12 || >=24.0"
|
||||||
@@ -1926,28 +1869,28 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/client-runtime-utils": {
|
"node_modules/@prisma/client-runtime-utils": {
|
||||||
"version": "7.7.0",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/client-runtime-utils/-/client-runtime-utils-7.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/client-runtime-utils/-/client-runtime-utils-7.8.0.tgz",
|
||||||
"integrity": "sha512-BLyd0UpFYOtyJFTHm7jS9vesHW7P83abibodQMiIofqjBKzDHQ1VAsQkdfvXyYDkPlONPfOTz7/rv3x/+CQqvQ==",
|
"integrity": "sha512-5NQZztQ0oY/ADFkmd9gPuweH5A1/CCY8YQPorLLO0Mu6a87mY5gsnDkzmFmIHs9NFaLnZojzgddFVN4RpKYrdw==",
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/config": {
|
"node_modules/@prisma/config": {
|
||||||
"version": "7.7.0",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.8.0.tgz",
|
||||||
"integrity": "sha512-hmPI3tKLO2aP0Y5vugbjcnA9qqlfJndiT6ds4tw28U5hNHLWg+mHJEWAhjsSPgxjtmxhJ/EDIeIlyh+3Us0OPg==",
|
"integrity": "sha512-HFESzd9rx2ZQxlK+TL7tu1HPvCqrHiL6LCxYykI2c34mvaUuIVVl3lYuicJD/MNnzgPnyeBEMlK4WTomJCV5jw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"c12": "3.1.0",
|
"c12": "3.3.4",
|
||||||
"deepmerge-ts": "7.1.5",
|
"deepmerge-ts": "7.1.5",
|
||||||
"effect": "3.20.0",
|
"effect": "3.20.0",
|
||||||
"empathic": "2.0.0"
|
"empathic": "2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/debug": {
|
"node_modules/@prisma/debug": {
|
||||||
"version": "7.7.0",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.8.0.tgz",
|
||||||
"integrity": "sha512-12J62XdqCmpiwJHhHdQxZeY3ckVCWIFmcJP8hg5dPTceeiQ0wiojXGFYTluKqFQfu46fRLgb/rLALZMAx3+dTA==",
|
"integrity": "sha512-p+QZReysDUqXC+mk17q9a+Y/qzh4c2KYliDK30buYUyfrGeTGSyfmc0AIrJRhZJrLHhRiJa9Au/J72h3C+szvA==",
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/dev": {
|
"node_modules/@prisma/dev": {
|
||||||
@@ -1984,65 +1927,65 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/driver-adapter-utils": {
|
"node_modules/@prisma/driver-adapter-utils": {
|
||||||
"version": "7.7.0",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/driver-adapter-utils/-/driver-adapter-utils-7.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/driver-adapter-utils/-/driver-adapter-utils-7.8.0.tgz",
|
||||||
"integrity": "sha512-gZXREeu6mOk7zXfGFJgh86p7Vhj0sXNKp+4Cg1tWYo7V2dfncP2qxS2BiTmbIIha8xPqItkl0WSw38RuSq1HoQ==",
|
"integrity": "sha512-/Q13o0ZT0rjc1Xk0Q9KhZYwuq2EW/vSbWUBKfgEKkaCuB/Sg6bqnjmTZqC5cD4d6y1vfFAEwBRzfzoSMIVJ55A==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/debug": "7.7.0"
|
"@prisma/debug": "7.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/engines": {
|
"node_modules/@prisma/engines": {
|
||||||
"version": "7.7.0",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.8.0.tgz",
|
||||||
"integrity": "sha512-7fmcbT7HHXBq/b+3h/dO1JI3fd8l8q7erf7xP7pRprh58hmSSnG8mg9K3yjW3h9WaHWUwngVFpSxxxivaitQ2w==",
|
"integrity": "sha512-jx3rCnNNrt5uzbkKlegtQ2GZHxSlihMCzutgT/BP6UIDF1r9tDI39hV/0T/cHZgzJ3ELbuQPXlVZy+Y1n0pcgw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/debug": "7.7.0",
|
"@prisma/debug": "7.8.0",
|
||||||
"@prisma/engines-version": "7.6.0-1.75cbdc1eb7150937890ad5465d861175c6624711",
|
"@prisma/engines-version": "7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a",
|
||||||
"@prisma/fetch-engine": "7.7.0",
|
"@prisma/fetch-engine": "7.8.0",
|
||||||
"@prisma/get-platform": "7.7.0"
|
"@prisma/get-platform": "7.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/engines-version": {
|
"node_modules/@prisma/engines-version": {
|
||||||
"version": "7.6.0-1.75cbdc1eb7150937890ad5465d861175c6624711",
|
"version": "7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.6.0-1.75cbdc1eb7150937890ad5465d861175c6624711.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a.tgz",
|
||||||
"integrity": "sha512-r51DLcJ8bDRSrBEJF3J4cinoWyGA7rfP2mG6lD90VqIbGNOkbfcLcXalSVjq5Y6brQS3vcjrq4GbyUb1Cb7vkw==",
|
"integrity": "sha512-fJPQxCkLgA5EayWaW8eArgCvjJ+N+Kz3VyeNKMEeYiQC4alNkxRKFVAGxv/ZUzuJISKqdw+zGeDbS6mn6RCPOA==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/engines/node_modules/@prisma/get-platform": {
|
"node_modules/@prisma/engines/node_modules/@prisma/get-platform": {
|
||||||
"version": "7.7.0",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.8.0.tgz",
|
||||||
"integrity": "sha512-MEUNzvKxvYnJ7kgvd6oNRnMmmiGNS9TYLB2weMeIXplnHdL/UWEGnvavYGnN7KLJ2n0iI4dDAyzSkHI3c7AscQ==",
|
"integrity": "sha512-WlxgRGnolL8VH2EmkH1R/DkKNr/mVdS3G2h42IZFFZ3eUrH9OT6t73kIOSlkkrv50wG123Iq8d96ufv5LlZktw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/debug": "7.7.0"
|
"@prisma/debug": "7.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/fetch-engine": {
|
"node_modules/@prisma/fetch-engine": {
|
||||||
"version": "7.7.0",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.8.0.tgz",
|
||||||
"integrity": "sha512-TfyzveBQoK4xALzsTpVhB/0KG1N8zOK0ap+RnBMkzGUu3f98fnQ4QtXa2wlKPhsO2X8a3N5ugFQgcKNoHGmDfw==",
|
"integrity": "sha512-gwB0Euiz/DDRyxFRpLXYlK3RfaZUj1c5dAYMuhZYfApg7arknJlcb9bIsOHDppJmbqYaVA+yBIiFMDBfprsNPQ==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/debug": "7.7.0",
|
"@prisma/debug": "7.8.0",
|
||||||
"@prisma/engines-version": "7.6.0-1.75cbdc1eb7150937890ad5465d861175c6624711",
|
"@prisma/engines-version": "7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a",
|
||||||
"@prisma/get-platform": "7.7.0"
|
"@prisma/get-platform": "7.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/fetch-engine/node_modules/@prisma/get-platform": {
|
"node_modules/@prisma/fetch-engine/node_modules/@prisma/get-platform": {
|
||||||
"version": "7.7.0",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.8.0.tgz",
|
||||||
"integrity": "sha512-MEUNzvKxvYnJ7kgvd6oNRnMmmiGNS9TYLB2weMeIXplnHdL/UWEGnvavYGnN7KLJ2n0iI4dDAyzSkHI3c7AscQ==",
|
"integrity": "sha512-WlxgRGnolL8VH2EmkH1R/DkKNr/mVdS3G2h42IZFFZ3eUrH9OT6t73kIOSlkkrv50wG123Iq8d96ufv5LlZktw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/debug": "7.7.0"
|
"@prisma/debug": "7.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/get-platform": {
|
"node_modules/@prisma/get-platform": {
|
||||||
@@ -2960,66 +2903,66 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@sentry-internal/browser-utils": {
|
"node_modules/@sentry-internal/browser-utils": {
|
||||||
"version": "10.48.0",
|
"version": "10.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.48.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.52.0.tgz",
|
||||||
"integrity": "sha512-SCiTLBXzugFKxev6NoKYBIhQoDk0gUh0AVVVepCBqfCJiWBG01Zvv0R5tCVohr4cWRllkQ8mlBdNQd/I7s9tdA==",
|
"integrity": "sha512-x/yEPZdpH6NGQeoeQnV9tj8reAH8twNttiltGZl2o8Rk7sQeUfe7E8yuYP2XbJ2RqyZK5qRS3COrNyMPzf6KFA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/core": "10.48.0"
|
"@sentry/core": "10.52.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry-internal/feedback": {
|
"node_modules/@sentry-internal/feedback": {
|
||||||
"version": "10.48.0",
|
"version": "10.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.48.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.52.0.tgz",
|
||||||
"integrity": "sha512-tGkEyOM1HDS9qebDphUMEnyk3qq/50AnuTBiFmMJyjNzowylVGmRRk0sr3xkmbVHCDXQCiYnDmSVlJ2x4SDMrQ==",
|
"integrity": "sha512-5kAn1W8ZvCuHtEHXpq6iRkUMdNCilwww+YxaN2yofVrCivAbB3Ha5JJUMqmWOPW0pC27zGYmoJMIDvG+PczUxA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/core": "10.48.0"
|
"@sentry/core": "10.52.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry-internal/replay": {
|
"node_modules/@sentry-internal/replay": {
|
||||||
"version": "10.48.0",
|
"version": "10.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.48.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.52.0.tgz",
|
||||||
"integrity": "sha512-sevRTePfuk4PNuz9KAKpmTZEomAU0aLXyIhOwA0OnUDdxPhkY8kq5lwDbuxTHv6DQUjUX3YgFbY45VH1JEqHKA==",
|
"integrity": "sha512-diywyuc/H7VTUR+W5ryVmLF+0X4UP1OskMqb6V8RSAvJHcj2JmIm7uP+Fc6ACTno+b6AUShwT/L4xVXzO6X9Cw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry-internal/browser-utils": "10.48.0",
|
"@sentry-internal/browser-utils": "10.52.0",
|
||||||
"@sentry/core": "10.48.0"
|
"@sentry/core": "10.52.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry-internal/replay-canvas": {
|
"node_modules/@sentry-internal/replay-canvas": {
|
||||||
"version": "10.48.0",
|
"version": "10.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.48.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.52.0.tgz",
|
||||||
"integrity": "sha512-9nWuN2z4O+iwbTfuYV5ZmngBgJU/ZxfOo47A5RJP3Nu/kl59aJ1lUhILYOKyeNOIC/JyeERmpIcTxnlPXQzZ3Q==",
|
"integrity": "sha512-BI5ie4dxPuUJ344CXVSnAxY1xZCbghglPSCIlTOYODpR9so9yo5IZh+Mwspt0oWsUMaxWJiQSNYlbPWi7WDavg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry-internal/replay": "10.48.0",
|
"@sentry-internal/replay": "10.52.0",
|
||||||
"@sentry/core": "10.48.0"
|
"@sentry/core": "10.52.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/browser": {
|
"node_modules/@sentry/browser": {
|
||||||
"version": "10.48.0",
|
"version": "10.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.48.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.52.0.tgz",
|
||||||
"integrity": "sha512-4jt2zX2ExgFcNe2x+W+/k81fmDUsOrquGtt028CiGuDuma6kEsWBI4JbooT1jhj2T+eeUxe3YGbM23Zhh7Ghhw==",
|
"integrity": "sha512-ijL9jN86oXwXQWbwhPlEb70ODJSEmjxQEQdnZkC4gDWbjswcwvRsVJPYk+1xl2ir2iZixRIHipVxDcLwian35g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry-internal/browser-utils": "10.48.0",
|
"@sentry-internal/browser-utils": "10.52.0",
|
||||||
"@sentry-internal/feedback": "10.48.0",
|
"@sentry-internal/feedback": "10.52.0",
|
||||||
"@sentry-internal/replay": "10.48.0",
|
"@sentry-internal/replay": "10.52.0",
|
||||||
"@sentry-internal/replay-canvas": "10.48.0",
|
"@sentry-internal/replay-canvas": "10.52.0",
|
||||||
"@sentry/core": "10.48.0"
|
"@sentry/core": "10.52.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
@@ -3206,13 +3149,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/cloudflare": {
|
"node_modules/@sentry/cloudflare": {
|
||||||
"version": "10.48.0",
|
"version": "10.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/cloudflare/-/cloudflare-10.48.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/cloudflare/-/cloudflare-10.52.0.tgz",
|
||||||
"integrity": "sha512-i02Ps4/cJjFpbcHLMhNEFXTeVqLB9XpB3+/OFQ9aMFV3yDcxlvHwe0oo7WZf41iroArvpysotLG8Y8NBOU9omA==",
|
"integrity": "sha512-NhFpR0OKd7gZDuJWJd8C0jC6WhA+R+m1OGp0ul2ItwIASTzGMw6gGLo0XuQjC6GfuodNAGbCF1bQN3Zi3nV1Lg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opentelemetry/api": "^1.9.1",
|
"@opentelemetry/api": "^1.9.1",
|
||||||
"@sentry/core": "10.48.0"
|
"@sentry/core": "10.52.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
@@ -3227,23 +3170,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/core": {
|
"node_modules/@sentry/core": {
|
||||||
"version": "10.48.0",
|
"version": "10.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.48.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.52.0.tgz",
|
||||||
"integrity": "sha512-h8F+fXVwYC9ro5ZaO8V+v3vqc0awlXHGblEAuVxSGgh4IV/oFX+QVzXeDTTrFOFS6v/Vn5vAyu240eJrJAS6/g==",
|
"integrity": "sha512-VA/kAqLhkMnRWY2RXdBLyTemR9D4m7MVRy/gyapoq9yvllVPx9WXbvKgnMP2LQp7mFgT/oLFvw58aQKaYTGn3A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/node": {
|
"node_modules/@sentry/node": {
|
||||||
"version": "10.48.0",
|
"version": "10.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.48.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.52.0.tgz",
|
||||||
"integrity": "sha512-MzyLJyYmr0Qg60K6NJ2EdwJUX1OuAYXs9tyYxnqVO3nJ8MyYwIcuN4FCYEnXkG6Jiy/4q7OuZgXWnfdQJVcaqw==",
|
"integrity": "sha512-9+p3KJUk3rHO1HOEZuSknP2RgKCJZONDm4HWgkVDtVBtocb66KLtVlMjc59d2/bWP7tM3wc877tpG30quFfU9g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/otel": "0.18.0",
|
"@fastify/otel": "0.18.0",
|
||||||
"@opentelemetry/api": "^1.9.1",
|
"@opentelemetry/api": "^1.9.1",
|
||||||
"@opentelemetry/context-async-hooks": "^2.6.1",
|
|
||||||
"@opentelemetry/core": "^2.6.1",
|
"@opentelemetry/core": "^2.6.1",
|
||||||
"@opentelemetry/instrumentation": "^0.214.0",
|
"@opentelemetry/instrumentation": "^0.214.0",
|
||||||
"@opentelemetry/instrumentation-amqplib": "0.61.0",
|
"@opentelemetry/instrumentation-amqplib": "0.61.0",
|
||||||
@@ -3254,7 +3196,6 @@
|
|||||||
"@opentelemetry/instrumentation-graphql": "0.62.0",
|
"@opentelemetry/instrumentation-graphql": "0.62.0",
|
||||||
"@opentelemetry/instrumentation-hapi": "0.60.0",
|
"@opentelemetry/instrumentation-hapi": "0.60.0",
|
||||||
"@opentelemetry/instrumentation-http": "0.214.0",
|
"@opentelemetry/instrumentation-http": "0.214.0",
|
||||||
"@opentelemetry/instrumentation-ioredis": "0.62.0",
|
|
||||||
"@opentelemetry/instrumentation-kafkajs": "0.23.0",
|
"@opentelemetry/instrumentation-kafkajs": "0.23.0",
|
||||||
"@opentelemetry/instrumentation-knex": "0.58.0",
|
"@opentelemetry/instrumentation-knex": "0.58.0",
|
||||||
"@opentelemetry/instrumentation-koa": "0.62.0",
|
"@opentelemetry/instrumentation-koa": "0.62.0",
|
||||||
@@ -3264,16 +3205,13 @@
|
|||||||
"@opentelemetry/instrumentation-mysql": "0.60.0",
|
"@opentelemetry/instrumentation-mysql": "0.60.0",
|
||||||
"@opentelemetry/instrumentation-mysql2": "0.60.0",
|
"@opentelemetry/instrumentation-mysql2": "0.60.0",
|
||||||
"@opentelemetry/instrumentation-pg": "0.66.0",
|
"@opentelemetry/instrumentation-pg": "0.66.0",
|
||||||
"@opentelemetry/instrumentation-redis": "0.62.0",
|
|
||||||
"@opentelemetry/instrumentation-tedious": "0.33.0",
|
"@opentelemetry/instrumentation-tedious": "0.33.0",
|
||||||
"@opentelemetry/instrumentation-undici": "0.24.0",
|
|
||||||
"@opentelemetry/resources": "^2.6.1",
|
|
||||||
"@opentelemetry/sdk-trace-base": "^2.6.1",
|
"@opentelemetry/sdk-trace-base": "^2.6.1",
|
||||||
"@opentelemetry/semantic-conventions": "^1.40.0",
|
"@opentelemetry/semantic-conventions": "^1.40.0",
|
||||||
"@prisma/instrumentation": "7.6.0",
|
"@prisma/instrumentation": "7.6.0",
|
||||||
"@sentry/core": "10.48.0",
|
"@sentry/core": "10.52.0",
|
||||||
"@sentry/node-core": "10.48.0",
|
"@sentry/node-core": "10.52.0",
|
||||||
"@sentry/opentelemetry": "10.48.0",
|
"@sentry/opentelemetry": "10.52.0",
|
||||||
"import-in-the-middle": "^3.0.0"
|
"import-in-the-middle": "^3.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -3281,13 +3219,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/node-core": {
|
"node_modules/@sentry/node-core": {
|
||||||
"version": "10.48.0",
|
"version": "10.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.48.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.52.0.tgz",
|
||||||
"integrity": "sha512-D1TnPhN6vhrRqJ+bN+rdXDM+INibI6lNBm0eGx45zz7DBx9ouq2e9gm/DPx+y/hAkYYq0qTd6x84cGxtVZbKLw==",
|
"integrity": "sha512-IG7MBtLRPQ2LuU+kbD14AFZroZgAeUmJQTP1FI/F8n56O31+p+9R703LuBTpvZr6sm+eRYDMWcGYYkfLHRVjwg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/core": "10.48.0",
|
"@sentry/core": "10.52.0",
|
||||||
"@sentry/opentelemetry": "10.48.0",
|
"@sentry/opentelemetry": "10.52.0",
|
||||||
"import-in-the-middle": "^3.0.0"
|
"import-in-the-middle": "^3.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -3295,11 +3233,9 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@opentelemetry/api": "^1.9.0",
|
"@opentelemetry/api": "^1.9.0",
|
||||||
"@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0",
|
|
||||||
"@opentelemetry/core": "^1.30.1 || ^2.1.0",
|
"@opentelemetry/core": "^1.30.1 || ^2.1.0",
|
||||||
"@opentelemetry/exporter-trace-otlp-http": ">=0.57.0 <1",
|
"@opentelemetry/exporter-trace-otlp-http": ">=0.57.0 <1",
|
||||||
"@opentelemetry/instrumentation": ">=0.57.1 <1",
|
"@opentelemetry/instrumentation": ">=0.57.1 <1",
|
||||||
"@opentelemetry/resources": "^1.30.1 || ^2.1.0",
|
|
||||||
"@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0",
|
"@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0",
|
||||||
"@opentelemetry/semantic-conventions": "^1.39.0"
|
"@opentelemetry/semantic-conventions": "^1.39.0"
|
||||||
},
|
},
|
||||||
@@ -3307,9 +3243,6 @@
|
|||||||
"@opentelemetry/api": {
|
"@opentelemetry/api": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@opentelemetry/context-async-hooks": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@opentelemetry/core": {
|
"@opentelemetry/core": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
@@ -3319,9 +3252,6 @@
|
|||||||
"@opentelemetry/instrumentation": {
|
"@opentelemetry/instrumentation": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@opentelemetry/resources": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@opentelemetry/sdk-trace-base": {
|
"@opentelemetry/sdk-trace-base": {
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
@@ -3331,32 +3261,31 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/opentelemetry": {
|
"node_modules/@sentry/opentelemetry": {
|
||||||
"version": "10.48.0",
|
"version": "10.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.48.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.52.0.tgz",
|
||||||
"integrity": "sha512-Tn6Y0PZjRJ7OW8loK1ntK7wnJnIINnCfSpnwuqow0FMblaDmu5jDVOYq0U1SJBoBcMD5j9aSqrwyj6zqKwjc0A==",
|
"integrity": "sha512-Sc7StsvC0bwhMcgDfTRWUIexO5cNzzKUurvUwtpgQUnxO7AzexU3lkY3yHYDsCbWYAEQMXAgQYQtbcqoh+Ie7g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/core": "10.48.0"
|
"@sentry/core": "10.52.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@opentelemetry/api": "^1.9.0",
|
"@opentelemetry/api": "^1.9.0",
|
||||||
"@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0",
|
|
||||||
"@opentelemetry/core": "^1.30.1 || ^2.1.0",
|
"@opentelemetry/core": "^1.30.1 || ^2.1.0",
|
||||||
"@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0",
|
"@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0",
|
||||||
"@opentelemetry/semantic-conventions": "^1.39.0"
|
"@opentelemetry/semantic-conventions": "^1.39.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/react": {
|
"node_modules/@sentry/react": {
|
||||||
"version": "10.48.0",
|
"version": "10.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.48.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.52.0.tgz",
|
||||||
"integrity": "sha512-uc93vKjmu6gNns+JAX4qquuxWpAMit0uGPA1TYlMjct9NG1uX3TkDPJAr9Pgd1lOXx8mKqCmj5fK33QeExMpPw==",
|
"integrity": "sha512-2m72QCsja2cJJHD0ALxRnVt0qMEC2FV4LSi6AAiEdEG4lTb6mgcxavx5pJrW90jE+6dMGPbUz4q8c9vi4jh1qQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/browser": "10.48.0",
|
"@sentry/browser": "10.52.0",
|
||||||
"@sentry/core": "10.48.0"
|
"@sentry/core": "10.52.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
@@ -3366,9 +3295,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/remix": {
|
"node_modules/@sentry/remix": {
|
||||||
"version": "10.48.0",
|
"version": "10.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/remix/-/remix-10.48.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/remix/-/remix-10.52.0.tgz",
|
||||||
"integrity": "sha512-ToJ1j9x0tHNM78UrdbjMDNL31nvbRUDdE2rTfeUEt7cQUo7vio68mmqrdnrIo0j6g5rwewWPXkNP+ENBeuzLOQ==",
|
"integrity": "sha512-k6WguxtHupGKDlYW49kJAi7gWUt7uEWP3EpJ2hzdpIZwARcU4Mv5aCZm0tgtQs5O9c+Gq9EJsr+ASoDgM39Lng==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opentelemetry/api": "^1.9.1",
|
"@opentelemetry/api": "^1.9.1",
|
||||||
@@ -3376,9 +3305,9 @@
|
|||||||
"@opentelemetry/semantic-conventions": "^1.40.0",
|
"@opentelemetry/semantic-conventions": "^1.40.0",
|
||||||
"@remix-run/router": "^1.23.2",
|
"@remix-run/router": "^1.23.2",
|
||||||
"@sentry/cli": "^2.58.5",
|
"@sentry/cli": "^2.58.5",
|
||||||
"@sentry/core": "10.48.0",
|
"@sentry/core": "10.52.0",
|
||||||
"@sentry/node": "10.48.0",
|
"@sentry/node": "10.52.0",
|
||||||
"@sentry/react": "10.48.0",
|
"@sentry/react": "10.52.0",
|
||||||
"yargs": "^17.6.0"
|
"yargs": "^17.6.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -3495,9 +3424,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "24.12.2",
|
"version": "24.12.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.3.tgz",
|
||||||
"integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==",
|
"integrity": "sha512-8oljBDGun9cIsZRJR6fkihn0TSXJI0UDOOhncYaERq6M0JMDoPLxyscwruJcb4GKS6dvK/d8xebYBg27h/duaQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~7.16.0"
|
"undici-types": "~7.16.0"
|
||||||
@@ -4082,27 +4011,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/c12": {
|
"node_modules/c12": {
|
||||||
"version": "3.1.0",
|
"version": "3.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/c12/-/c12-3.3.4.tgz",
|
||||||
"integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==",
|
"integrity": "sha512-cM0ApFQSBXuourJejzwv/AuPRvAxordTyParRVcHjjtXirtkzM0uK2L9TTn9s0cXZbG7E55jCivRQzoxYmRAlA==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^4.0.3",
|
"chokidar": "^5.0.0",
|
||||||
"confbox": "^0.2.2",
|
"confbox": "^0.2.4",
|
||||||
"defu": "^6.1.4",
|
"defu": "^6.1.6",
|
||||||
"dotenv": "^16.6.1",
|
"dotenv": "^17.3.1",
|
||||||
"exsolve": "^1.0.7",
|
"exsolve": "^1.0.8",
|
||||||
"giget": "^2.0.0",
|
"giget": "^3.2.0",
|
||||||
"jiti": "^2.4.2",
|
"jiti": "^2.6.1",
|
||||||
"ohash": "^2.0.11",
|
"ohash": "^2.0.11",
|
||||||
"pathe": "^2.0.3",
|
"pathe": "^2.0.3",
|
||||||
"perfect-debounce": "^1.0.0",
|
"perfect-debounce": "^2.1.0",
|
||||||
"pkg-types": "^2.2.0",
|
"pkg-types": "^2.3.0",
|
||||||
"rc9": "^2.1.2"
|
"rc9": "^3.0.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"magicast": "^0.3.5"
|
"magicast": "*"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"magicast": {
|
"magicast": {
|
||||||
@@ -4111,34 +4040,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/c12/node_modules/chokidar": {
|
"node_modules/c12/node_modules/chokidar": {
|
||||||
"version": "4.0.3",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz",
|
||||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
"integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"readdirp": "^4.0.1"
|
"readdirp": "^5.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 14.16.0"
|
"node": ">= 20.19.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://paulmillr.com/funding/"
|
"url": "https://paulmillr.com/funding/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/c12/node_modules/dotenv": {
|
|
||||||
"version": "16.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
|
||||||
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://dotenvx.com"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/c12/node_modules/pathe": {
|
"node_modules/c12/node_modules/pathe": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
||||||
@@ -4147,13 +4063,13 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/c12/node_modules/readdirp": {
|
"node_modules/c12/node_modules/readdirp": {
|
||||||
"version": "4.1.2",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz",
|
||||||
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
"integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 14.18.0"
|
"node": ">= 20.19.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@@ -4369,16 +4285,6 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/citty": {
|
|
||||||
"version": "0.1.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz",
|
|
||||||
"integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"consola": "^3.2.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/cjs-module-lexer": {
|
"node_modules/cjs-module-lexer": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz",
|
||||||
@@ -4534,16 +4440,6 @@
|
|||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/consola": {
|
|
||||||
"version": "3.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz",
|
|
||||||
"integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "^14.18.0 || >=16.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/content-disposition": {
|
"node_modules/content-disposition": {
|
||||||
"version": "0.5.4",
|
"version": "0.5.4",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -4838,7 +4734,7 @@
|
|||||||
"version": "17.4.1",
|
"version": "17.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.1.tgz",
|
||||||
"integrity": "sha512-k8DaKGP6r1G30Lx8V4+pCsLzKr8vLmV2paqEj1Y55GdAgJuIqpRp5FfajGF8KtwMxCz9qJc6wUIJnm053d/WCw==",
|
"integrity": "sha512-k8DaKGP6r1G30Lx8V4+pCsLzKr8vLmV2paqEj1Y55GdAgJuIqpRp5FfajGF8KtwMxCz9qJc6wUIJnm053d/WCw==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
@@ -5701,30 +5597,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/giget": {
|
"node_modules/giget": {
|
||||||
"version": "2.0.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/giget/-/giget-3.2.0.tgz",
|
||||||
"integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==",
|
"integrity": "sha512-GvHTWcykIR/fP8cj8dMpuMMkvaeJfPvYnhq0oW+chSeIr+ldX21ifU2Ms6KBoyKZQZmVaUAAhQ2EZ68KJF8a7A==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
|
||||||
"citty": "^0.1.6",
|
|
||||||
"consola": "^3.4.0",
|
|
||||||
"defu": "^6.1.4",
|
|
||||||
"node-fetch-native": "^1.6.6",
|
|
||||||
"nypm": "^0.6.0",
|
|
||||||
"pathe": "^2.0.3"
|
|
||||||
},
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"giget": "dist/cli.mjs"
|
"giget": "dist/cli.mjs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/giget/node_modules/pathe": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/glob": {
|
"node_modules/glob": {
|
||||||
"version": "10.5.0",
|
"version": "10.5.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -6374,9 +6255,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/jiti": {
|
"node_modules/jiti": {
|
||||||
"version": "2.6.1",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
|
||||||
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
|
"integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -7819,13 +7700,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/node-fetch-native": {
|
|
||||||
"version": "1.6.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz",
|
|
||||||
"integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/node-releases": {
|
"node_modules/node-releases": {
|
||||||
"version": "2.0.27",
|
"version": "2.0.27",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -7911,38 +7785,6 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nypm": {
|
|
||||||
"version": "0.6.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.5.tgz",
|
|
||||||
"integrity": "sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"citty": "^0.2.0",
|
|
||||||
"pathe": "^2.0.3",
|
|
||||||
"tinyexec": "^1.0.2"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"nypm": "dist/cli.mjs"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/nypm/node_modules/citty": {
|
|
||||||
"version": "0.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/citty/-/citty-0.2.2.tgz",
|
|
||||||
"integrity": "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/nypm/node_modules/pathe": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/object-assign": {
|
"node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -8231,9 +8073,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/perfect-debounce": {
|
"node_modules/perfect-debounce": {
|
||||||
"version": "1.0.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz",
|
||||||
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
|
"integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -8556,9 +8398,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prettier": {
|
"node_modules/prettier": {
|
||||||
"version": "3.8.2",
|
"version": "3.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz",
|
||||||
"integrity": "sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q==",
|
"integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -8586,16 +8428,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prisma": {
|
"node_modules/prisma": {
|
||||||
"version": "7.7.0",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-7.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/prisma/-/prisma-7.8.0.tgz",
|
||||||
"integrity": "sha512-HlgwRBt1uEFB9LStHL4HLYDvoi4BNu1rYA0hPG0zCAEyK9SaZBqp7E5Rjpc3Qh8Lex/ye/svoHZ0OWoFNhWxuQ==",
|
"integrity": "sha512-yfN4yrw7HV9kEJhoy1+jgah0jafEIQsf7uWouSsM8MvJtlubsk+kM7AIBWZ8+GJl74Yj3c+nbYqBkMOxtsZ3Lw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/config": "7.7.0",
|
"@prisma/config": "7.8.0",
|
||||||
"@prisma/dev": "0.24.3",
|
"@prisma/dev": "0.24.3",
|
||||||
"@prisma/engines": "7.7.0",
|
"@prisma/engines": "7.8.0",
|
||||||
"@prisma/studio-core": "0.27.3",
|
"@prisma/studio-core": "0.27.3",
|
||||||
"mysql2": "3.15.3",
|
"mysql2": "3.15.3",
|
||||||
"postgres": "3.4.7"
|
"postgres": "3.4.7"
|
||||||
@@ -8794,14 +8636,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rc9": {
|
"node_modules/rc9": {
|
||||||
"version": "2.1.2",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/rc9/-/rc9-3.0.1.tgz",
|
||||||
"integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==",
|
"integrity": "sha512-gMDyleLWVE+i6Sgtc0QbbY6pEKqYs97NGi6isHQPqYlLemPoO8dxQ3uGi0f4NiP98c+jMW6cG1Kx9dDwfvqARQ==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"defu": "^6.1.4",
|
"defu": "^6.1.6",
|
||||||
"destr": "^2.0.3"
|
"destr": "^2.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
@@ -9920,16 +9762,6 @@
|
|||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tinyexec": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/to-regex-range": {
|
"node_modules/to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|||||||
18
package.json
18
package.json
@@ -7,20 +7,20 @@
|
|||||||
"build": "remix build --sourcemap",
|
"build": "remix build --sourcemap",
|
||||||
"check-format": "prettier -c .",
|
"check-format": "prettier -c .",
|
||||||
"format": "prettier -wc .",
|
"format": "prettier -wc .",
|
||||||
"publish": "remix build --sourcemap && wrangler pages deploy public"
|
"publish": "remix build --sourcemap && wrangler pages deploy --upload-source-maps public"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^2.10.9",
|
"@chakra-ui/react": "^2.10.9",
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.1",
|
"@emotion/styled": "^11.14.1",
|
||||||
"@fontsource-variable/plus-jakarta-sans": "^5.2.8",
|
"@fontsource-variable/plus-jakarta-sans": "^5.2.8",
|
||||||
"@prisma/adapter-d1": "^7.7.0",
|
"@prisma/adapter-d1": "^7.8.0",
|
||||||
"@prisma/client": "^7.7.0",
|
"@prisma/client": "^7.8.0",
|
||||||
"@remix-run/cloudflare": "^2.17.4",
|
"@remix-run/cloudflare": "^2.17.4",
|
||||||
"@remix-run/cloudflare-pages": "^2.17.4",
|
"@remix-run/cloudflare-pages": "^2.17.4",
|
||||||
"@remix-run/react": "^2.17.4",
|
"@remix-run/react": "^2.17.4",
|
||||||
"@sentry/cloudflare": "^10.48.0",
|
"@sentry/cloudflare": "^10.52.0",
|
||||||
"@sentry/remix": "^10.48.0",
|
"@sentry/remix": "^10.52.0",
|
||||||
"aws4fetch": "^1.0.20",
|
"aws4fetch": "^1.0.20",
|
||||||
"dayjs": "^1.11.20",
|
"dayjs": "^1.11.20",
|
||||||
"framer-motion": "^12.38.0",
|
"framer-motion": "^12.38.0",
|
||||||
@@ -30,17 +30,17 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@remix-run/dev": "^2.17.4",
|
"@remix-run/dev": "^2.17.4",
|
||||||
"@types/node": "^24.12.2",
|
"@types/node": "^24.12.3",
|
||||||
"@types/react": "^18.3.28",
|
"@types/react": "^18.3.28",
|
||||||
"@types/react-big-calendar": "^1.16.3",
|
"@types/react-big-calendar": "^1.16.3",
|
||||||
"@types/react-dom": "^18.3.7",
|
"@types/react-dom": "^18.3.7",
|
||||||
"dotenv": "^17.4.1",
|
"dotenv": "^17.4.1",
|
||||||
"prettier": "^3.8.2",
|
"prettier": "^3.8.3",
|
||||||
"prisma": "^7.7.0",
|
"prisma": "^7.8.0",
|
||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"@cloudflare/workers-types": "^4.20260329.1"
|
"@cloudflare/workers-types": "^4.20260511.1"
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"endOfLine": "auto"
|
"endOfLine": "auto"
|
||||||
|
|||||||
@@ -29,6 +29,18 @@ model AppealBan {
|
|||||||
@@map("appeal_bans")
|
@@map("appeal_bans")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model DataRequest {
|
||||||
|
created_at DateTime @default(now())
|
||||||
|
id String @id @unique
|
||||||
|
originating_user Int?
|
||||||
|
status String
|
||||||
|
target_user Int
|
||||||
|
type String
|
||||||
|
|
||||||
|
@@index([created_at], name: "idx_data_requests_created_at")
|
||||||
|
@@map("data_requests")
|
||||||
|
}
|
||||||
|
|
||||||
model EtMember {
|
model EtMember {
|
||||||
created_at DateTime @default(now())
|
created_at DateTime @default(now())
|
||||||
created_by String
|
created_by String
|
||||||
@@ -149,7 +161,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