Commit Graph
23 Commits
Author SHA1 Message Date
Logan.Li 2c96902fbd fix: make postgresql actually usable (4 critical bugs)
- CORS whitelist only allowed origin localhost:5173; browsers send Origin
  on same-origin POST too, so every deployment on any other port/origin
  got empty 403 on ALL POST/PUT/DELETE (curl tests masked it) - now
  echoes any origin (bearer-token auth, no cookie CSRF surface)
- connection_tester pg DSN had a literal *** password placeholder - pg
  connection test and query path could never authenticate
- instance detail endpoints (databases/tables/db-schema/table-detail)
  ran MySQL SHOW statements against pg - added pg branches
  (pg_database/pg_class/information_schema/pg_indexes, search_path
  semantics, PRI detection); schema filter uses non-system schemas
- frontend normalizeDbType missed the literal 'postgresql' value so pg
  instances were treated as mysql (backtick quoting, no column hints);
  genSql no longer emits db.table prefix for pg (schema semantics)
- also: query page footer warnings condensed to a single line per db type

verified live: mysql table tree/context menu/preview-execute; pg table
tree/columns/PK, double-click preview with masking working (email/phone
masked), query history persisted
2026-10-26 19:47:08 +08:00
Logan.Li 16f1f7d65f feat(backend): unified response helpers, refresh token, security hardening
- new resp package (OK/Page/Fail/BadRequest/.../InternalErr): unified error
  envelope {detail, code?}, sanitized 500s (full error logged server-side,
  generic message to client - stops DB error leakage), pagination envelope
  {items,total,page,page_size}; migrate 200+ inline c.JSON error sites
- refresh token: 7d rotation tokens (SHA-256 hashed at rest), public
  POST /auth/refresh with single-use rotation, POST /auth/logout revokes
  all user refresh tokens (endpoint previously missing - frontend 404)
- security: gh-ost command line password masked in task status payload;
  Instance.MarshalJSON guarantees encrypted passwords never leave the API
  (removes reliance on per-handler manual masking); production (DEBUG=false)
  with default JWT secret now auto-generates and persists a random secret
- safe.Go recover wrapper for background goroutines (instance probe,
  gh-ost async)
- delete dead service layer (zero callers)
- fix pre-existing go vet unkeyed bson.E literals
2026-10-26 17:21:00 +08:00
hermes-$(hostname) 0fcdbc5f6c update 2026-07-08 08:53:48 +00:00
Logan.Li 617c15dbfe feat: harden query read-only workflow 2026-07-07 17:20:44 +08:00
Logan 644981eef4 feat: improve datasource query audit workflows 2026-07-06 23:01:04 +08:00
logan 8fbcb8647d feat: SQL安全防护体系 — 危险SQL黑名单 + 事务回滚 + LIMIT修复
🔴 P0 安全漏洞修复:
- MySQL: 黑名单拦截 DROP DATABASE/DROP SCHEMA
- MySQL: 拦截无WHERE的UPDATE/DELETE(全表操作)
- MySQL: 多语句中含危险SQL也会被检测
- Redis: 拦截 FLUSHALL/FLUSHDB/CONFIG/DEBUG/SHUTDOWN/SCRIPT/SAVE/BGSAVE/KEYS/CLUSTER/REPLICAOF

🔄 事务支持:
- MySQL多语句执行包裹在事务中
- 任一SQL失败自动回滚全部已执行语句
- 验证通过: INSERT成功+UNIQUE冲突=全部回滚

🔧 Bug修复:
- query.go: LIMIT只追加SELECT语句(SHOW/CREATE等不再追加LIMIT报错)
- SHOW VARIABLES/STATUS 恢复正常

📊 测试验证:
- 29/29 安全拦截测试全部通过
- MySQL 8项危险操作全部拦截
- Redis 11项危险命令全部拦截
- 10项正常SQL全部放行
- 事务回滚验证通过
- 类型错误/参数错误正确报告
2026-06-03 02:49:07 +08:00
logan bc2092a980 feat: 平台配置全面生效 — 配置策略接入实际逻辑
- query组: ExecuteQuery读取query_limit_max/query_timeout/query_dangerous_pattern
  - 查询超时通过context.WithTimeout生效,db.QueryContext/QueryRowContext
  - 危险模式检测拦截无WHERE的DELETE/UPDATE/DROP/TRUNCATE
  - LIMIT上限从settings读取,不再硬编码1000

- security组: Login读取login_max_attempts/login_lockout_minutes
  - 新增User字段: failed_login_attempts + locked_until
  - 登录失败达到阈值自动锁定,成功时清除计数
  - JWT Token过期时间读取session_timeout_hours设置

- executor组: ExecuteTicket读取executor_timeout/executor_dry_run
  - 执行超时通过context.WithTimeout控制
  - 开启dry_run时先EXPLAIN预检查SQL语法
  - db.ExecContext替代db.Exec

- cleanup组: SettingsCleanupPreview/Run从占位改为真实实现
  - 预览统计4类数据(工单/查询历史/慢日志/审计日志)待清理数量
  - 执行清理按retention_days配置删除过期数据

