feat: 修复菜单路由+角色权限展示+操作审计+WebSSH终端审计

1. 菜单路由修复: /roles /users /logs-audit /terminal-audit 等系统管理子菜单
   通过 useLocation 同步 URL 路径到 Tab 选中状态

2. WebSSH错误提示优化: Go error → 友好中文提示
   i/o timeout → 连接超时(防火墙或网络不通)
   connection refused → 端口未开放/SSH服务未启动
   cannot find session key → 密码或密钥认证失败
   连接提示增加端口号显示

3. 角色权限展示: 31项权限种子数据 (资产管理/云资源/K8s/发布/监控/AIOps/系统管理)
   4个角色权限分配: admin(31) ops(27) developer(16) viewer(3)
   前端角色卡片显示权限名称而非原始code

4. 操作审计修复: 删除/创建/更新服务器均记录审计日志
   批量删除逐条记录审计

5. WebSSH终端审计 (JumpServer模式):
   - 新增 TerminalSession 模型记录会话(用户/服务器/时间/状态)
   - webshell.go 录制终端输出(1MB上限)
   - 终端审计页面: 会话列表+状态筛选+批量删除
   - 操作回放: xterm.js 重放录制的终端输出
   - WS连接增加JWT鉴权+token传递
This commit is contained in:
attacker committed 2026-06-17 08:55:09 +08:00
1 parent 4797059be2
commit bdc7a507c0
17 files changed
+985 -34

No files matched your search

@@ -10,6 +10,7 @@ import { FitAddon } from 'xterm-addon-fit';
import 'xterm/css/xterm.css';
import { Maximize2, Minimize2, X } from 'lucide-react';
import { cn } from '@/lib/utils';
import { useUserStore } from '@/store';
interface TerminalDialogProps {
open: boolean;
@@ -61,7 +62,8 @@ export function TerminalDialog({
// WebSocket 连接
const proto = location.protocol === 'https:' ? 'wss' : 'ws';
const wsUrl = `${proto}://${location.host}/ws/terminal?id=${serverId}&cols=80&rows=24`;
const token = useUserStore.getState().token || '';
const wsUrl = `${proto}://${location.host}/ws/terminal?id=${serverId}&cols=80&rows=24&token=${encodeURIComponent(token)}`;
const ws = new WebSocket(wsUrl);
wsRef.current = ws;
+3 -1
View File
@@ -30,6 +30,7 @@ import { Terminal as XTerm } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import 'xterm/css/xterm.css';
import { serverApi } from '@/services/api';
import { useUserStore } from '@/store';
interface TerminalSession {
id: string;
@@ -116,7 +117,8 @@ export function WebShell() {
term.loadAddon(fit);
const proto = typeof location !== 'undefined' && location.protocol === 'https:' ? 'wss' : 'ws';
const wsUrl = `${proto}://${location.host}/ws/terminal?id=${server.id}&cols=${cols}&rows=${rows}`;
const token = useUserStore.getState().token || '';
const wsUrl = `${proto}://${location.host}/ws/terminal?id=${server.id}&cols=${cols}&rows=${rows}&token=${encodeURIComponent(token)}`;
const ws = new WebSocket(wsUrl);
// 终端输入 -> WebSocket