Commit Graph

93 Commits

Author SHA1 Message Date
t8y2 d353d4673f feat(redis): add configurable key namespace separator 2026-06-10 17:46:48 +08:00
t8y2 22928c51cc chore(release): bump version to 0.5.31 2026-06-10 13:01:57 +08:00
t8y2 bfec556e9b feat(readonly): add read-only mode for all database connections
- Add read_only field to ConnectionConfig with backward-compatible serde defaults
- SQL classifier with first-keyword + embedded keyword defense layers
- PRAGMA white-listing for safe read-only operations
- Guard all write entry points: SQL, Mongo, Redis, etcd, MCP Bridge
- 16 unit tests covering edge cases (CTE, case insensitivity, string masking)
- 7-language i18n support
- Fast-fail at command/route level before pool creation

Closes #889
2026-06-10 11:58:18 +08:00
runstone a440415e86 feat(readonly): add read-only mode for all database connections
## Background
Add a read-only toggle for database connections that blocks all write
operations (INSERT, UPDATE, DELETE, DROP, etc.) when enabled, allowing
only read queries (SELECT, SHOW, EXPLAIN, etc.). Closes #889.

## Changes

### Data Model
- Added `read_only: bool` field to ConnectionConfig (Rust struct, TS
  interfaces, and ConnectionConfigData deserialization layer)
- Used `#[serde(default, skip_serializing_if = "is_false")]` for
  backward/forward compatibility with existing configs

### Frontend UI
- Added "Read Only" checkbox in connection dialog
- 7-language i18n support (en/es/it/pt-BR/zh-CN/zh-TW)

### SQL Classification (query_execution_sql.rs)
- Added `is_write_sql()` with two-layer defense:
  - Layer 1: First-keyword check (must start with known read keyword)
  - Layer 2: Embedded dangerous keyword detection (catches CTE-wrapped
    writes like `WITH ... AS (DELETE FROM ...)`)
  - `FROM` keyword supported as DuckDB SELECT-less syntax indicator
- Added `check_read_only()` returning descriptive error with connection name
- Added 16 unit tests covering: pure reads/writes, CTE, case insensitivity,
  string literal masking, comment stripping, stored procedure calls, edge cases

### SQL Execution Guards (query.rs / transfer.rs)
- Added `check_read_only_for_connection()` and `_multi()` helper functions
  with lazy name clone (only allocates when read_only is true)
- 6 interception points: `do_execute`, MySQL batch, SQL Server batch,
  DuckDB batch, transaction execution, transfer execution

### Non-SQL Write Guards — Tauri Commands
- Added `ensure_connection_writable()` helper (connection.rs)
- Mongo: 6 write entry points (insert/update/delete, single + batch)
- Redis: 15 write entry points (SET, DEL, HSET, HDEL, LPUSH, LSET, LREM,
  SADD, SREM, ZADD, ZREM, EXPIRE, FLUSHDB, delete_keys, execute_command)
  - execute_command uses RedisCommandSafety classification to allow
    safe read commands through raw command interface
- etcd: 2 write entry points (put, delete)
- sql_file: SQL file execution guarded
- MCP Bridge: 4 write entry points (Insert/Update/Delete/SQL query)

### Non-SQL Write Guards — Web API
- Local `ensure_writable()` helper in each route module
- Redis: 12 write endpoints including classified execute_command
- Mongo: 6 write endpoints
- etcd: 2 write endpoints
- sql_file, table_import, transfer: early rejection

### Test Updates
- Updated ConnectionConfig construction in 7 test files with
  `read_only: false` initialization

