Files
screenclipper/apps/frontend/app/layout.tsx
T
ayrisdevandClaude Sonnet 5 fb8485d638 feat: panele auth sistemi ekle (kullanıcı/şifre + oturum + middleware)
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>
2026-09-01 11:26:42 +03:00

40 lines
1.2 KiB
TypeScript

import type { Metadata } from "next";
import Link from "next/link";
import "./globals.css";
import { getSession } from "../lib/auth";
import { logout } from "./login/actions";
export const metadata: Metadata = {
title: "StreamClipper AI — Panel",
};
export default async function RootLayout({ children }: { children: React.ReactNode }) {
const session = await getSession();
return (
<html lang="tr">
<body>
{session && (
<nav className="nav">
<Link href="/">Kanal Durumu</Link>
<Link href="/segments">Segment & Aday Kütüphanesi</Link>
<Link href="/settings">Ayarlar</Link>
<span style={{ marginLeft: "auto", display: "flex", gap: "1rem", alignItems: "center" }}>
<span className="mono">{session.username}</span>
<form action={logout}>
<button
type="submit"
style={{ background: "none", border: "none", color: "var(--muted)", cursor: "pointer", font: "inherit" }}
>
Çıkış Yap
</button>
</form>
</span>
</nav>
)}
<main>{children}</main>
</body>
</html>
);
}