feat(auth): Google ile Giriş + landing/login + çalışan çıkış + admin rolü
- server/auth.mjs: ID token'ı oauth2.googleapis.com/tokeninfo ile doğrula (ek bağımlılık yok), HMAC imzalı app token, ADMIN_EMAILS ile admin - POST /api/auth/google, GET /api/auth/google/config, GET /api/auth/me - LoginPage: GIS butonlu landing/giriş; giriş yapılmadan uygulama açılmaz - Header çıkış butonu artık çalışıyor; kullanıcı adı/avatar Google'dan - AI Model Ayarları sekmesi sadece admin'e görünür - Env: GOOGLE_CLIENT_ID + ADMIN_EMAILS (Coolify'dan)
This commit is contained in:
@@ -16,6 +16,7 @@ import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { readDtTenders } from './dt-store.mjs';
|
||||
import { loginWithGoogle, userFromAuthHeader } from './auth.mjs';
|
||||
|
||||
// ilan.gov.tr sunucusu ara sertifikayı (GeoTrust TLS RSA CA G1) göndermiyor;
|
||||
// zinciri tamamlamak için PEM'i yerelden ekliyoruz.
|
||||
@@ -295,9 +296,46 @@ function json(res, code, body) {
|
||||
res.end(JSON.stringify(body));
|
||||
}
|
||||
|
||||
function readBody(req, limit = 100 * 1024) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let data = '';
|
||||
req.on('data', (c) => {
|
||||
data += c;
|
||||
if (data.length > limit) reject(new Error('gövde çok büyük'));
|
||||
});
|
||||
req.on('end', () => {
|
||||
try {
|
||||
resolve(data ? JSON.parse(data) : {});
|
||||
} catch {
|
||||
reject(new Error('geçersiz JSON gövdesi'));
|
||||
}
|
||||
});
|
||||
req.on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
const server = http.createServer(async (req, res) => {
|
||||
const url = new URL(req.url, `http://localhost:${PORT}`);
|
||||
try {
|
||||
// --- Google ile Giriş ---
|
||||
if (url.pathname === '/api/auth/google/config') {
|
||||
return json(res, 200, { clientId: process.env.GOOGLE_CLIENT_ID || null });
|
||||
}
|
||||
if (url.pathname === '/api/auth/google' && req.method === 'POST') {
|
||||
try {
|
||||
const body = await readBody(req);
|
||||
const { token, user } = await loginWithGoogle(body.credential);
|
||||
return json(res, 200, { success: true, token, user });
|
||||
} catch (e) {
|
||||
return json(res, 401, { success: false, error: e.message });
|
||||
}
|
||||
}
|
||||
if (url.pathname === '/api/auth/me') {
|
||||
const user = userFromAuthHeader(req.headers['authorization']);
|
||||
if (!user) return json(res, 401, { success: false, error: 'oturum yok' });
|
||||
return json(res, 200, { success: true, user });
|
||||
}
|
||||
|
||||
if (url.pathname === '/api/tenders') {
|
||||
const force = url.searchParams.get('refresh') === '1';
|
||||
const c = await getTenders(force);
|
||||
|
||||
Reference in New Issue
Block a user