Panel şu ana kadar herkese açıktı — URL'yi bilen herkes kanal ekleyip/silebilir, cookie güncelleyebilir, kayıt indirebilirdi. - users tablosu (bcrypt şifre hash'i) - /login: hiç kullanıcı yoksa "ilk admin hesabı oluştur" formu, varsa normal giriş formu - jose ile imzalanmış, httpOnly çerezde tutulan 30 günlük oturum - middleware.ts: /login hariç tüm rotaları korur (video stream route'u dahil — aynı origin istekleri çerezi otomatik taşır) - layout: oturum yoksa nav hiç gösterilmiyor, varsa kullanıcı adı + çıkış butonu ekleniyor SESSION_SECRET production'da zorunlu (docker-compose derleme zamanında kontrol ediyor); Coolify'a rastgele bir değer eklendi. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
72 lines
1.9 KiB
TypeScript
72 lines
1.9 KiB
TypeScript
import { prisma } from "@streamclipper/db";
|
||
import { bootstrapAdmin, login } from "./actions";
|
||
|
||
export const dynamic = "force-dynamic";
|
||
|
||
const fieldStyle = {
|
||
background: "var(--bg)",
|
||
border: "1px solid var(--border)",
|
||
borderRadius: "6px",
|
||
padding: "0.6rem 0.7rem",
|
||
color: "var(--text)",
|
||
fontSize: "0.9rem",
|
||
};
|
||
|
||
const buttonStyle = {
|
||
background: "var(--accent)",
|
||
border: "none",
|
||
borderRadius: "6px",
|
||
padding: "0.6rem 1rem",
|
||
color: "#fff",
|
||
fontWeight: 600,
|
||
fontSize: "0.9rem",
|
||
cursor: "pointer",
|
||
};
|
||
|
||
export default async function LoginPage({
|
||
searchParams,
|
||
}: {
|
||
searchParams: Promise<{ error?: string }>;
|
||
}) {
|
||
const { error } = await searchParams;
|
||
const userCount = await prisma.user.count();
|
||
const isBootstrap = userCount === 0;
|
||
|
||
return (
|
||
<div style={{ maxWidth: "360px", margin: "4rem auto" }}>
|
||
<h1>{isBootstrap ? "İlk Yönetici Hesabını Oluştur" : "Giriş Yap"}</h1>
|
||
|
||
{isBootstrap && (
|
||
<p className="empty" style={{ marginBottom: "1rem" }}>
|
||
Henüz kullanıcı yok — panele erişecek ilk admin hesabını burada oluştur.
|
||
</p>
|
||
)}
|
||
|
||
{!isBootstrap && error && (
|
||
<p style={{ color: "var(--err)", fontSize: "0.9rem", marginBottom: "1rem" }}>
|
||
Kullanıcı adı veya şifre hatalı.
|
||
</p>
|
||
)}
|
||
|
||
<form
|
||
action={isBootstrap ? bootstrapAdmin : login}
|
||
className="card"
|
||
style={{ display: "flex", flexDirection: "column", gap: "0.6rem" }}
|
||
>
|
||
<input name="username" placeholder="Kullanıcı adı" required style={fieldStyle} />
|
||
<input
|
||
name="password"
|
||
type="password"
|
||
placeholder="Şifre"
|
||
required
|
||
minLength={isBootstrap ? 8 : undefined}
|
||
style={fieldStyle}
|
||
/>
|
||
<button type="submit" style={buttonStyle}>
|
||
{isBootstrap ? "Hesabı Oluştur" : "Giriş Yap"}
|
||
</button>
|
||
</form>
|
||
</div>
|
||
);
|
||
}
|