Remove data transfer code
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user