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>
41 lines
1.2 KiB
TypeScript
41 lines
1.2 KiB
TypeScript
import { cookies } from "next/headers";
|
|
import { SignJWT, jwtVerify } from "jose";
|
|
|
|
export const SESSION_COOKIE_NAME = "session";
|
|
|
|
const secret = new TextEncoder().encode(
|
|
process.env.SESSION_SECRET ?? "dev-insecure-secret-change-me-in-production",
|
|
);
|
|
|
|
export interface SessionPayload {
|
|
sub: string;
|
|
username: string;
|
|
}
|
|
|
|
export async function createSessionToken(payload: SessionPayload): Promise<string> {
|
|
return new SignJWT({ username: payload.username })
|
|
.setProtectedHeader({ alg: "HS256" })
|
|
.setSubject(payload.sub)
|
|
.setIssuedAt()
|
|
.setExpirationTime("30d")
|
|
.sign(secret);
|
|
}
|
|
|
|
export async function verifySessionToken(token: string): Promise<SessionPayload | null> {
|
|
try {
|
|
const { payload } = await jwtVerify(token, secret);
|
|
if (typeof payload.sub !== "string" || typeof payload.username !== "string") return null;
|
|
return { sub: payload.sub, username: payload.username };
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/** Server Component helper — reads and verifies the session cookie. */
|
|
export async function getSession(): Promise<SessionPayload | null> {
|
|
const jar = await cookies();
|
|
const token = jar.get(SESSION_COOKIE_NAME)?.value;
|
|
if (!token) return null;
|
|
return verifySessionToken(token);
|
|
}
|