From a54b28bba8e346c3c71812d70c6e062e8199a244 Mon Sep 17 00:00:00 2001 From: anonymousratwastaken Date: Sun, 15 Mar 2026 17:48:02 +0000 Subject: [PATCH] feat: Integrate Authentik for account creation Add support for creating Authentik invitations after successful whitelisting. The invite URL is now stored in local storage and displayed to the user. Refactor Bedrock profile fetching to use a new action. --- src/app/access/[method]/[step]/page.tsx | 48 ++++++++++--- src/app/actions.ts | 6 ++ src/app/api/whitelist/route.ts | 20 ++++++ src/lib/authentik.ts | 93 +++++++++++++++++++++++++ src/lib/cfg.ts | 5 ++ 5 files changed, 163 insertions(+), 9 deletions(-) create mode 100644 src/lib/authentik.ts diff --git a/src/app/access/[method]/[step]/page.tsx b/src/app/access/[method]/[step]/page.tsx index aeb2722..7a47251 100644 --- a/src/app/access/[method]/[step]/page.tsx +++ b/src/app/access/[method]/[step]/page.tsx @@ -15,7 +15,7 @@ import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { cfg } from "@/lib/cfg"; -import { getAvatarProfile } from "@/lib/avatar"; +import { verifyAccessCode, getBedrockProfile } from "@/app/actions"; import localFont from "next/font/local"; @@ -42,6 +42,7 @@ export default function AccessPage({ params }: PageProps) { const [code, setCode] = useState(""); const [verified, setVerified] = useState(false); const [whitelistSuccess, setWhitelistSuccess] = useState(false); + const [inviteUrl, setInviteUrl] = useState(null); const [status, setStatus] = useState<{ ok: boolean; message?: string }>({ ok: false }); const [isPending, startTransition] = useTransition(); @@ -102,6 +103,7 @@ export default function AccessPage({ params }: PageProps) { const savedVerified = localStorage.getItem(`${prefix}verified`); const savedWhitelistSuccess = localStorage.getItem(`${prefix}whitelist-success`); + const savedInviteUrl = localStorage.getItem(`${prefix}invite-url`); const savedCode = localStorage.getItem(`${prefix}auth-code`); const savedJavaName = localStorage.getItem(`${prefix}java-name`); const savedBedrockName = localStorage.getItem(`${prefix}bedrock-name`); @@ -115,6 +117,9 @@ export default function AccessPage({ params }: PageProps) { if (savedWhitelistSuccess === 'true') { setWhitelistSuccess(true); } + if (savedInviteUrl) { + setInviteUrl(savedInviteUrl); + } if (savedCode) { setCode(savedCode); } @@ -154,6 +159,11 @@ export default function AccessPage({ params }: PageProps) { localStorage.setItem(`${prefix}whitelist-success`, whitelistSuccess.toString()); }, [whitelistSuccess, method]); + useEffect(() => { + const prefix = method === 'qr' ? 'frg-qr-' : 'frg-'; + localStorage.setItem(`${prefix}invite-url`, inviteUrl || ""); + }, [inviteUrl, method]); + useEffect(() => { const prefix = method === 'qr' ? 'frg-qr-' : 'frg-'; localStorage.setItem(`${prefix}auth-code`, code); @@ -200,11 +210,11 @@ export default function AccessPage({ params }: PageProps) { const fetchProfileData = async () => { try { - const res = await fetch( - `/api/xbox/profile/get?gamertag=${encodeURIComponent(cfg.server.bedrockFriend)}` - ); - const data = await res.json(); - setProfileData(data); + const data = await getBedrockProfile(cfg.server.bedrockFriend); + setProfileData({ + avatarUrl: data.avatarUrl, + gamertag: data.gamertag + }); } catch (e) { console.error("Failed to fetch profile", e); } @@ -330,6 +340,11 @@ export default function AccessPage({ params }: PageProps) { }); setWhitelistSuccess(true); + // If Authentik invite URL is provided, store it + if (result.inviteUrl) { + setInviteUrl(result.inviteUrl); + } + // Navigate to success step router.push(`/access/${method}/success`); } else { @@ -400,6 +415,7 @@ export default function AccessPage({ params }: PageProps) { const prefix = method === 'qr' ? 'frg-qr-' : 'frg-'; localStorage.removeItem(`${prefix}verified`); localStorage.removeItem(`${prefix}whitelist-success`); + localStorage.removeItem(`${prefix}invite-url`); localStorage.removeItem(`${prefix}auth-code`); localStorage.removeItem(`${prefix}java-name`); localStorage.removeItem(`${prefix}bedrock-name`); @@ -409,6 +425,7 @@ export default function AccessPage({ params }: PageProps) { setVerified(false); setWhitelistSuccess(false); + setInviteUrl(null); setCode(""); setJavaName(""); setBedrockName(""); @@ -733,16 +750,16 @@ export default function AccessPage({ params }: PageProps) { - + ? - {cfg.server.bedrockFriend} + {profileData?.gamertag || cfg.server.bedrockFriend} +

+ An account lets you manage your profile and access more features. +

+ + )}