US-006: 验证 + 修复编译和运行时问题

- 修复 migration: role 从 ENUM 改为 VARCHAR(20) 以兼容 tokio-postgres
- 修复 Cargo.toml: 将 chrono/argon2/uuid/rand 改为非 optional,添加 wasm-bindgen/getrandom js
- 修复 main.rs: Tokio runtime panic,改用 std::thread + Runtime::new
- 修复 db/mod.rs wasm stub: DummyPool 替代 deadpool_postgres
- 修复 login/admin.rs: wasm_bindgen::JsCast 条件编译
- 验证通过: 注册✓ 登录✓ get_current_user✓ 重复注册拒绝✓ 错误密码✓

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
xfy 2026-05-25 16:49:43 +08:00
parent 14b92c3a89
commit 6df0a7ee19
9 changed files with 34 additions and 14 deletions

View File

@ -0,0 +1 @@
/home/xfy/Developer/yggdrasil/src/db/mod.rs

2
Cargo.lock generated
View File

@ -4594,12 +4594,14 @@ dependencies = [
"deadpool-postgres",
"dioxus",
"dotenvy",
"getrandom 0.2.17",
"rand 0.8.6",
"regex",
"serde",
"tokio",
"tokio-postgres",
"uuid",
"wasm-bindgen",
"web-sys",
]

View File

@ -9,15 +9,17 @@ serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.52", features = ["full"], optional = true }
tokio-postgres = { version = "0.7", features = ["with-chrono-0_4"], optional = true }
deadpool-postgres = { version = "0.14", optional = true }
argon2 = { version = "0.5", optional = true }
uuid = { version = "1", features = ["v4"], optional = true }
chrono = { version = "0.4", features = ["serde"], optional = true }
regex = { version = "1.10", optional = true }
argon2 = "0.5"
uuid = { version = "1", features = ["v4", "js"] }
chrono = { version = "0.4", features = ["serde"] }
regex = "1.10"
dotenvy = { version = "0.15", optional = true }
rand = { version = "0.8", features = ["getrandom"], optional = true }
rand = { version = "0.8", features = ["getrandom"] }
getrandom = { version = "0.2", features = ["js"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
web-sys = { version = "0.3", features = ["Document", "Window", "HtmlDocument", "Storage", "Element"] }
wasm-bindgen = "0.2"
[features]
default = []
@ -27,10 +29,5 @@ server = [
"dep:tokio",
"dep:tokio-postgres",
"dep:deadpool-postgres",
"dep:argon2",
"dep:uuid",
"dep:chrono",
"dep:regex",
"dep:dotenvy",
"dep:rand",
]

View File

@ -1,11 +1,9 @@
CREATE TYPE user_role AS ENUM ('admin', 'blocked');
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role user_role NOT NULL DEFAULT 'blocked',
role VARCHAR(20) NOT NULL DEFAULT 'blocked',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

View File

@ -1 +1,13 @@
#[cfg(feature = "server")]
pub mod pool;
#[cfg(not(feature = "server"))]
pub mod pool {
pub struct DummyPool;
impl DummyPool {
pub async fn get(&self) -> Result<(), ()> {
Err(())
}
}
pub static DB_POOL: DummyPool = DummyPool;
}

View File

@ -15,7 +15,10 @@ fn main() {
#[cfg(feature = "server")]
{
dotenvy::dotenv().ok();
tokio::spawn(tasks::session_cleanup::run_cleanup());
std::thread::spawn(|| {
let rt = tokio::runtime::Runtime::new().expect("Failed to create Tokio runtime");
rt.block_on(tasks::session_cleanup::run_cleanup());
});
}
dioxus::launch(AppRouter);

View File

@ -1,5 +1,8 @@
use dioxus::prelude::*;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::JsCast;
use crate::api::auth::{get_current_user, logout};
#[component]

View File

@ -1,5 +1,8 @@
use dioxus::prelude::*;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::JsCast;
use crate::api::auth::{login, AuthResponse};
#[component]

View File

@ -1 +1,2 @@
#[cfg(feature = "server")]
pub mod session_cleanup;