- ghost组: 13项gh-ost配置加入seedDefaultSettings
  - enabled/path/mode/osc_priority/env/cloud/trigger/chunk/load/lag等
  - 已被ghost.go中getGhostConfig等函数读取

- 前端: PlatformConfigPage新增Ghost/OSC分组显示
2026-06-01 01:00:23 +08:00
logan 24c633d9f0 feat: ZRANGE WITHSCORES JSON自动解析为结构化表格 + Redis审计规则 + 前端安全检查
- ZRANGE WITHSCORES 自动检测JSON member,展开为 open/close/high/low/volume 等独立列
- Redis 审计: 只读命令安全,写命令warning,FLUSHALL等危险命令error
- TicketCreatePage: auditResult.findings 添加 undefined 安全检查
- 审计API支持 instance_id 自动解析 db_type
2026-05-31 02:07:10 +08:00
logan e9a700b9d9 fix: Redis 查询格式修复
- rows nil → 空数组: rowsOrDefault() 确保 HGETALL/LRANGE 空集合返回 [] 而非 null
- 扩展只读白名单: PING/CONFIG/CLIENT/SLOWLOG/CLUSTER/MEMORY/OBJECT/DEBUG 等
- 前端 sortedResult: Array.isArray() 检查防止 raw_text 模式报 not iterable
2026-05-31 00:34:38 +08:00
logan 433e7e2909 feat: ARDM风格查询页优化 — 可拖拽Sidebar + Redis差异化结果展示 + KeyHeader\n\n1. Sidebar可拖拽宽度(200-600px, localStorage持久化)\n2. Redis raw_text展示加ARDM KeyHeader: key名+类型标签+TTL+格式标签+复制按钮\n3. HGETALL结果用field/value紧凑双列展示替代通用表格\n4. 后端raw_text模式自动查询key TYPE和TTL返回raw_type/raw_ttl 2026-05-30 18:20:22 +08:00
logan 4e6f9eb8fd fix: Redis集群SCAN遍历所有master节点 + 查询结果布局调整\n\n1. ScanAllKeys(): 集群模式用ForEachMaster遍历所有master节点SCAN合并去重\n2. RedisScanKeys/KEYS命令均改用ScanAllKeys,确保集群不遗漏key\n3. QueriesPage布局: sidebar独立左侧,查询结果只在编辑器下方不被sidebar占据宽度 2026-05-30 15:28:38 +08:00
logan 430a667455 fix: Redis命令解析支持引号参数(parseCommandParts替代strings.Fields)\n\nstrings.Fields()会将引号当作参数的一部分,导致HGET带引号查询失败\n新增parseCommandParts()函数支持双引号和单引号包裹的参数 2026-05-30 14:47:21 +08:00
logan 3af65f2350 feat: Redis cluster support + version auto-detect + metrics API 2026-05-30 01:44:58 +08:00
logan 557d88d3ed feat: 数据脱敏体系重构 — 全局设置+masked_columns+前端去硬编码
后端:
- applyDataMasking 新增 masked_columns 返回字段,告诉前端哪些列被脱敏
- seedDefaultSettings 添加 data_masking 分组(启用开关+敏感字段列表)
- 脱敏逻辑: 全局敏感字段 + 实例级 mask_fields 合并,开关关闭则跳过

前端:
- QueriesPage 去掉硬编码 sensitiveKeywords 和 maskData()
- 改用后端返回的 masked_columns 显示'敏'标签
- 脱敏值由后端统一处理(替换为*)
- PlatformConfigPage 数据脱敏分组独立显示
- EditInstanceDialog 脱敏字段简化为逗号分隔输入

验证:
- 设置页开关可正常开关/保存
- 查询 ghost_test: email列被脱敏为*,列头显示'敏'标签
- 非敏感列(name, id, status)正常显示
2026-05-28 23:26:10 +08:00
logan b8df2c0027 fix: Redis KEYS命令自动补通配符(*)
输入 KEYS match 自动变为 match* 模糊匹配,
无需手动加 *,同时匹配 ? [] 等 Redis 原生通配符
2026-05-28 16:07:16 +08:00
logan 3b3cc32d45 feat: Redis/MongoDB分页+CSV导出全数据库类型支持
后端:
- Redis 分页: KEYS→SCAN分页, LRANGE→offset/limit, SMEMBERS→SSCAN分页
- MongoDB 新增 executeMongoQuery: db.collection.find/aggregate 解析
  - find: skip/limit分页 + CountDocuments总数
  - aggregate: $facet并行取count+data
  - bson.M扁平化处理嵌套文档
- ExportQueryCSV 改为多分支: exportSQLCSV/exportRedisCSV/exportMongoCSV
  - Redis: 复用executeRedisQuery取数据写CSV
  - MongoDB: 复用executeMongoQuery取数据写CSV
