import { formatDiscordNickname } from "@minecraft-account-manager/minecraft"; import { ipIntelligence, ipObservations, minecraftAccounts } from "@minecraft-account-manager/database"; import { and, desc, eq, isNull } from "drizzle-orm"; import { logout } from "@/app/auth/actions"; import { db } from "@/lib/database"; import { requireCurrentUser } from "@/lib/auth/user-session"; import { intelligenceSummary } from "@/lib/event-ip-summary"; import { addMinecraftAccount, confirmDashboardNickname, removeMinecraftAccount, setPrimaryAccount, updateFirstName, } from "./actions"; const errorMessages: Record = { "invalid-name": "Enter a valid name between 1 and 50 characters.", "invalid-username": "Java usernames use 3–16 letters, numbers, or underscores.", "already-registered": "That Minecraft account is already registered.", "unknown-account": "That account is no longer available.", "nickname-not-configured": "Discord nickname updates are not configured.", "nickname-update-failed": "Discord rejected the nickname update. An admin may need to adjust bot permissions.", "vpn-blocked": "Turn off your VPN, proxy, or Tor connection before adding a Minecraft account.", "ip-check-unavailable": "We could not verify your network, so account addition is temporarily blocked.", }; export default async function AccountPage({ searchParams, }: { searchParams: Promise>; }) { const user = await requireCurrentUser("/account"); const query = await searchParams; const [accounts, observations] = await Promise.all([ db .select() .from(minecraftAccounts) .where(and(eq(minecraftAccounts.userId, user.id), isNull(minecraftAccounts.deletedAt))) .orderBy(desc(minecraftAccounts.isPrimary), minecraftAccounts.username), db .select({ id: ipObservations.id, ipAddress: ipObservations.ipAddress, source: ipObservations.source, classification: ipObservations.classification, observedAt: ipObservations.observedAt, intelligence: ipIntelligence.rawResponse, }) .from(ipObservations) .leftJoin(ipIntelligence, eq(ipIntelligence.ipAddress, ipObservations.ipAddress)) .where(eq(ipObservations.userId, user.id)) .orderBy(desc(ipObservations.observedAt)) .limit(20), ]); const primary = accounts.find((account) => account.isPrimary); const desiredNickname = user.firstName && primary ? formatDiscordNickname(user.firstName, primary.username) : null; return (

Account registry

{user.firstName ?? user.discordUsername}

{query.error && (

{errorMessages[query.error] ?? "The requested change could not be completed."}

)} {query.nicknameUpdated &&

Discord nickname updated

} {query.confirmNickname && desiredNickname && (

Confirm Discord change

Your community nickname will become

{desiredNickname}

)}

Whitelist identities

Minecraft accounts

{accounts.length} active
{accounts.map((account) => (

{account.username}

{account.isPrimary && Primary} {account.validationStatus === "verified" ? "UUID verified" : "User confirmed"}

{account.minecraftUuid ?? "UUID will be learned at game login"}

{!account.isPrimary &&
}
))} {accounts.length === 0 &&

No active Minecraft accounts. Add one before joining the server.

}
{query.unverified ? (

Mojang couldn’t verify “{query.unverified}”

Continue only if you are certain the spelling is correct.

Cancel
) : (
)}

Recent security activity

Access addresses

{observations.length ? (
{observations.map((observation) => { const summary = intelligenceSummary(observation.intelligence); return

{observation.ipAddress}

{summary.location ?? "Location unavailable"} · {summary.classification ?? observation.classification}

{observation.source} · {observation.observedAt.toISOString()}
; })}
) :

No web or game access addresses have been recorded yet.

}
); }