2025-11-23 20:04:00 +03:00
2025-11-23 20:04:00 +03:00
2025-11-23 20:04:00 +03:00
2025-11-23 20:04:00 +03:00
2025-11-23 20:04:00 +03:00
2025-11-23 20:04:00 +03:00
2025-11-23 20:04:00 +03:00
2025-11-23 20:04:00 +03:00
2025-11-23 20:04:00 +03:00
2025-11-23 20:04:00 +03:00

Comment API iskeleti

Node.js + Express + Socket.io + Supabase + Redis tabanlı login/register API iskeleti. Güvenlik odaklı, host allowlist, rate limit, admin rol kilidi ve Redis oturum yönetimi içerir. Docker-compose ile Redis + API birlikte ayağa kalkar.

Dizın yapısı

src/
  app.js                // Express app
  server.js             // HTTP + Socket.io bootstrap
  config/
    env.js              // .env yükleme ve parse
    supabase.js         // Supabase client
    redis.js            // Redis client
  middleware/
    authRequired.js
    adminRequired.js
    rateLimit.js
    hostOnly.js
    errorHandler.js
  routes/
    auth.routes.js
    health.routes.js
  controllers/
    auth.controller.js
  services/
    auth.service.js
    session.service.js
    adminLock.service.js
  utils/
    crypto.js           // bcrypt + JWT yardımcıları
    response.js         // standart JSON çıktı

