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>
This commit is contained in:
2026-09-01 11:26:42 +03:00
co-authored by Claude Sonnet 5
parent ef1dc1b7ac
commit fb8485d638
12 changed files with 282 additions and 6 deletions
+24
View File
@@ -44,6 +44,12 @@ importers:
'@streamclipper/db':
specifier: workspace:*
version: link:../../packages/db
bcryptjs:
specifier: ^2.4.3
version: 2.4.3
jose:
specifier: ^5.9.6
version: 5.10.0
next:
specifier: ^15.1.0
version: 15.5.24(@types/node@22.20.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
@@ -54,6 +60,9 @@ importers:
specifier: ^19.0.0
version: 19.2.8(react@19.2.8)
devDependencies:
'@types/bcryptjs':
specifier: ^2.4.6
version: 2.4.6
'@types/node':
specifier: ^22.10.0
version: 22.20.1
@@ -533,6 +542,9 @@ packages:
'@swc/helpers@0.5.15':
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
'@types/bcryptjs@2.4.6':
resolution: {integrity: sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==}
'@types/body-parser@1.19.6':
resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==}
@@ -584,6 +596,9 @@ packages:
array-flatten@1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
bcryptjs@2.4.3:
resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==}
body-parser@1.20.6:
resolution: {integrity: sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
@@ -834,6 +849,9 @@ packages:
resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
hasBin: true
jose@5.10.0:
resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==}
luxon@3.7.2:
resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==}
engines: {node: '>=12'}
@@ -1404,6 +1422,8 @@ snapshots:
dependencies:
tslib: 2.8.1
'@types/bcryptjs@2.4.6': {}
'@types/body-parser@1.19.6':
dependencies:
'@types/connect': 3.4.38
@@ -1469,6 +1489,8 @@ snapshots:
array-flatten@1.1.1: {}
bcryptjs@2.4.3: {}
body-parser@1.20.6:
dependencies:
bytes: 3.1.2
@@ -1771,6 +1793,8 @@ snapshots:
jiti@2.7.0: {}
jose@5.10.0: {}
luxon@3.7.2: {}
math-intrinsics@1.1.0: {}