feat: implement internal auth user creation and update related functionalities

This commit is contained in:
Poyraz Avsever
2026-06-14 12:41:00 +03:00
parent 8fa89168c3
commit b1620d4748
19 changed files with 382 additions and 129 deletions
+71 -91
View File
@@ -1,123 +1,103 @@
import { createInternalAuthUser } from "@/lib/auth/internal-users";
import { createClient } from "@/lib/supabase/server";
import { NextResponse } from "next/server";
type SupabaseAdminUserResponse = {
id?: string;
email?: string;
message?: string;
error_description?: string;
};
export async function POST(request: Request) {
try {
const { email, password, client_id } = await request.json();
if (!email || !password || !client_id) {
return NextResponse.json(
{ error: "Email, şifre ve müşteri ID gereklidir." },
{ error: "E-posta, şifre ve müşteri ID gereklidir." },
{ status: 400 },
);
}
const supabaseUrl =
process.env.SUPABASE_INTERNAL_URL || process.env.NEXT_PUBLIC_SUPABASE_URL;
const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY;
const supabase = await createClient();
const {
data: { user },
error: userError,
} = await supabase.auth.getUser();
if (!supabaseUrl || !serviceRoleKey) {
if (userError || !user) {
return NextResponse.json(
{ error: "Supabase service role ayarı eksik." },
{ status: 500 },
{ error: "Müşteri hesabı oluşturmak için giriş yapmalısınız." },
{ status: 401 },
);
}
const userResponse = await fetch(`${supabaseUrl}/auth/v1/admin/users`, {
method: "POST",
headers: getServiceHeaders(serviceRoleKey),
body: JSON.stringify({
email,
password,
email_confirm: true,
app_metadata: {
internal_created: true,
role: "client",
},
}),
});
const userPayload = (await userResponse.json()) as SupabaseAdminUserResponse;
const { data: client, error: clientError } = await supabase
.from("clients")
.select("id, client_auth_id")
.eq("id", client_id)
.eq("user_id", user.id)
.single();
if (!userResponse.ok || !userPayload.id) {
if (clientError || !client) {
return NextResponse.json(
{ error: "Müşteri kaydı bulunamadı." },
{ status: 404 },
);
}
if (client.client_auth_id) {
return NextResponse.json(
{ error: "Bu müşteri için portal hesabı zaten oluşturulmuş." },
{ status: 409 },
);
}
const {
admin,
user: createdUser,
userId,
} = await createInternalAuthUser({
email,
password,
role: "client",
reason: "client_portal",
});
const { error: profileError } = await admin
.from("profiles")
.update({ role: "client" })
.eq("id", userId);
if (profileError) {
return NextResponse.json(
{
error:
userPayload.message ||
userPayload.error_description ||
"Kullanıcı oluşturulamadı.",
error: `Kullanıcı oluşturuldu fakat profil rolü güncellenemedi: ${profileError.message}`,
},
{ status: 400 },
);
}
const userId = userPayload.id;
await patchRestRow({
supabaseUrl,
serviceRoleKey,
table: "profiles",
filter: `id=eq.${encodeURIComponent(userId)}`,
payload: { role: "client" },
});
const clientResponse = await patchRestRow({
supabaseUrl,
serviceRoleKey,
table: "clients",
filter: `id=eq.${encodeURIComponent(client_id)}`,
payload: { client_auth_id: userId },
});
if (!clientResponse.ok) {
return NextResponse.json(
{ error: "Kullanıcı oluşturuldu fakat müşteri kaydıyla ilişkilendirilemedi." },
{ status: 500 },
);
}
return NextResponse.json({ success: true, user: userPayload });
const { error: updateClientError } = await admin
.from("clients")
.update({ client_auth_id: userId })
.eq("id", client_id)
.eq("user_id", user.id);
if (updateClientError) {
return NextResponse.json(
{
error: `Kullanıcı oluşturuldu fakat müşteri kaydıyla ilişkilendirilemedi: ${updateClientError.message}`,
},
{ status: 500 },
);
}
return NextResponse.json({ success: true, user: createdUser });
} catch (error) {
console.error("Create client user error:", error);
return NextResponse.json(
{ error: "Sunucu tarafında beklenmeyen bir hata oluştu." },
{
error:
error instanceof Error
? error.message
: "Sunucu tarafında beklenmeyen bir hata oluştu.",
},
{ status: 500 },
);
}
}
function getServiceHeaders(serviceRoleKey: string) {
return {
apikey: serviceRoleKey,
authorization: `Bearer ${serviceRoleKey}`,
"content-type": "application/json",
};
}
function patchRestRow({
supabaseUrl,
serviceRoleKey,
table,
filter,
payload,
}: {
supabaseUrl: string;
serviceRoleKey: string;
table: string;
filter: string;
payload: Record<string, unknown>;
}) {
return fetch(`${supabaseUrl}/rest/v1/${table}?${filter}`, {
method: "PATCH",
headers: {
...getServiceHeaders(serviceRoleKey),
prefer: "return=minimal",
},
body: JSON.stringify(payload),
});
}