## Defense-in-Depth
- Layer 1: Command/Route-level early rejection (saves resources)
- Layer 2: Core SQL classifier (`is_write_sql` — first keyword + embedded scan)
- Layer 3: Core execution-time interception (do_execute/transfer/transaction)
2026-06-10 10:58:52 +08:00
t8y2 d0bf6c3b53 feat(redis): persist command history across sessions (#933) 2026-06-10 04:34:45 +08:00
DengQingNian 35692bc53b
feat(redis): add TTL, structured entries, Stream and JSON support to create key dialog (#947)
Thanks @DengQingNian! Great feature — TTL, structured entries, Stream, and JSON support for Redis key creation.
2026-06-09 22:08:08 +08:00
二丫讲梵 41758e6bb1
feat(connection): 增加可见数据库选择功能 (#944)
感谢 @eryajf 的贡献!此功能允许用户在创建或编辑连接时选择可见的数据库,支持多种数据库类型。
2026-06-09 20:56:39 +08:00
t8y2 2a7b26baad fix: add missing idle_timeout_secs in ConnectionConfig constructors and fix clippy warnings 2026-06-09 11:56:39 +08:00
t8y2 47ee9c6d58 chore: release 0.5.30 2026-06-08 02:26:25 +08:00
Quinlevi 897e6998fd
feat(dameng): full DM8 database support
Adds Dameng DM8 explain/autotrace support and user-management SQL support, with backend autotrace safety checks and escaped CREATE USER SQL.
2026-06-08 02:07:00 +08:00
t8y2 e6062b2b07 feat(etcd): add agent-backed etcd support 2026-06-08 00:58:42 +08:00
t8y2 7bd8d29a79 feat(sidebar): lazily load database object groups 2026-06-07 23:44:40 +08:00
t8y2 a473f4ff8f chore: switch license to Apache-2.0 2026-06-07 17:34:59 +08:00
Caisin 8c0fe3a6e7
Expose forwarded database port for local testing (#803)
Database connection context menus now show a copy action when the connection has enabled transport layers. The action starts or reuses the ordered transport chain, copies the final local forwarding port, and keeps runtime config cached so later disconnect cleanup can stop the created tunnel.

Constraint: Local testing sometimes needs external tools to connect through DBX's generated proxy/tunnel endpoint

Rejected: Copy full host:port endpoint | user specifically asked for the port and existing tunnel host is always localhost

Rejected: Require an active pool before copying | local test workflows may need the tunnel before opening the DBX connection

Confidence: high

Scope-risk: moderate

Tested: pnpm test -- packages/app-tests/connectionTransport.test.ts (ran full app-tests: 862 passed)

Tested: pnpm typecheck

Tested: pnpm exec oxlint --vue-plugin apps/desktop/src/components/sidebar/TreeItem.vue apps/desktop/src/lib/connectionTransport.ts apps/desktop/src/lib/api.ts apps/desktop/src/lib/tauri.ts apps/desktop/src/lib/http.ts

Tested: cargo check -p dbx-core -p dbx-web

Tested: cargo check -p dbx

Tested: cargo fmt --check --all

Co-authored-by: caisin <caisin@caisins-Mac-mini.local>
2026-06-07 01:00:34 +08:00
Caisin e9ee982843
Preserve ordered SSH and proxy connection layers (#802)
* Preserve ordered SSH and proxy connection layers

Replace separate SSH/proxy connection fields with ordered transport_layers while keeping legacy migration and secret fallback paths intact. The UI now edits SSH tunnel/proxy layers in configured order without a global SSH enable gate.

Constraint: Existing saved SSH tunnels, proxy settings, and secret-store keys must continue to load through migration.
Rejected: Folding proxy fields into SshTunnelConfig | mixes proxy semantics into an SSH-specific structure.
Confidence: high
Scope-risk: moderate
Directive: Keep SSH/proxy structs provider-specific; put cross-layer chaining in transport_layer_tunnel orchestration.
Tested: git diff --check; cargo fmt --check; cargo check --workspace; cargo test -p dbx-core --lib; vue-tsc --noEmit --project apps/desktop/tsconfig.json; tsc -p packages/node-core/tsconfig.json --noEmit; oxlint --vue-plugin apps/desktop/src; tsx --tsconfig apps/desktop/tsconfig.json --test packages/app-tests/*.test.ts; tsx --test packages/node-core/tests/*.test.ts
Not-tested: Live external SSH/proxy/database endpoint integration.

* Keep ordered transport changes CI-format clean

Constraint: CI pnpm check failed only on oxfmt formatting for two desktop TypeScript files
Confidence: high
Scope-risk: narrow
Directive: Keep generated/editor config changes out of this PR fix commit
Tested: PATH="/Volumes/data/code/rust/dbx/node_modules/.bin:/Users/hekx/.codex/tmp/arg0/codex-arg0nuL34n:/Users/hekx/.cargo/bin:/Users/hekx/.local/bin:/opt/homebrew/opt/llvm/bin:/opt/homebrew/opt/libpq/bin:/Volumes/data/Users/hekx/.opencode/bin:/Users/hekx/.bun/bin:/Volumes/data/sdks/flutter/bin:/Volumes/data/Users/hekx/.cargo/bin:/Users/hekx/.local/bin:/opt/homebrew/opt/llvm/bin:/opt/homebrew/opt/libpq/bin:/Volumes/data/Users/hekx/.opencode/bin:/Users/hekx/.bun/bin:/Volumes/data/Users/hekx/Library/pnpm:/Volumes/data/sdks/flutter/bin:/Volumes/data/Users/hekx/.cargo/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/pkg/env/global/bin:/opt/X11/bin:/Library/Apple/usr/bin:/Applications/Wireshark.app/Contents/MacOS:/usr/local/go/bin:/opt/homebrew/bin:/opt/podman/bin:/Applications/Ghostty.app/Contents/MacOS" rtk node scripts/run-check.mjs
Not-tested: GitHub Actions rerun not observed locally

* Keep Rust checks warning-clean

Constraint: cargo clippy --workspace --all-targets --all-features -- -D warnings failed across core, web, and tauri crates
Rejected: Broad workspace-level clippy suppression | kept allows local to long-argument command/API boundaries
Confidence: high
Scope-risk: moderate
Directive: Preserve src-tauri/tauri.conf.json as an unrelated local change outside this commit
Tested: rtk cargo clippy --workspace --all-targets --all-features -- -D warnings
Not-tested: Full GitHub Actions rerun not observed locally

* Reuse existing proxy tunnels on retry

Proxy tunnel startup now mirrors SSH tunnel behavior by returning the existing local port for an active connection id instead of replacing the managed handle. A second map check aborts a just-spawned duplicate handle if a concurrent retry won the race before insertion, preventing orphaned listeners while keeping the change narrow.

Constraint: Reviewer requested proxy tunnel behavior align with SSH local-port reuse

Rejected: Always overwrite and abort the previous handle | less consistent with SSH behavior and churns listeners during retries

Confidence: high

Scope-risk: narrow

Tested: cargo fmt --check --all

Tested: cargo test -p dbx-core db::proxy_tunnel::tests::start_tunnel_reuses_existing_local_port

Tested: cargo clippy -p dbx-core --all-targets -- -D warnings

---------

Co-authored-by: hekx <hekx@momandeMac-mini.local>
Co-authored-by: caisin <caisin@caisins-Mac-mini.local>
2026-06-06 23:22:29 +08:00
t8y2 2b5300722f feat: optimize tab result lifecycle caching 2026-06-06 20:30:35 +08:00
t8y2 7acd1625a9 fix(web): support encrypted config import over HTTP 2026-06-06 13:12:28 +08:00
t8y2 a799958328 feat: add driver runtime manager 2026-06-04 23:20:15 +08:00
t8y2 8d51a5779b fix: cancel DuckDB queries via duckdb_interrupt instead of only cancelling async future
Previously, cancelling a DuckDB query only dropped the tokio CancellationToken,
but the actual DuckDB C call continued running in spawn_blocking. This caused
the UI to show "正在停止..." until timeout silently expired.

Now, RunningQueries stores per-execution interrupt callbacks. For DuckDB and
ExternalTabular branches, an InterruptHandle is registered on query start so
cancel() calls duckdb_interrupt() at the C level, truly stopping the query.
2026-06-04 17:20:13 +08:00
t8y2 293600d9b4 fix: pass connection query timeout to execute_batch so ALTER respects configured timeout
Previously execute_batch always used the hardcoded 30s default timeout,
ignoring the user's query_timeout_secs connection setting. This caused
long-running ALTER TABLE statements on large tables to time out even
when the user configured a longer timeout or disabled it entirely.
2026-06-04 13:54:20 +08:00
t8y2 0194adfa4c chore(release): bump version to v0.5.29 2026-06-04 02:10:39 +08:00
t8y2 388873213f fix(export): stream full table exports correctly 2026-06-04 01:10:23 +08:00
t8y2 493b4dafdd fix(web): stream offline agent zip uploads in docker 2026-06-03 16:24:39 +08:00
t8y2 7fb53ee0b4 fix(drivers): skip blocked driver updates 2026-06-03 14:39:46 +08:00
t8y2 3f4521f550 chore(release): bump version to 0.5.28 2026-06-03 12:55:04 +08:00
t8y2 9adf2b8d00 fix(dameng): deduplicate column metadata 2026-06-03 12:38:36 +08:00
t8y2 cc74fabad7 feat(completion): suggest database routines 2026-06-03 11:27:31 +08:00
DengQingNian bea3b45fd8
perf(export): 优化导出ui体验和性能
* docs(getting-started): set brew upgrade to use official homebrew cask

* fix(mysql): make admin show handling dialect aware

* fix(data-compare): create missing target tables during sync

* feat(sql): suggest join conditions from foreign keys

* fix(sidebar): use filtered order for range selection

* fix(tabs): close connection tabs on disconnect

* fix(sqlserver): execute cte queries without wrapping

* fix(opengauss): open table structure editor

* perf(export): 优化导出ui体验和性能

* perf(export): 优化导出ui体验和性能

* fix(export): normalize status casing and fix web route issues

- Add missing table export web routes (POST /export/table, SSE progress, cancel)
- Fix tauri table export Promise to wait for terminal events
- Change cancel to return Ok(()) so it doesn't get overwritten as Error
- Unify ExportStatus to PascalCase across all frontend components
- Fix http.ts table export POST body wrapping
- Fix duplicate pub mod in dbx-web routes

* fix(export): return export file for browser download in web mode

Write table export output to temp dir, register a download endpoint,
and trigger browser download from the frontend when export completes.

* fix(export): avoid table export progress races

---------

Co-authored-by: Francesco Lucarelli <francesco06lucarelli@gmail.com>
Co-authored-by: t8y2 <1156263951@qq.com>
Co-authored-by: dqn <someonegdeng@qq.com>
2026-06-03 10:39:11 +08:00
t8y2 b10e7cb1cf fix(data-compare): create missing target tables during sync 2026-06-02 17:46:30 +08:00
t8y2 6fc8364157 chore(release): bump version to 0.5.27 2026-06-02 04:58:29 +08:00
t8y2 ac7a5b7576 feat(desktop): drop tree schema objects 2026-06-02 00:33:58 +08:00
t8y2 46c05b811f feat(connection): support multi-hop ssh tunnels 2026-06-01 14:48:33 +08:00
t8y2 738696f38e chore(release): v0.5.26 2026-06-01 00:50:24 +08:00
t8y2 da6074caaa refactor(sql-file): share import executor 2026-05-31 11:58:15 +08:00
t8y2 f5cc81f761 perf(sql-file): optimize import batching 2026-05-31 11:14:14 +08:00
t8y2 74b4acba19 chore(release): bump version to 0.5.25 2026-05-30 13:23:42 +08:00
t8y2 13d52514d9 feat(connection): close database scoped pools 2026-05-30 12:34:14 +08:00
t8y2 41e23cccc3 feat(desktop): improve sql file preview 2026-05-30 11:22:17 +08:00
t8y2 b6ac1f177b refactor(agent): consolidate driver architecture 2026-05-29 23:29:27 +08:00
t8y2 4fd8d895f4 fix: cargo fmt formatting in dbx-web main.rs 2026-05-29 15:46:32 +08:00
t8y2 6c0db6f517 feat: add "Copy as SQL ALTER" to DataGrid column header context menu
Right-click a column header in the data grid to copy the ALTER TABLE
statement for that column, making it easy to replicate column definitions
across databases. Supports all major dialects (MySQL, Postgres, SQL Server,
Oracle, ClickHouse, SQLite, DuckDB, H2).

Closes #516
2026-05-29 15:09:10 +08:00
t8y2 521195c801 chore(release): v0.5.24 2026-05-29 02:03:18 +08:00
徐文彬 5ea146e08e fix(mongodb): guard aggregate execution paths 2026-05-28 21:29:08 +08:00
徐文彬 c56bcb8e2d feat(mongodb): 支持聚合查询、批量写入和 MCP 集成
- 桌面端:解析 db.<集合>.aggregate([...]) shell 语法,新增 mongoAggregateDocuments
  接口(Tauri + HTTP);mongo 入口统一补 ensureConnected;ObjectId(...) 自动
  转换为 {"\$oid":"..."} 扩展 JSON 表示。
- dbx-core:新增 aggregate_documents、insert/update/delete_documents bulk
  操作;扩展 JSON 解析识别 \$oid;schema list_tables_core 补 MongoDB/Elasticsearch
  分支返回 COLLECTION/INDEX。
- dbx-web / Tauri 命令 / MCP bridge:注册 4 个新 mongo 路由
  (aggregate/insert/update/delete documents);MCP bridge 新增 mongo HTTP 入口
  和 lazy 连接复用。
- node-core (MCP 后端):mongodb 走专属 executeQuery / listTables /
  describeTable;read-only 默认 + DBX_MCP_ALLOW_WRITES /
  DBX_MCP_ALLOW_DANGEROUS_SQL 两级开关;aggregate 含 \$out/\$merge 走同样开关;
  describeTable 抽样 20 条文档推断字段类型,_id 自动标记主键。
- mcp-server:mongodb 跳过 SQL safety evaluator(mongo shell 与 SQL 语法
  不兼容),改由 backend 做命令级 gating;附注释。
- AiAssistant 同时 emit replaceSql + executeSql 让编辑器和结果保持一致;
  App.vue ensureQueryTab 在无上下文时回退到连接默认库;aiMessageRender
  识别 mongodb / mongo 代码块。
- Review 修复:合并两份重复的 evaluateMongo*Safety 实现(同时修复 web-backend
  用字符串比较导致空 filter 检查可被空格绕过的 bug);ObjectId 正则兼容
  单/双引号;mongo_ops 错误文案 "MCP" 改为 "bulk";补 aggregate 解析测试用例。

测试:pnpm test 911 通过;vue-tsc 通过;cargo check -p dbx-core 通过。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 21:25:43 +08:00
t8y2 e725dd0379 fix(connection): keep config after disconnect 2026-05-28 18:48:53 +08:00
t8y2 486d9bb3a6 fix(connection): move query timeout into per-connection settings 2026-05-28 18:18:45 +08:00
t8y2 d35aeaa08c fix: continue transfer after table failure 2026-05-28 16:11:29 +08:00
t8y2 f40745fbd1 chore: bump version to 0.5.23 2026-05-28 01:32:54 +08:00
t8y2 0ffc0dbca8 fix(ci): add missing redis cluster test config field 2026-05-28 01:20:24 +08:00
t8y2 c952c65483 feat: upgrade data compare sync planning 2026-05-28 01:05:15 +08:00