|
@@ -1,24 +1,49 @@
|
|
|
-import { NextResponse } from "next/server";
|
|
|
|
|
|
|
+import { NextRequest, NextResponse } from "next/server";
|
|
|
import { getSupabaseServerClient } from "@/lib/supabase/server";
|
|
import { getSupabaseServerClient } from "@/lib/supabase/server";
|
|
|
import { getSupabaseAdminClient } from "@/lib/supabase/admin";
|
|
import { getSupabaseAdminClient } from "@/lib/supabase/admin";
|
|
|
import { generateRecoveryCode, hashRecoveryCode } from "@/lib/auth/recovery";
|
|
import { generateRecoveryCode, hashRecoveryCode } from "@/lib/auth/recovery";
|
|
|
|
|
|
|
|
-export async function POST() {
|
|
|
|
|
|
|
+export async function POST(request: NextRequest) {
|
|
|
try {
|
|
try {
|
|
|
- const supabase = await getSupabaseServerClient();
|
|
|
|
|
- const {
|
|
|
|
|
- data: { user },
|
|
|
|
|
- } = await supabase.auth.getUser();
|
|
|
|
|
|
|
+ // Prefer the Authorization: Bearer header (sent explicitly by the client)
|
|
|
|
|
+ // because the @supabase/ssr cookie sync after signInAnonymously() can lag
|
|
|
|
|
+ // behind the immediate router.push("/recovery") navigation, leaving the
|
|
|
|
|
+ // server with no/stale auth cookies and a spurious 401. Falling back to
|
|
|
|
|
+ // the cookie-based server client preserves existing behavior for any
|
|
|
|
|
+ // caller that doesn't send the header.
|
|
|
|
|
+ const authHeader = request.headers.get("authorization");
|
|
|
|
|
+ const bearerToken = authHeader?.toLowerCase().startsWith("bearer ")
|
|
|
|
|
+ ? authHeader.slice(7).trim()
|
|
|
|
|
+ : null;
|
|
|
|
|
|
|
|
- if (!user) {
|
|
|
|
|
|
|
+ const admin = getSupabaseAdminClient();
|
|
|
|
|
+ let userId: string | null = null;
|
|
|
|
|
+
|
|
|
|
|
+ if (bearerToken) {
|
|
|
|
|
+ const { data, error } = await admin.auth.getUser(bearerToken);
|
|
|
|
|
+ if (!error && data.user) {
|
|
|
|
|
+ userId = data.user.id;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!userId) {
|
|
|
|
|
+ const supabase = await getSupabaseServerClient();
|
|
|
|
|
+ const {
|
|
|
|
|
+ data: { user },
|
|
|
|
|
+ } = await supabase.auth.getUser();
|
|
|
|
|
+ if (user) {
|
|
|
|
|
+ userId = user.id;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!userId) {
|
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const code = generateRecoveryCode();
|
|
const code = generateRecoveryCode();
|
|
|
const hashed = await hashRecoveryCode(code);
|
|
const hashed = await hashRecoveryCode(code);
|
|
|
|
|
|
|
|
- const admin = getSupabaseAdminClient();
|
|
|
|
|
- const { error } = await admin.from("users").update({ recovery_code: hashed }).eq("id", user.id);
|
|
|
|
|
|
|
+ const { error } = await admin.from("users").update({ recovery_code: hashed }).eq("id", userId);
|
|
|
|
|
|
|
|
if (error) {
|
|
if (error) {
|
|
|
return NextResponse.json({ error: "Failed to store recovery code" }, { status: 500 });
|
|
return NextResponse.json({ error: "Failed to store recovery code" }, { status: 500 });
|