Çalıştırma

  1. Bağımlılıklar:
    npm install
    

    Not: metascraper bağımlılığı özel git repodan gelir (git+https://gitea.wisecolt-panda.net/wisecolt/metascraper.git). Erişim için uygun token/SSH anahtarı olan bir ortamda npm install çalıştırın. Docker build için base imaja git eklenmiştir; özel repo erişimi için gerekirse GIT_SSH_COMMAND veya GITHUB_TOKEN benzeri auth ekleyin.

  2. Ortam değişkenleri: .env.example dosyasını .env olarak kopyalayıp doldurun.
  3. Geliştirme:
    npm run dev
    
  4. Üretim:
    npm start
    

Docker

Yerelde (dev, hot-reload) Redis ile birlikte çalıştırmak için:

docker compose -f docker-compose.dev.yml up --build
# durdurmak için
docker compose -f docker-compose.dev.yml down
  • API: http://localhost:${PORT}
  • Redis: redis://localhost:6379 (container içinde redis://redis:6379)

Prod modunda Docker

  1. .env içinde NODE_ENV=production ve mümkünse COOKIE_SECURE=true, TRUST_PROXY=loopback (veya proxy sayısı) olarak ayarlayın.
  2. Çalıştırın:
    docker compose up --build -d
    
  3. Durdurun:
    docker compose down
    

.env örneği

NODE_ENV=development
PORT=3000
TRUST_PROXY=loopback

SUPABASE_URL=https://YOUR-SUPABASE-PROJECT.supabase.co
SUPABASE_SERVICE_ROLE_KEY=YOUR_SUPABASE_SERVICE_ROLE_KEY

REDIS_URL=redis://redis:6379

JWT_SECRET=supersecretjwt
JWT_EXPIRES_IN=7d
COOKIE_NAME=sid
COOKIE_SECURE=false

ADMIN_EMAIL=admin@example.com
ADMIN_USERNAME=admin
ADMIN_NAME=Admin User
ADMIN_ROLE_LOCK=true

HOST_ONLY_ALLOWLIST=127.0.0.1,::1

RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX=100

LOGIN_RATE_LIMIT_WINDOW_MS=60000
LOGIN_RATE_LIMIT_MAX=5

Endpointler

  • GET /health{ ok: true, time }
  • POST /auth/register — body { email, name, username, password }
  • POST /auth/login — body { emailOrUsername, password }
  • POST /auth/logout — cookie tabanlı JWT siler
  • GET /auth/me — aktif kullanıcıyı döndürür
  • POST /auth/refresh — yeni JWT üretir (iskelet)
  • POST /meta/scrape — body { url }, destekli domainler: netflix.com, primevideo.com (yalnızca role: user)
    • Başarılı sorgu Supabase media_data tablosuna kaydedilir: media_id, media_name, year, type(movie/tv), thumbnail_url, info, genre, media_provider (netflix/primevideo)

Postman örnekleri

Register

POST {{baseUrl}}/auth/register
Content-Type: application/json
Body:
{
  "email": "user@example.com",
  "name": "Test User",
  "username": "testuser",
  "password": "password123"
}

200:

{
  "user": {
    "id": "...",
    "email": "user@example.com",
    "name": "Test User",
    "username": "testuser",
    "roleEffective": "user"
  }
}

Login

POST {{baseUrl}}/auth/login
Content-Type: application/json
Body:
{
  "emailOrUsername": "testuser",
  "password": "password123"
}

200:

{
  "user": {
    "id": "...",
    "email": "user@example.com",
    "name": "Test User",
    "username": "testuser",
    "roleEffective": "user"
  }
}

JWT otomatik olarak Cookie: sid=<token> olarak set edilir.

Me

GET {{baseUrl}}/auth/me
Cookie: sid=<token>

200:

{
  "user": {
    "id": "...",
    "email": "...",
    "username": "...",
    "roleEffective": "user"
  }
}

Logout

POST {{baseUrl}}/auth/logout
Cookie: sid=<token>

200:

{ "message": "Çıkış yapıldı" }

Meta scrape (Netflix/Prime)

POST {{baseUrl}}/meta/scrape
Content-Type: application/json
Cookie: sid=<token>   # roleEffective=user
Body:
{ "url": "https://www.netflix.com/tr/title/81507921" }

Prime örneği:

{ "url": "https://www.primevideo.com/-/tr/detail/0NHIN3TGAI9L7VZ45RS52RHUPL/ref=share_ios_movie" }

200 (örnek):

{
  "provider": "netflix",
  "type": "movie",
  "media": {
    "url": "https://www.netflix.com/title/82123114",
    "id": "82123114",
    "name": "ONE SHOT with Ed Sheeran",
    "year": "2025",
    "seasons": null,
    "thumbnail": "...",
    "info": "...",
    "genre": "..."
  },
  "saved": {
    "media_id": "82123114",
    "media_name": "ONE SHOT with Ed Sheeran",
    "year": "2025",
    "type": "movie",
    "thumbnail_url": "...",
    "info": "...",
    "genre": "...",
    "media_provider": "netflix",
    "created_at": "..."
  }
}

Hata çıktıları tek tip:

{
  "error": { "code": "ERROR_CODE", "message": "Açıklama", "details": [...] }
}

Supabase şeması (SQL)

create extension if not exists "pgcrypto";

create table if not exists public.users (
  id uuid primary key default gen_random_uuid(),
  email text unique not null,
  name text not null,
  username text unique not null,
  password_hash text not null,
  role text not null default 'user' check (role in ('user','admin')),
  created_at timestamp with time zone default now()
);

create table if not exists public.media_data (
  media_id varchar,
  media_name text,
  year numeric,
  type text,
  thumbnail_url varchar,
  info text,
  genre text,
  media_provider text,
  created_at timestamp with time zone default now()
);

Admin rol kilidi: Sadece .env içindeki ADMIN_EMAIL ve ADMIN_USERNAME ile birebir eşleşen kullanıcı API tarafından admin kabul edilir. Supabase üzerinde rol elle değiştirilse bile etkisizdir.

Güvenlik notları

  • hostOnly middleware ve CORS sadece allowlistteki host/ip erişimine izin verir.
  • Global rate limit + login özel rate limit aktiftir.
  • JWT httpOnly cookie olarak set edilir; Redis içinde session:{jti} anahtarıyla oturum metadata tutulur.

Socket.io

  • Handshake sırasında cookiedeki JWT doğrulanır, Redis oturum kontrol edilir.
  • Başarılı bağlantıda welcome eventi döner.
  • Örnek ping/pong:
    • Client: socket.emit('ping')
    • Server cevabı: pong içinde zaman damgası.

Docker notları

  • docker-compose.yml içinde api servisi redis servisine bağımlıdır.
  • Geliştirme için kod klasörü container içine mount edilerek canlı yenileme (npm run dev) sağlanır.
  • Sağlık kontrolü: container içinde GET /health çağrısı ile yapılır.

Yapılandırılabilir noktalar

  • Rate limit penceresi ve max değerleri .env ile ayarlanır.
  • HOST_ONLY_ALLOWLIST ile izin verilen host/ip listesi yönetilir.
  • ADMIN_ROLE_LOCK kapatılmadıkça tek admin .envdeki kullanıcıdır.

TODO / Genişletme fikirleri

  • Refresh token için ayrı bir anahtar ve whitelist mekanizması.
  • Audit logları (morgan loglarını dosyaya yazma).
  • Supabase RPC veya policylerle ek güvenlik.
  • Testler (Jest/Supertest) ve CI pipelineı.
Description
No description provided
Readme 44 KiB
Languages
JavaScript 98.3%
Dockerfile 1.7%