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:
2026-08-28 00:43:08 +03:00
parent 1b28ebb603
commit 13f3e9d366
8 changed files with 409 additions and 18 deletions
+25
View File
@@ -2,6 +2,7 @@ import React, { createContext, useContext, useState, useEffect } from 'react';
import { MOCK_TENDERS, MOCK_LIVE_STATS, MOCK_COMPANY_STATS } from '../data/mockTenders';
import { parseWebsiteCapabilitiesDynamically } from '../services/webScraperService';
import { fetchLiveTenders, fetchTenderDetail, mergeUserState } from '../services/tenderApi';
import { restoreSession, clearSession, getStoredUser } from '../services/auth';
const AppContext = createContext();
@@ -34,6 +35,24 @@ export const AppProvider = ({ children }) => {
const [liveDataError, setLiveDataError] = useState(null);
const [liveDataSource, setLiveDataSource] = useState(null);
// --- Kimlik doğrulama (Google ile Giriş) ---
const [authUser, setAuthUser] = useState(() => getStoredUser());
const [authReady, setAuthReady] = useState(false);
const isAuthenticated = Boolean(authUser);
const isAdmin = Boolean(authUser?.isAdmin);
useEffect(() => {
restoreSession()
.then((u) => setAuthUser(u))
.finally(() => setAuthReady(true));
}, []);
const handleLogin = (user) => setAuthUser(user);
const handleLogout = () => {
clearSession();
setAuthUser(null);
};
// Canlı ihale verisini (ilan.gov.tr) çeker; kullanıcının kanban/takip durumunu korur.
const refreshLiveEKAPData = async ({ refresh = true } = {}) => {
setIsRefreshingLive(true);
@@ -338,6 +357,12 @@ export const AppProvider = ({ children }) => {
refreshLiveEKAPData,
liveDataError,
liveDataSource,
authUser,
authReady,
isAuthenticated,
isAdmin,
handleLogin,
handleLogout,
liveStats,
searchQuery,
setSearchQuery,