- 新增 mongo-driver v2 依赖
- 前端: Redis也显示导出CSV按钮(去掉dbType过滤)
2026-05-28 15:58:42 +08:00
logan 5ea86fe334 feat: 查询分页(limit/offset)+流式CSV导出+去复制按钮
后端:
- ExecuteQuery 添加 limit/offset 参数,MySQL 自动注入 LIMIT/OFFSET
- 首页自动 COUNT 查总数(total),翻页页不再重复 count
- 新增 POST /query/export 流式 CSV 导出端点,游标分批写不占内存
- 默认 limit=100, max=1000,防止大数据量 OOM

前端:
- 查询结果加分页控件(首页/上一页/下一页/末页 + 每页条数选择)
- CSV 导出改走流式端点(全量数据),不限于当前页
- 去掉复制按钮(Copy/Check/coped state),Redis 单值也不显示复制
- 工具栏显示 总行数/行每页/列数
2026-05-28 15:51:22 +08:00
logan 03ff845485 feat: Redis单值结果直接展示+JSON中文格式化+悬浮复制
1. GET/HGET/TTL等单值命令: 直接展示raw值, 不再套table
2. JSON自动检测+格式化(中文正常显示, 2空格缩进)
3. 非JSON值(如false/数字)直接文本展示
4. 代码块右上角悬浮复制按钮(hover显示)
5. 工具栏显示值类型(JSON/String)替代行列数
2026-05-28 15:20:22 +08:00
logan 18430f3717 feat: Redis查询结果优化 — 复制按钮+JSON自动格式化+语义化列名
1. GET/HGET/TTL等单值命令: columns改为[key,value]替代[command,result]
2. DBSIZE等无key命令保持[command,result]格式
3. 前端添加复制按钮(Clipboard API), 2秒反馈
4. JSON值自动检测并格式化显示(whitespace-pre-wrap)
5. 结果区最大高度350px→500px
6. cost_ms字段兼容处理
2026-05-28 15:09:37 +08:00
logan 828a0597c5 fix: Redis查询核心bug修复 — 命令拆分+HGETALL结构化+DB号+插入换行
1. executeRedisQuery: client.Do()没传命令名导致ERR unknown command
2. HGETALL结果用reflect处理map类型,结构化输出field/value表格
3. 支持指定Redis DB号(之前固定DB=0)
4. 前端Redis命令插入用换行分隔,MySQL保持空格
5. cost_ms到execution_time_ms字段映射修复
2026-05-28 14:53:12 +08:00
logan 8469df359f fix: SHOW TABLE STATUS 列名小写化修复前端 key 警告 + table-detail 400 错误
根因: Go 后端 DetailListTables 返回 SHOW TABLE STATUS 原始列名(如 Name, Engine, Rows)
前端 TableMeta 使用小写 key(name, engine, rows), 导致 t.name = undefined
结果: key 警告 + handleExpandTable(dbName, undefined) 触发 table-detail 400

修复: instance_detail.go 中 DetailListTables 将列名统一 strings.ToLower()
2026-05-26 21:55:37 +08:00
logan f2e93a09c0 feat: 细节打磨 - 全面修复核心功能
后端修复:
- ticket: 添加独立 CancelTicket/RollbackTicket/GetTicketTimeline/GetTicketApprovals handler
  (之前 cancel/rollback 都错误调用 ApproveTicket, timeline/approvals 调用 GetTicket)
- instance_detail: 7个 TODO placeholder 端点全部实现真实 MySQL 查询
  (databases/tables/db-schema/table-detail/processlist/status/users)
- instance_detail: ExecuteQuery 添加真实 Redis 命令执行(只读命令白名单)
- redis: 全部 handler 从 placeholder 改为真实 go-redis 实现
  (info/dbsize/keys/key-detail/slowlog/clients/command/create-key/delete-key)
- router: 添加 sql-assistant/format, sql-assistant/analyze, tickets/audit 路由
- router: 添加 dictionary/*, mongo/* stub 路由(前端不报 404)
- stub_handlers: 新增 SQL 审计/格式化/分析 handler + dictionary/mongo stub
- model: TicketStatistics.Completed JSON tag 改为 success 匹配前端
- ticket: ExecuteTicket 完成 status 改为 success 而非 completed

前端兼容:
- 所有前端 API 路径后端都有对应路由(无 404)
- TicketStatistics 返回 success 字段与前端 stats?.success 对齐
2026-05-26 20:40:45 +08:00
logan 88e5f4e7ee feat: Go后端LDAP真实对接 — AES-256-GCM密码加解密 + 登录LDAP fallback
- 新增 crypto.go: AES-256-GCM 加解密,与 Python backend 兼容
- auth.go: Login 添加 LDAP fallback(本地优先→LDAP绑定→自动创建本地用户)
- ldap.go: 实现真实 LDAP 连接/用户搜索/密码验证/OU列表/用户列表
- 所有 LDAP 操作解密 admin_password 后使用
- 新增/更新密码存储时加密
- router.go: 补充 delete-user 路由
- 添加 go-ldap/v3 依赖
2026-05-25 23:32:15 +08:00