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
+27 -8
View File
@@ -26,9 +26,10 @@ import { AnalyticsDashboard } from './components/tools/AnalyticsDashboard';
import { ApiWebhooks } from './components/tools/ApiWebhooks';
import { PwaSettings } from './components/tools/PwaSettings';
import { AiModelSettings } from './components/tools/AiModelSettings';
import { LoginPage } from './components/LoginPage';
const MainContent = () => {
const { activeTab } = useApp();
const { activeTab, isAdmin } = useApp();
return (
<main className="max-w-[1600px] mx-auto px-4 pb-12">
@@ -58,7 +59,7 @@ const MainContent = () => {
{activeTab === 'analitik_dashboard' && <AnalyticsDashboard />}
{activeTab === 'api_webhooks' && <ApiWebhooks />}
{activeTab === 'pwa_settings' && <PwaSettings />}
{activeTab === 'ai_ayarlari' && <AiModelSettings />}
{activeTab === 'ai_ayarlari' && isAdmin && <AiModelSettings />}
{/* Global Modals */}
<DetailedSearchModal />
@@ -69,15 +70,33 @@ const MainContent = () => {
);
};
const Gate = () => {
const { authReady, isAuthenticated, handleLogin } = useApp();
if (!authReady) {
return (
<div className="min-h-screen bg-[#0f172a] flex items-center justify-center text-white/70">
Yükleniyor…
</div>
);
}
if (!isAuthenticated) {
return <LoginPage onLogin={handleLogin} />;
}
return (
<div className="min-h-screen bg-[#f3f5f8] text-slate-800 flex flex-col font-['Inter',sans-serif]">
<Header />
<LiveStatsBar />
<TopNavigation />
<MainContent />
</div>
);
};
export default function App() {
return (
<AppProvider>
<div className="min-h-screen bg-[#f3f5f8] text-slate-800 flex flex-col font-['Inter',sans-serif]">
<Header />
<LiveStatsBar />
<TopNavigation />
<MainContent />
</div>
<Gate />
</AppProvider>
);
}