first commit
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
# alterdb
|
||||
|
||||
> 以 SQLite 為底層存儲格式的自定義數據庫引擎,附帶開箱即用的 Web 管理介面。
|
||||
|
||||
**狀態:早期開發中** — axum HTTP API 骨架、Askama 渲染的首頁與 SQLite 存儲層(rusqlite + 連接池)已就緒,數據模型 Account(帳戶)與 Database(外部數據庫連接,mysql / postgres)的 CRUD 與 REST API 已可用;Web 介面的登入 / 會話(Cookie + 進程內存會話存儲)、變更密碼與數據庫連接管理頁已完成,連接詳情頁可實際連線目標庫(測試連接狀態、瀏覽數據表),數據表管理頁可檢視欄位結構並新增 / 刪除欄位,數據管理頁可分頁瀏覽並編輯(以主鍵定位修改資料列)表內資料,管理介面其餘部分與查詢引擎仍在開發中。
|
||||
|
||||
## 專案簡介
|
||||
|
||||
alterdb 是一個使用 Rust 編寫的自定義數據庫引擎。它不是又一個 SQLite 管理工具,而是:
|
||||
|
||||
- **自定義查詢引擎**:對外提供自己的查詢介面與數據模型,查詢的解析、規劃與執行均由 alterdb 自行實作;
|
||||
- **SQLite 作為底層存儲**:數據最終落在單一 SQLite 檔案中,直接享受其成熟可靠的持久化與事務能力,而無需從零重造存儲層;
|
||||
- **Web 管理介面**:以本地伺服器方式運行,打開瀏覽器即可瀏覽數據、執行查詢、管理表結構。
|
||||
|
||||
## 核心特性(規劃中)
|
||||
|
||||
- 自定義查詢引擎:查詢的解析與執行由本項目實作,不直接透傳 SQL
|
||||
- SQLite 存儲後端:單檔案持久化,支援事務
|
||||
- Web 管理介面:
|
||||
- 數據庫 / 表 / 結構瀏覽
|
||||
- 線上執行查詢,結果以表格呈現
|
||||
- 數據新增、編輯、刪除
|
||||
- 單一可執行檔部署:編譯為單一 binary,內嵌前端資源,無外部運行時依賴
|
||||
|
||||
## 架構規劃
|
||||
|
||||
```text
|
||||
┌─────────────┐ HTTP ┌───────────────────┐
|
||||
│ 瀏覽器 │ ◄────────────► │ HTTP API 伺服器 │
|
||||
│ (Web UI) │ │ (Rust) │
|
||||
└─────────────┘ └─────────┬─────────┘
|
||||
│
|
||||
┌─────────▼─────────┐
|
||||
│ 查詢引擎 │
|
||||
│ 解析 / 規劃 / 執行 │
|
||||
└─────────┬─────────┘
|
||||
│
|
||||
┌─────────▼─────────┐
|
||||
│ 存儲層 │
|
||||
│ (SQLite 檔案) │
|
||||
└───────────────────┘
|
||||
```
|
||||
|
||||
技術選型:
|
||||
|
||||
| 項目 | 選擇 | 備註 |
|
||||
| --- | --- | --- |
|
||||
| 語言 | Rust(edition 2024) | 需 Rust 1.85+ |
|
||||
| Web 框架 | [axum](https://github.com/tokio-rs/axum) 0.8 + tokio | REST API;中間件透過 tower-http |
|
||||
| 模板引擎 | [Askama](https://github.com/askama-rs/askama) 0.16 | 編譯期模板,HTML 內嵌於執行檔 |
|
||||
| 存儲 | SQLite([rusqlite](https://github.com/rusqlite/rusqlite) bundled) | deadpool-sqlite 連接池;WAL 模式 |
|
||||
| 外部庫連線 | [mysql_async](https://github.com/blackbeam/mysql_async) / [tokio-postgres](https://github.com/sfackler/rust-postgres) | 連接測試與數據表瀏覽;暫未啟用 TLS |
|
||||
| 密碼雜湊 | [argon2](https://github.com/RustCrypto/password-hashes) 0.5 | 帳戶密碼以 Argon2id + 隨機鹽雜湊存儲,永不落明文 |
|
||||
|
||||
## 快速開始
|
||||
|
||||
環境需求:[Rust](https://www.rust-lang.org/) 1.85 或以上版本(本項目使用 edition 2024)。
|
||||
|
||||
```bash
|
||||
# 編譯並運行
|
||||
cargo run
|
||||
|
||||
# 伺服器啟動後:
|
||||
# - 管理介面首頁:http://127.0.0.1:8080/(未登入會被導向 /login)
|
||||
# - 數據庫連接管理頁:http://127.0.0.1:8080/databases(需登入)
|
||||
# - 變更密碼頁:http://127.0.0.1:8080/password(需登入)
|
||||
# - 登入頁:http://127.0.0.1:8080/login(默認帳號 admin / admin)
|
||||
# - 健康檢查 API:http://127.0.0.1:8080/api/health
|
||||
# - 帳戶 API:http://127.0.0.1:8080/api/accounts
|
||||
# - 數據庫連接 API:http://127.0.0.1:8080/api/databases
|
||||
```
|
||||
|
||||
資料庫檔案默認為工作目錄下的 `alterdb.db`,可透過環境變數 `ALTERDB_DB_PATH` 指定其他路徑。
|
||||
|
||||
SQLite 數據檔(`*.db` 等)已被 `.gitignore` 排除,不會被誤提交到版本庫。
|
||||
|
||||
## 登入與會話
|
||||
|
||||
Web 介面頁面(目前為首頁 `/`)需登入後才能訪問,未登入的請求會被重定向到 `/login`:
|
||||
|
||||
| 方法 | 路徑 | 說明 |
|
||||
| --- | --- | --- |
|
||||
| GET | `/login` | 登入頁(已登入者直接回到首頁);帶 `?changed=1` 時顯示密碼變更成功提示 |
|
||||
| POST | `/login` | 提交用戶名 / 密碼;成功建立會話並下發 Cookie |
|
||||
| POST | `/logout` | 銷毀會話並清除 Cookie |
|
||||
| GET | `/password` | 變更密碼頁(需登入) |
|
||||
| POST | `/password` | 校驗原密碼後更新密碼;成功即銷毀該帳戶全部會話,導向 `/login?changed=1` |
|
||||
|
||||
實作要點:
|
||||
|
||||
- 密碼以 Argon2id 校驗;帳號不存在時仍執行一次雜湊運算,避免以回應時間差列舉用戶名;已停用(`is_active = false`)的帳戶無法登入
|
||||
- 會話保存在**進程內存**,以 256 位隨機 token 為鑰匙,透過 `HttpOnly` + `SameSite=Lax` Cookie 傳遞,有效期 24 小時;伺服器重啟後會話失效(重新登入即可)
|
||||
- 變更密碼需驗證原密碼;新密碼長度 8–128 字符、兩次輸入需一致且不得與原密碼相同;成功後以新 Argon2 雜湊覆寫,該帳戶**全部會話(含當前)即刻失效**,需以新密碼重新登入
|
||||
- `/api/*` 端點**暫不要求會話**,後續將統一接入認證
|
||||
|
||||
## Web 管理介面
|
||||
|
||||
登入後的頁面共用側邊導航欄(`_shell.html` 應用外殼):左側為品牌、主導航(首頁 / 數據庫,當前頁以 `aria-current="page"` 高亮)與底部的登入者資訊、變更密碼入口及登出;窄屏(≤ 48rem)自動折疊為頂欄。登入頁與 404 頁保持無側欄的獨立版式。頁面外殼由 Askama 渲染,數據操作由內嵌 vanilla JS 調用 `/api/*` 完成(無任何外部前端依賴):
|
||||
|
||||
全站支援深淺色主題:預設跟隨系統偏好(`color-scheme: light dark`),點擊側邊欄底部(獨立版式頁為頁首右側)的「深色 / 淺色模式」按鈕可手動固定,選擇保存在 `localStorage`(鍵 `theme`),並由 `<head>` 內的同步內聯腳本在首幀繪製前重新套用,避免刷新閃爍。配色完全由 `color-scheme` 驅動(`currentColor` 混色與 `light-dark()`),無任何主題相關的服務端狀態。
|
||||
|
||||
| 路徑 | 說明 |
|
||||
| --- | --- |
|
||||
| `/` | 首頁:服務資訊與各管理入口 |
|
||||
| `/databases` | 數據庫連接列表(名稱連到詳情頁;含刪除) |
|
||||
| `/databases/new` | 新增連接(獨立表單頁) |
|
||||
| `/databases/{id}` | 連接詳情頁:服務端渲染連接資訊,頁面載入即自動測試連接(狀態徽章 + 伺服器版本 + 延遲)並列出目標庫當前 schema 的數據表(名稱連到表管理頁);可「重新測試」 |
|
||||
| `/databases/{id}/edit` | 編輯連接(獨立表單頁,服務端預填現值;連接不存在返回 404) |
|
||||
| `/databases/{id}/tables/{table}` | 數據表管理頁:欄位結構(名稱 / 類型 / 可空 / 默認值,支援新增與刪除欄位),由內嵌 JS 即時連線目標庫取得;頁面不請求表內資料 |
|
||||
| `/databases/{id}/tables/{table}/data` | 數據管理頁:表內資料分頁瀏覽(每頁 25–200 列、顯示總列數)與編輯資料列(以主鍵定位,逐欄輸入、可空欄位可設 NULL),由內嵌 JS 即時連線目標庫取得 |
|
||||
| `/password` | 變更密碼(表單:原密碼 / 新密碼 / 確認新密碼;成功後全部會話失效並導向登入頁) |
|
||||
|
||||
`/databases` 相關頁面要點:
|
||||
|
||||
- 埠留空按類型自動補默認(MySQL 3306 / PostgreSQL 5432)
|
||||
- 編輯頁由服務端預填現值,但密碼**永不回填**(API 與頁面皆不輸出密碼);編輯時密碼欄留空表示**保留原密碼**(對應 PUT 語義:`password` 鍵缺省=保留、空字串=清空、有值=覆寫)
|
||||
- 表單提交由 JS 調用 `/api/databases`,成功後跳回列表頁;操作錯誤(驗證失敗、名稱衝突等)以頁面錯誤條展示 API 返回的錯誤訊息
|
||||
- 詳情頁(`/databases/{id}`)載入時自動並行發起連接測試與數據表查詢,狀態以徽章呈現(已連接 / 無法連接 / 測試中),數據表類型映射為「表 / 視圖」
|
||||
- 表管理頁(`/databases/{id}/tables/{table}`)載入時僅載入欄位結構,不請求表內資料;工具列「數據管理」連到對應的數據管理頁
|
||||
- 數據管理頁(`/databases/{id}/tables/{table}/data`)載入時載入第一頁資料;支援換頁、調整每頁列數與手動刷新,NULL 儲存格以斜體 `NULL` 呈現,過長內容截斷並以懸浮提示顯示全文;頁面對視圖(VIEW)同樣適用
|
||||
- 數據管理頁可**編輯資料列**:有主鍵的表每列附「編輯」按鈕,對話框逐欄輸入(可空欄位附 NULL 勾選),只送出有變更的欄位,以編輯前的主鍵原值定位資料列;沒有主鍵的表(含視圖)僅能瀏覽並顯示提示;目標列已被刪除或主鍵已變更時返回衝突錯誤並保留表單內容
|
||||
- 表管理頁的欄位結構區可**新增欄位**(內嵌表單:名稱 / 類型(含常用建議)/ 可空(默認允許)/ 默認值)與**刪除欄位**(紅色按鈕,彈出確認對話框後才執行);結構變更成功後自動刷新欄位結構
|
||||
- 所有動態內容經 `textContent` 寫入,不以字串拼接 HTML
|
||||
|
||||
## 帳戶 API
|
||||
|
||||
管理介面用戶帳戶的 CRUD 端點(後續將由自定義查詢引擎統一驅動):
|
||||
|
||||
| 方法 | 路徑 | 說明 |
|
||||
| --- | --- | --- |
|
||||
| GET | `/api/accounts` | 列出所有帳戶 |
|
||||
| POST | `/api/accounts` | 建立帳戶;`username`、`email` 必填且全表唯一 |
|
||||
| GET | `/api/accounts/{id}` | 取得單一帳戶,不存在時返回 404 |
|
||||
| PUT | `/api/accounts/{id}` | 覆寫帳戶可編輯欄位(`updated_at` 自動刷新) |
|
||||
| DELETE | `/api/accounts/{id}` | 刪除帳戶 |
|
||||
|
||||
輸入會先被正規化(去除首尾空白、`display_name` 缺省時同 `username`、`is_active` 缺省為啟用);驗證失敗返回 400,唯一欄位衝突返回 409。
|
||||
|
||||
### 默認管理員帳號
|
||||
|
||||
資料庫初始化時會自動建立默認管理員帳號(僅在不存在時建立,重啟不會覆蓋日後的變更):
|
||||
|
||||
- 用戶名:`admin`
|
||||
- 密碼:`admin`
|
||||
|
||||
密碼以 Argon2 雜湊存儲,`password_hash` 欄位永不透過 API 序列化輸出;既有舊版資料庫啟動時會自動遷移(補上 `password_hash` 欄位)。**初始密碼即帳號名,建議儘早變更。**
|
||||
|
||||
```bash
|
||||
# 建立帳戶
|
||||
curl -X POST http://127.0.0.1:8080/api/accounts \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"username": "alice", "email": "alice@example.com", "display_name": "Alice"}'
|
||||
|
||||
# 列出所有帳戶
|
||||
curl http://127.0.0.1:8080/api/accounts
|
||||
```
|
||||
|
||||
## 數據庫連接 API
|
||||
|
||||
管理外部數據庫連接(MySQL / PostgreSQL)的 CRUD 端點,以及對目標庫的**實際連線**操作(測試連接、列出數據表、檢視欄位結構、分頁瀏覽與修改資料,由 `mysql_async` / `tokio-postgres` 驅動):
|
||||
|
||||
| 方法 | 路徑 | 說明 |
|
||||
| --- | --- | --- |
|
||||
| GET | `/api/databases` | 列出所有連接 |
|
||||
| POST | `/api/databases` | 建立連接;`name` 必填且全表唯一 |
|
||||
| GET | `/api/databases/{id}` | 取得單一連接,不存在時返回 404 |
|
||||
| PUT | `/api/databases/{id}` | 覆寫連接可編輯欄位(`updated_at` 自動刷新) |
|
||||
| DELETE | `/api/databases/{id}` | 刪除連接 |
|
||||
| POST | `/api/databases/{id}/test` | 實際連線目標庫並查詢伺服器版本;成功與失敗都是 200(結果在 `ok` 欄位,附 `server_version` / `error` 與 `elapsed_ms`),連接記錄不存在返回 404 |
|
||||
| GET | `/api/databases/{id}/tables` | 列出目標庫當前 schema 的數據表(`name` + `kind`,按名稱排序);連不上目標時返回 502 並附錯誤訊息 |
|
||||
| GET | `/api/databases/{id}/tables/{table}/columns` | 列出資料表欄位結構(`name` / `type` / `nullable` / `default` / `primary_key`,按表定義順序);資料表不存在返回 404 |
|
||||
| POST | `/api/databases/{id}/tables/{table}/columns` | 新增欄位(`ALTER TABLE … ADD COLUMN`):`name`(≤64 字符)、`type`(原生 SQL 片段,如 `varchar(255)`)、`nullable`(缺省允許)、`default`(可選,原生 SQL 片段);欄位名衝突返回 409,成功返回 204 |
|
||||
| DELETE | `/api/databases/{id}/tables/{table}/columns/{column}` | 刪除欄位(`ALTER TABLE … DROP COLUMN`,資料一併丟失且無法復原);欄位不存在返回 404,成功返回 204 |
|
||||
| GET | `/api/databases/{id}/tables/{table}/rows` | 分頁瀏覽資料:`?limit=&offset=`(limit 1–200、缺省 50;offset ≥ 0),回應含 `columns`、字串化的 `rows`(NULL 為 `null`)、`total`(`COUNT(*)`)與生效的分頁參數 |
|
||||
| PATCH | `/api/databases/{id}/tables/{table}/rows` | 修改資料列:body 為 `{"where": {主鍵欄位: 原值}, "set": {欄位: 新值}}`(值為字串或 `null`=設為 NULL,按欄位型別隱式轉換);`where` 須恰好覆蓋主鍵欄位,`set` 欄位須存在且值 ≤65536 字符;目標列不存在(已被刪除或主鍵已變更)返回 409,成功返回 204 |
|
||||
|
||||
連線操作要點:
|
||||
|
||||
- 每次操作建立全新連線、用完即斷(不做連接複用);整體逾時 5 秒,目標不可達時不會長時間佔住請求
|
||||
- 錯誤訊息展平驅動庫的錯誤鏈,可直接區分連線被拒、認證失敗等原因(如 `db error: FATAL: password authentication failed for user "app"`)
|
||||
- 表名 / 欄位名拼入 SQL 前先經 information_schema 白名單核對(不存在的表或欄位直接 404,不進入 SQL),再以驅動各自的引號規則轉義(MySQL 反引號、PostgreSQL 雙引號),杜絕經標識符注入
|
||||
- 新增欄位的 `type` / `default` 是**原生 SQL 片段**(管理工具的固有語義):驗證攔截分號、註解起始符(`--`、`/*`)與控制字元,配合兩驅動皆走的預備語句協議(不啟用多語句),即使片段被惡意構造也無法執行第二條語句;目標端語義錯誤(如對有資料的表加 NOT NULL 無默認值欄位)由驅動錯誤原樣回報(502)
|
||||
- 刪除欄位屬**不可復原的破壞性操作**;`/api/*` 端點暫不要求會話(接入認證前,對外暴露埠時須自行做好網路隔離)
|
||||
- 瀏覽資料時儲存格一律轉為字串表示(PostgreSQL 逐欄 `::text` 轉換),NULL 保留為 `null` 由前端呈現
|
||||
- 修改資料列以**主鍵定位**(欄位是否為主鍵經 `TABLE_CONSTRAINTS` 連接 `KEY_COLUMN_USAGE` 判定):MySQL 的值以預備語句參數綁定(並啟用 `CLIENT_FOUND_ROWS`,使 affected rows 為匹配列數);PostgreSQL 的值以引號加倍轉義的字面值拼入(標準遵循字串下反斜線無特殊含義),未知型別字面值由伺服器隱式轉換為欄位型別;型別無法轉換、違反約束等錯誤由目標庫原樣回報(502)
|
||||
- **暫未啟用 TLS**:對目標庫的連線為明文,僅適合配合受信任網路使用(MySQL 的 `caching_sha2_password` 認證在無 TLS 下經伺服器 RSA 金鑰完成)
|
||||
|
||||
輸入欄位:
|
||||
|
||||
| 欄位 | 必填 | 說明 |
|
||||
| --- | --- | --- |
|
||||
| `name` | 是 | 連接顯示名稱,全表唯一,≤ 128 字符 |
|
||||
| `type` | 是 | 數據庫類型,目前僅支援 `"mysql"` / `"postgres"` |
|
||||
| `host` | 是 | 主機名或 IP,≤ 255 字符 |
|
||||
| `port` | 否 | 埠,1–65535;缺省按類型補 3306(mysql)/ 5432(postgres) |
|
||||
| `username` | 是 | 連接用戶名,≤ 64 字符 |
|
||||
| `password` | 否 | 連接密碼,默認空字串;**永不透過 API 序列化輸出**(連線需明文可用,故不做單向雜湊) |
|
||||
| `database_name` | 是 | 目標資料庫名,≤ 64 字符 |
|
||||
|
||||
輸入會先被正規化(去除首尾空白,密碼除外;`port` 缺省補默認);驗證失敗返回 400,`name` 衝突返回 409,`type` 為不支援的類型時由反序列化直接拒絕。
|
||||
|
||||
```bash
|
||||
# 建立連接(port 自動補 3306,回應不含 password)
|
||||
curl -X POST http://127.0.0.1:8080/api/databases \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"name": "shop-prod", "type": "mysql", "host": "10.0.0.5",
|
||||
"username": "app", "password": "secret", "database_name": "shop"}'
|
||||
|
||||
# 列出所有連接
|
||||
curl http://127.0.0.1:8080/api/databases
|
||||
```
|
||||
|
||||
## 開發路線圖
|
||||
|
||||
- [ ] **階段一:存儲層 MVP(進行中)** — 連接池(deadpool-sqlite)與 WAL 初始化已完成;Account 模型的 CRUD 與 REST API(`/api/accounts`)已就緒,通用表管理開發中
|
||||
- [ ] **階段二:自定義查詢引擎** — 查詢語法定義、解析與執行
|
||||
- [ ] **階段三:HTTP API(進行中)** — axum 伺服器骨架、健康檢查與帳戶 CRUD 端點已完成,登入 / 登出 / 會話已就緒(頁面已受保護,API 端點接入認證開發中),其餘 API 端點開發中
|
||||
- [ ] **階段四:Web 管理介面(進行中)** — 登入頁、會話、變更密碼頁、數據庫連接管理頁(`/databases`)、連接詳情頁(實際連線測試 + 數據表瀏覽)、數據表管理頁(欄位結構 + 新增 / 刪除欄位)與數據管理頁(表內資料分頁瀏覽 + 以主鍵定位編輯資料列)已完成;瀏覽器端 UI:查詢執行、新增 / 刪除資料列開發中
|
||||
- [ ] **進階功能** — 匯入 / 匯出、備份、多用戶與權限等
|
||||
|
||||
## 專案現狀與結構
|
||||
|
||||
目前已完成 HTTP API 骨架、存儲層接線、首頁渲染與登入 / 會話(axum + rusqlite + askama),並以 Account(帳戶)打通「模型 → 存儲 → REST API」全鏈路;Database(外部數據庫連接,mysql / postgres)為第二個模型,同構接入同一鏈路,且已具備實際連線能力(`connect` 模組:測試連接、列出數據表、檢視欄位結構、分頁瀏覽資料):
|
||||
|
||||
```text
|
||||
alterdb/
|
||||
├── Cargo.toml # 項目清單(axum / tokio / rusqlite / askama / mysql_async / tokio-postgres 等)
|
||||
├── .gitignore
|
||||
├── README.md
|
||||
├── templates/ # Askama 模板(編譯期內嵌進執行檔)
|
||||
│ ├── base.html # 頁面骨架(基礎樣式與布局塊)
|
||||
│ ├── _shell.html # 應用外殼:側邊導航欄(品牌 / 導航 / 登入者與登出)+ 主內容區
|
||||
│ ├── index.html # 首頁(登入後可見)
|
||||
│ ├── databases.html # 數據庫連接列表頁(外殼 + 內嵌 JS 調用 /api/databases)
|
||||
│ ├── database_detail.html # 連接詳情頁(連接資訊 + 連接狀態 + 數據表,內嵌 JS 即時連線)
|
||||
│ ├── table_detail.html # 數據表管理頁(欄位結構管理,內嵌 JS 即時連線)
|
||||
│ ├── table_data.html # 數據管理頁(表內資料分頁瀏覽 + 編輯資料列,內嵌 JS 即時連線)
|
||||
│ ├── database_form.html # 新增 / 編輯連接共用表單頁(服務端預填 + 提交 JS)
|
||||
│ ├── password.html # 變更密碼頁(原密碼 + 新密碼兩次確認)
|
||||
│ ├── login.html # 登入頁(無側欄)
|
||||
│ └── 404.html # 404 頁(無側欄)
|
||||
└── src/
|
||||
├── main.rs # 程序入口:初始化存儲層並啟動 HTTP 伺服器
|
||||
├── state.rs # 應用共享狀態(資料庫連接池 + 會話存儲)
|
||||
├── session.rs # 會話管理:進程內存存儲、Cookie 解析與 CurrentUser 提取器
|
||||
├── connect.rs # 實際連線能力:測試連接(版本 / 延遲)、列出數據表、檢視欄位結構與分頁瀏覽資料(mysql_async / tokio-postgres)
|
||||
├── models/ # 模型層:數據結構與輸入驗證(不含存儲細節)
|
||||
│ ├── account.rs # Account 模型(帳戶)與輸入正規化、密碼雜湊
|
||||
│ └── database.rs # Database 模型(外部數據庫連接)與 DatabaseType 枚舉
|
||||
├── storage/ # 存儲層:各模型對應表的 SQL 與 CRUD
|
||||
│ ├── mod.rs # 連接池建立、資料庫初始化與共用錯誤類型
|
||||
│ ├── account.rs # accounts 表結構與 CRUD
|
||||
│ └── database.rs # databases 表結構與 CRUD
|
||||
└── controllers/ # 控制器層(HTTP API + 頁面)
|
||||
├── mod.rs # 路由匯總
|
||||
├── accounts.rs # 帳戶 CRUD API(/api/accounts)
|
||||
├── auth.rs # 登入 / 登出 / 變更密碼(/login、/logout、/password)
|
||||
├── database.rs # 數據庫連接 CRUD API 與連線操作(/api/databases)
|
||||
├── health.rs # 健康檢查 API(GET /api/health,含資料庫狀態)
|
||||
└── pages.rs # 頁面渲染(GET /、/databases 等,需登入)
|
||||
```
|
||||
|
||||
## 開發
|
||||
|
||||
```bash
|
||||
cargo build # 編譯
|
||||
cargo test # 執行測試
|
||||
cargo run # 運行
|
||||
```
|
||||
|
||||
## 授權
|
||||
|
||||
尚未決定(TBD)。
|
||||
Reference in New Issue
Block a user