feat(backend): realtime event system, admin API ve metrics altyapısı
- socket.ts: ContentRealtimeEvent, CacheRealtimeEvent, MetricsRealtimeEvent
tipleri eklendi; emitContentEvent / emitCacheEvent / emitMetricsEvent
fonksiyonları ile tüm istemcilere broadcast desteği getirildi.
emitJobCompleted imzası GetInfoResponse + DataSource ile güçlendirildi.
- auth.middleware.ts: require() tabanlı env erişimi static import'a
dönüştürüldü; admin-only endpointler için adminOnlyMiddleware eklendi
(X-API-Key !== API_KEY_ADMIN → 403).
- cache.service.ts: set / delete / clearAll işlemlerinden sonra
emitCacheEvent çağrısı eklenerek cache mutasyonları anlık yayınlanıyor.
- content.service.ts: create / update / delete sonrasında emitContentEvent
çağrısı eklenerek DB yazımları Socket.IO üzerinden duyuruluyor.
- job.service.ts: async ve sync akışa MetricsService entegrasyonu eklendi;
cache hit/miss ve kaynak (cache/database/netflix) sayaçları her işlemde
artırılıyor.
- types/index.ts: AdminOverviewResponse ve AdminActionResponse tipleri
merkezi olarak tanımlandı.
- admin.service.ts (yeni): getOverview, clearCache, warmupCacheFromDatabase,
retryFailedJobs, refreshStaleContent operasyonları implement edildi.
Redis pipeline ile TTL/boyut analizi ve DB metrikleri paralel toplanıyor.
- metrics.service.ts (yeni): Redis hash tabanlı cache hit/miss ve kaynak
sayaçları; her artışta MetricsRealtimeEvent yayınlanıyor.
- api.routes.ts: Admin endpointleri eklendi:
GET /api/admin/overview
POST /api/admin/cache/clear
POST /api/admin/cache/warmup
POST /api/admin/jobs/retry-failed
POST /api/admin/content/refresh-stale
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { getValidApiKeys } from '../config/env.js';
|
||||
import { env, getValidApiKeys } from '../config/env.js';
|
||||
import logger from '../utils/logger.js';
|
||||
import type { ApiResponse } from '../types/index.js';
|
||||
|
||||
@@ -61,8 +61,6 @@ export function authMiddleware(
|
||||
* Optional: Identify which client made the request
|
||||
*/
|
||||
export function identifyClient(apiKey: string): string {
|
||||
const { env } = require('../config/env.js');
|
||||
|
||||
if (apiKey === env.API_KEY_WEB) return 'web';
|
||||
if (apiKey === env.API_KEY_MOBILE) return 'mobile';
|
||||
if (apiKey === env.API_KEY_ADMIN) return 'admin';
|
||||
@@ -70,4 +68,46 @@ export function identifyClient(apiKey: string): string {
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* Strict admin API key guard.
|
||||
* Use for admin-only operational endpoints.
|
||||
*/
|
||||
export function adminOnlyMiddleware(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): void {
|
||||
const apiKey = req.headers['x-api-key'] as string | undefined;
|
||||
|
||||
if (!apiKey) {
|
||||
res.status(401).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'MISSING_API_KEY',
|
||||
message: 'API key is required. Include X-API-Key header.',
|
||||
},
|
||||
} satisfies ApiResponse<never>);
|
||||
return;
|
||||
}
|
||||
|
||||
if (apiKey !== env.API_KEY_ADMIN) {
|
||||
logger.warn('Admin endpoint access denied', {
|
||||
ip: req.ip,
|
||||
path: req.path,
|
||||
keyPrefix: apiKey.substring(0, 8) + '...',
|
||||
});
|
||||
|
||||
res.status(403).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: 'ADMIN_API_KEY_REQUIRED',
|
||||
message: 'Admin API key required.',
|
||||
},
|
||||
} satisfies ApiResponse<never>);
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
export default authMiddleware;
|
||||
|
||||
Reference in New Issue
Block a user