Files
kovakyazilim/app/admin/login/actions.ts
T
Ege Can Komur 7eb0c1acc2 fix(auth): SDK'yı kaldırıp ince REST katmanına geç (lib/appwrite-rest.ts)
Sorun:
- node-appwrite v20-25 hepsi Node 26'da bozuk (node-fetch-native-with-agent polyfill)
- appwrite browser SDK Server Action context'inde 'unexpected response' veriyor
  (büyük olasılıkla browser-only global'ları kontrol ederken)

Çözüm:
- Tüm Appwrite SDK'larını sil (appwrite + node-appwrite)
- lib/appwrite-rest.ts: native fetch üzerinde ~250 satırlık ince REST wrapper
  - account: createEmailPasswordSession, get, deleteSession
  - tablesDB: listRows, getRow, createRow, updateRow, deleteRow
  - storage: listFiles, createFile, deleteFile, fileViewUrl
  - Q helpers: equal, orderAsc/Desc, limit, offset
  - AppwriteError class
- Session secret cookie tabanlı auth korundu (isletmem-kovakcrm'deki desen)
- Tüm CRUD action ve query'ler REST katmanına bağlandı

End-to-end test edildi:
✓ Login (proper 401 hata mesajları, başarılı durumda redirect)
✓ Public read (services, blog, testimonials)
✓ Anonim create (contact form)
✓ Build (24 route)
✓ Sıfır SDK bağımlılığı — Node 26 sorunu yok
2026-05-20 02:29:19 +03:00

67 lines
1.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use server";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
import { account, AppwriteError } from "@/lib/appwrite-rest";
import { SESSION_COOKIE } from "@/lib/auth";
export type LoginState = { error?: string };
function friendly(err: unknown): string {
if (err instanceof AppwriteError) {
switch (err.type) {
case "user_invalid_credentials":
return "E-posta veya şifre hatalı.";
case "user_blocked":
return "Hesabınız engellenmiş.";
case "general_rate_limit_exceeded":
return "Çok fazla deneme. Birkaç dakika sonra tekrar deneyin.";
default:
return err.message;
}
}
return err instanceof Error ? err.message : "Giriş başarısız";
}
export async function loginAction(
_prev: LoginState | undefined,
formData: FormData,
): Promise<LoginState> {
const email = String(formData.get("email") ?? "").trim();
const password = String(formData.get("password") ?? "");
if (!email || !password) return { error: "E-posta ve şifre zorunlu" };
let session;
try {
session = await account.createEmailPasswordSession(email, password);
} catch (err) {
return { error: friendly(err) };
}
const store = await cookies();
store.set(SESSION_COOKIE, session.secret, {
httpOnly: true,
sameSite: "lax",
secure: process.env.NODE_ENV === "production",
path: "/",
expires: new Date(session.expire),
});
redirect("/admin");
}
export async function logoutAction() {
const store = await cookies();
const secret = store.get(SESSION_COOKIE)?.value;
if (secret) {
try {
await account.deleteSession("current", secret);
} catch {
// ignore — cookie is cleared anyway
}
}
store.delete(SESSION_COOKIE);
redirect("/admin/login");
}