Phase G2-1~G2-6: Code Execution Worker - Docker sandbox deployment, backend API (code_exec_admin.py), frontend CodeExecTab, security hardening (read-only FS, non-root, capability dropping, RLIMIT_AS)

This commit is contained in:
qyyfw committed 2026-07-06 14:10:41 +08:00
1 parent 909c013e2d
commit 9b3e15ace6
9 files changed
+1709 -447

No files matched your search

+128 -145
View File
@@ -1,145 +1,128 @@
import React, { useState, useEffect, Suspense, lazy } from 'react';
import { Routes, Route, Navigate } from 'react-router-dom';
import type { User } from '@/types';
import { AuthContext, AuthContextType } from '@/contexts/AuthContext';
// Layouts - eagerly loaded (needed immediately)
import FrontLayout from '@/components/layout/FrontLayout';
import AdminLayout from '@/components/layout/AdminLayout';
// Front Pages - lazy loaded
const LandingPage = lazy(() => import('@/pages/front/LandingPage'));
const LoginPage = lazy(() => import('@/pages/front/LoginPage'));
const ChatPage = lazy(() => import('@/pages/front/ChatPage'));
const ChannelPage = lazy(() => import('@/pages/front/ChannelPage'));
const KnowledgePage = lazy(() => import('@/pages/front/KnowledgePage'));
const MarketPage = lazy(() => import('@/pages/front/MarketPage'));
const TokenDashboardPage = lazy(() => import('@/pages/front/TokenDashboardPage'));
const PricingPage = lazy(() => import('@/pages/front/PricingPage'));
const ProfilePage = lazy(() => import('@/pages/front/ProfilePage'));
const NotificationPage = lazy(() => import('@/pages/front/NotificationPage'));
const AssetsPage = lazy(() => import('@/pages/front/AssetsPage'));
const NovelPreviewPage = lazy(() => import('@/pages/front/NovelPreviewPage'));
const EvolutionDashboard = lazy(() => import('@/pages/front/EvolutionDashboard'));
// Admin Pages - lazy loaded
const AdminDashboard = lazy(() => import('@/pages/admin/Dashboard'));
const AdminUsers = lazy(() => import('@/pages/admin/Users'));
const AdminModels = lazy(() => import('@/pages/admin/Models'));
const AdminSiteSettings = lazy(() => import('@/pages/admin/SiteSettings'));
const AdminPayment = lazy(() => import('@/pages/admin/Payment'));
const AdminServices = lazy(() => import('@/pages/admin/Services'));
const AdminMembership = lazy(() => import('@/pages/admin/Membership'));
const AdminAds = lazy(() => import('@/pages/admin/Ads'));
const AdminMarket = lazy(() => import('@/pages/admin/Market'));
const AdminLogs = lazy(() => import('@/pages/admin/Logs'));
const AdminSkills = lazy(() => import('@/pages/admin/Skills'));
const AdminAgents = lazy(() => import('@/pages/admin/Agents'));
const AdminKnowledge = lazy(() => import('@/pages/admin/Knowledge'));
// Phase C2: New orphan page routes
const AdminApps = lazy(() => import('@/pages/admin/Apps'));
const AdminAutomation = lazy(() => import('@/pages/admin/Automation'));
const AdminDeveloper = lazy(() => import('@/pages/admin/Developer'));
const AdminDeveloperTools = lazy(() => import("@/pages/admin/DeveloperTools"));
const AdminMcp = lazy(() => import('@/pages/admin/Mcp'));
const AdminStorage = lazy(() => import('@/pages/admin/Storage'));
const AdminAssetCenter = lazy(() => import('@/pages/admin/AssetCenter'));
const AdminWorkflow = lazy(() => import('@/pages/admin/Workflow'));
// Loading fallback
const PageLoading: React.FC = () => (
<div style={{
display: 'flex', alignItems: 'center', justifyContent: 'center',
padding: '60px 20px', color: 'var(--color-text-tertiary)', fontSize: '14px',
gap: '12px',
}}>
<div className="audit-spinner" />
<span>加载中...</span>
</div>
);
const App: React.FC = () => {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const token = localStorage.getItem('aiflow_token');
const cachedUser = localStorage.getItem('aiflow_user');
if (token && cachedUser) {
try { setUser(JSON.parse(cachedUser)); } catch {
localStorage.removeItem('aiflow_token');
localStorage.removeItem('aiflow_user');
}
}
setLoading(false);
}, []);
const login = (u: User) => { setUser(u); localStorage.setItem('aiflow_user', JSON.stringify(u)); };
const logout = () => { setUser(null); localStorage.removeItem('aiflow_token'); localStorage.removeItem('aiflow_user'); };
const isAdmin = user?.role === 'admin';
if (loading) return (
<div style={{
display: 'flex', alignItems: 'center', justifyContent: 'center',
height: '100vh', color: '#6C63FF', flexDirection: 'column', gap: 16,
}}>
<div className="audit-spinner" style={{ width: 40, height: 40 }} />
<span style={{ fontSize: 14, color: '#9CA3AF' }}>加载中...</span>
</div>
);
return (
<AuthContext.Provider value={{ user, login, logout, isAdmin }}>
<Suspense fallback={<PageLoading />}>
<Routes>
<Route path="/login" element={user ? (isAdmin ? <Navigate to="/admin" /> : <Navigate to="/chat" />) : <LoginPage />} />
<Route path="/" element={user ? (isAdmin ? <Navigate to="/admin" /> : <Navigate to="/chat" />) : <LandingPage />} />
<Route path="/" element={<FrontLayout />}>
<Route path="chat" element={<ChatPage />} />
<Route path="chat/:id" element={<ChatPage />} />
<Route path="channels" element={<ChannelPage />} />
<Route path="knowledge" element={<KnowledgePage />} />
<Route path="market" element={<MarketPage />} />
<Route path="token" element={<TokenDashboardPage />} />
<Route path="pricing" element={<PricingPage />} />
<Route path="profile" element={<ProfilePage />} />
<Route path="notifications" element={<NotificationPage />} />
<Route path="assets" element={<AssetsPage />} />
<Route path="assets/novel/:id" element={<NovelPreviewPage />} />
<Route path="evolution" element={<EvolutionDashboard />} />
</Route>
<Route path="/admin" element={<AdminLayout />}>
<Route index element={<AdminDashboard />} />
{/* 用户体系 */}
<Route path="users" element={<AdminUsers />} />
<Route path="membership" element={<AdminMembership />} />
{/* AI能力 */}
<Route path="models" element={<AdminModels />} />
<Route path="agents" element={<AdminAgents />} />
<Route path="workflow" element={<AdminWorkflow />} />
<Route path="skills" element={<AdminSkills />} />
<Route path="knowledge" element={<AdminKnowledge />} />
<Route path="mcp" element={<AdminMcp />} />
{/* 业务运营 */}
<Route path="market" element={<AdminMarket />} />
<Route path="services" element={<AdminServices />} />
<Route path="payment" element={<AdminPayment />} />
<Route path="apps" element={<AdminApps />} />
<Route path="ads" element={<AdminAds />} />
{/* 系统设置 */}
<Route path="settings" element={<AdminSiteSettings />} />
<Route path="logs" element={<AdminLogs />} />
<Route path="storage" element={<AdminStorage />} />
<Route path="asset-center" element={<AdminAssetCenter />} />
<Route path="automation" element={<AdminAutomation />} />
<Route path="developer" element={<AdminDeveloper />} />
<Route path="developer-tools" element={<AdminDeveloperTools />} />
</Route>
<Route path="*" element={<Navigate to="/" />} />
</Routes>
</Suspense>
</AuthContext.Provider>
);
};
export default App;
import React, { useState, useEffect } from 'react';
import { Routes, Route, Navigate } from 'react-router-dom';
import type { User } from '@/types';
import { AuthContext, AuthContextType } from '@/contexts/AuthContext';
import { authAPI } from '@/api';
// Layouts
import FrontLayout from '@/components/layout/FrontLayout';
import AdminLayout from '@/components/layout/AdminLayout';
// Front Pages
import LandingPage from '@/pages/front/LandingPage';
import LoginPage from '@/pages/front/LoginPage';
import ChatPage from '@/pages/front/ChatPage';
import ChannelPage from '@/pages/front/ChannelPage';
import KnowledgePage from '@/pages/front/KnowledgePage';
import MarketPage from '@/pages/front/MarketPage';
import TokenDashboardPage from '@/pages/front/TokenDashboardPage';
import PricingPage from '@/pages/front/PricingPage';
import ProfilePage from '@/pages/front/ProfilePage';
import NotificationPage from '@/pages/front/NotificationPage';
import AssetsPage from '@/pages/front/AssetsPage';
import NovelPreviewPage from '@/pages/front/NovelPreviewPage';
import EvolutionDashboard from '@/pages/front/EvolutionDashboard';
// Admin Pages
import AdminDashboard from '@/pages/admin/Dashboard';
import AdminUsers from '@/pages/admin/Users';
import AdminModels from '@/pages/admin/Models';
import AdminSiteSettings from '@/pages/admin/SiteSettings';
import AdminPayment from '@/pages/admin/Payment';
import AdminServices from '@/pages/admin/Services';
import AdminMembership from '@/pages/admin/Membership';
import AdminAds from '@/pages/admin/Ads';
import AdminMarket from '@/pages/admin/Market';
import AdminLogs from '@/pages/admin/Logs';
import AdminSkills from '@/pages/admin/Skills'
import AdminAgents from '@/pages/admin/Agents';
import AdminCodeExec from '@/pages/admin/CodeExec';;
const App: React.FC = () => {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
// 初始化:从localStorage恢复登录状态
useEffect(() => {
const token = localStorage.getItem('aiflow_token');
const cachedUser = localStorage.getItem('aiflow_user');
if (token && cachedUser) {
try {
setUser(JSON.parse(cachedUser));
} catch {
localStorage.removeItem('aiflow_token');
localStorage.removeItem('aiflow_user');
}
}
setLoading(false);
}, []);
const login = (u: User) => {
setUser(u);
localStorage.setItem('aiflow_user', JSON.stringify(u));
};
const logout = () => {
setUser(null);
localStorage.removeItem('aiflow_token');
localStorage.removeItem('aiflow_user');
};
const isAdmin = user?.role === 'admin';
if (loading) {
return <div className="loading-screen">加载中...</div>;
}
return (
<AuthContext.Provider value={{ user, login, logout, isAdmin }}>
<Routes>
{/* Login */}
<Route path="/login" element={
user ? (isAdmin ? <Navigate to="/admin" /> : <Navigate to="/chat" />) : <LoginPage />
} />
{/* Root - Landing for guests, redirect for authenticated users */}
<Route path="/" element={
user ? (isAdmin ? <Navigate to="/admin" /> : <Navigate to="/chat" />) : <LandingPage />
} />
{/* Front Routes (authenticated only) */}
<Route path="/" element={<FrontLayout />}>
<Route path="chat" element={<ChatPage />} />
<Route path="chat/:id" element={<ChatPage />} />
<Route path="channels" element={<ChannelPage />} />
<Route path="knowledge" element={<KnowledgePage />} />
<Route path="market" element={<MarketPage />} />
<Route path="token" element={<TokenDashboardPage />} />
<Route path="pricing" element={<PricingPage />} />
<Route path="profile" element={<ProfilePage />} />
<Route path="notifications" element={<NotificationPage />} />
<Route path="assets" element={<AssetsPage />} />
<Route path="assets/novel/:id" element={<NovelPreviewPage />} />
<Route path="evolution" element={<EvolutionDashboard />} />
</Route>
{/* Admin Routes */}
<Route path="/admin" element={<AdminLayout />}>
<Route index element={<AdminDashboard />} />
<Route path="users" element={<AdminUsers />} />
<Route path="models" element={<AdminModels />} />
<Route path="settings" element={<AdminSiteSettings />} />
<Route path="payment" element={<AdminPayment />} />
<Route path="services" element={<AdminServices />} />
<Route path="membership" element={<AdminMembership />} />
<Route path="ads" element={<AdminAds />} />
<Route path="market" element={<AdminMarket />} />
<Route path="logs" element={<AdminLogs />} />
<Route path="skills" element={<AdminSkills />} />
<Route path="agents" element={<AdminAgents />} />
<Route path="code-exec" element={<AdminCodeExec />} />
</Route>
<Route path="*" element={<Navigate to="/" />} />
</Routes>
</AuthContext.Provider>
);
};
export default App;