Admin endpoint to link mrpiglr@aethex.dev to mrpiglr@gmail.com
cgen-74a5436d775747868dc1bf6c22299d8a
This commit is contained in:
parent
733ccf2df6
commit
555103564f
1 changed files with 248 additions and 0 deletions
248
api/user/link-mrpiglr-accounts.ts
Normal file
248
api/user/link-mrpiglr-accounts.ts
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
import { getAdminClient } from "../_supabase";
|
||||
|
||||
/**
|
||||
* Admin-only endpoint to link mrpiglr@aethex.dev to mrpiglr@gmail.com
|
||||
* Both emails are tied to the same person, so they should share the same account.
|
||||
* Primary account: mrpiglr@aethex.dev (work email for dev account)
|
||||
* Linked account: mrpiglr@gmail.com (personal email, merges into work account)
|
||||
*/
|
||||
export default async (req: Request) => {
|
||||
if (req.method !== "POST") {
|
||||
return new Response(JSON.stringify({ error: "Method not allowed" }), {
|
||||
status: 405,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
// Check authorization header for admin token
|
||||
const authHeader = req.headers.get("authorization");
|
||||
const adminToken = authHeader?.replace("Bearer ", "");
|
||||
|
||||
// Simple token check (in production, use more robust auth)
|
||||
if (adminToken !== "mrpiglr-admin-token") {
|
||||
return new Response(JSON.stringify({ error: "Unauthorized" }), {
|
||||
status: 401,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
const supabase = getAdminClient();
|
||||
const primaryEmail = "mrpiglr@aethex.dev";
|
||||
const linkedEmail = "mrpiglr@gmail.com";
|
||||
|
||||
console.log(`[Email Linking] Starting mrpiglr account linking...`);
|
||||
|
||||
// Fetch the primary user (work email)
|
||||
const { data: primaryUser, error: primaryError } = await supabase
|
||||
.from("user_profiles")
|
||||
.select("user_id, email")
|
||||
.eq("email", primaryEmail)
|
||||
.single();
|
||||
|
||||
if (primaryError || !primaryUser) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: "Primary email not found",
|
||||
email: primaryEmail,
|
||||
details: primaryError?.message,
|
||||
}),
|
||||
{ status: 404, headers: { "Content-Type": "application/json" } }
|
||||
);
|
||||
}
|
||||
|
||||
// Fetch the linked user (personal email)
|
||||
const { data: linkedUser, error: linkedError } = await supabase
|
||||
.from("user_profiles")
|
||||
.select("user_id, email")
|
||||
.eq("email", linkedEmail)
|
||||
.single();
|
||||
|
||||
if (linkedError || !linkedUser) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: "Linked email not found",
|
||||
email: linkedEmail,
|
||||
details: linkedError?.message,
|
||||
}),
|
||||
{ status: 404, headers: { "Content-Type": "application/json" } }
|
||||
);
|
||||
}
|
||||
|
||||
const sourceUserId = linkedUser.user_id; // gmail account
|
||||
const targetUserId = primaryUser.user_id; // aethex.dev account
|
||||
|
||||
console.log(`[Email Linking] Merging ${sourceUserId} into ${targetUserId}`);
|
||||
|
||||
// 1. Transfer achievements
|
||||
console.log(`[Email Linking] Transferring achievements...`);
|
||||
const { error: achievementError } = await supabase
|
||||
.from("achievements_earned")
|
||||
.update({ user_id: targetUserId })
|
||||
.eq("user_id", sourceUserId);
|
||||
if (achievementError) {
|
||||
console.warn("Achievement transfer warning:", achievementError);
|
||||
}
|
||||
|
||||
// 2. Transfer aethex_creators profile
|
||||
console.log(`[Email Linking] Checking for creator profile...`);
|
||||
const { data: creatorProfile } = await supabase
|
||||
.from("aethex_creators")
|
||||
.select("*")
|
||||
.eq("user_id", sourceUserId)
|
||||
.single();
|
||||
|
||||
if (creatorProfile) {
|
||||
console.log(`[Email Linking] Transferring creator profile...`);
|
||||
await supabase
|
||||
.from("aethex_creators")
|
||||
.update({ user_id: targetUserId })
|
||||
.eq("user_id", sourceUserId);
|
||||
}
|
||||
|
||||
// 3. Transfer applications
|
||||
console.log(`[Email Linking] Transferring applications...`);
|
||||
const { error: appError } = await supabase
|
||||
.from("aethex_applications")
|
||||
.update({ user_id: targetUserId })
|
||||
.eq("user_id", sourceUserId);
|
||||
if (appError) {
|
||||
console.warn("Application transfer warning:", appError);
|
||||
}
|
||||
|
||||
// 4. Transfer discord_links
|
||||
console.log(`[Email Linking] Checking for discord links...`);
|
||||
const { data: discordLinks } = await supabase
|
||||
.from("discord_links")
|
||||
.select("*")
|
||||
.eq("user_id", sourceUserId);
|
||||
|
||||
if (discordLinks && discordLinks.length > 0) {
|
||||
console.log(
|
||||
`[Email Linking] Found ${discordLinks.length} discord links, transferring...`
|
||||
);
|
||||
for (const link of discordLinks) {
|
||||
const { data: existing } = await supabase
|
||||
.from("discord_links")
|
||||
.select("*")
|
||||
.eq("user_id", targetUserId);
|
||||
|
||||
if (!existing || existing.length === 0) {
|
||||
await supabase
|
||||
.from("discord_links")
|
||||
.update({ user_id: targetUserId })
|
||||
.eq("id", link.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Transfer web3_wallets if they exist
|
||||
console.log(`[Email Linking] Checking for web3 wallets...`);
|
||||
const { data: web3Links } = await supabase
|
||||
.from("web3_wallets")
|
||||
.select("*")
|
||||
.eq("user_id", sourceUserId);
|
||||
|
||||
if (web3Links && web3Links.length > 0) {
|
||||
console.log(
|
||||
`[Email Linking] Found ${web3Links.length} web3 wallets, transferring...`
|
||||
);
|
||||
for (const wallet of web3Links) {
|
||||
const { data: existing } = await supabase
|
||||
.from("web3_wallets")
|
||||
.select("*")
|
||||
.eq("user_id", targetUserId)
|
||||
.eq("wallet_address", wallet.wallet_address);
|
||||
|
||||
if (!existing || existing.length === 0) {
|
||||
await supabase
|
||||
.from("web3_wallets")
|
||||
.update({ user_id: targetUserId })
|
||||
.eq("id", wallet.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 6. Link both emails in user_email_links
|
||||
console.log(`[Email Linking] Creating email links...`);
|
||||
const { data: existingLinks } = await supabase
|
||||
.from("user_email_links")
|
||||
.select("*")
|
||||
.in("email", [primaryEmail, linkedEmail]);
|
||||
|
||||
// Insert primary email
|
||||
const primaryEmailExists = existingLinks?.some(
|
||||
(l) => l.email === primaryEmail
|
||||
);
|
||||
if (!primaryEmailExists) {
|
||||
await supabase.from("user_email_links").insert({
|
||||
user_id: targetUserId,
|
||||
email: primaryEmail,
|
||||
is_primary: true,
|
||||
verified_at: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
// Insert linked email
|
||||
const linkedEmailExists = existingLinks?.some(
|
||||
(l) => l.email === linkedEmail
|
||||
);
|
||||
if (!linkedEmailExists) {
|
||||
await supabase.from("user_email_links").insert({
|
||||
user_id: targetUserId,
|
||||
email: linkedEmail,
|
||||
is_primary: false,
|
||||
verified_at: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
// 7. Update user_profiles
|
||||
console.log(`[Email Linking] Updating user profiles...`);
|
||||
await supabase
|
||||
.from("user_profiles")
|
||||
.update({
|
||||
primary_email: primaryEmail,
|
||||
is_dev_account: true,
|
||||
})
|
||||
.eq("user_id", targetUserId);
|
||||
|
||||
// Mark source profile as merged
|
||||
await supabase
|
||||
.from("user_profiles")
|
||||
.update({
|
||||
merged_to_user_id: targetUserId,
|
||||
updated_at: new Date().toISOString(),
|
||||
})
|
||||
.eq("user_id", sourceUserId);
|
||||
|
||||
console.log(`[Email Linking] ✅ Successfully linked mrpiglr accounts`);
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
message: "Successfully linked mrpiglr@aethex.dev and mrpiglr@gmail.com",
|
||||
primaryEmail,
|
||||
linkedEmail,
|
||||
targetUserId,
|
||||
sourceUserId,
|
||||
note: "Both emails can now log in and will access the same account. Primary account is mrpiglr@aethex.dev (work/dev account).",
|
||||
}),
|
||||
{
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
}
|
||||
);
|
||||
} catch (error: any) {
|
||||
console.error("[Email Linking Error]", error);
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: "Failed to link mrpiglr accounts",
|
||||
details: error.message,
|
||||
}),
|
||||
{
|
||||
status: 500,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
Loading…
Reference in a new issue