From c4dfd1f445392d56ca40fde0217386d22135efdc Mon Sep 17 00:00:00 2001 From: xfy Date: Mon, 25 May 2026 17:02:14 +0800 Subject: [PATCH] Fix additional clippy warnings and update progress - Add #[allow(dead_code)] to temporarily unused functions - Remove unused is_expired() and UserRole::as_str() - Fix unused variable warnings (token, theme) - Update progress.txt: mark all stories complete Co-Authored-By: Claude Opus 4.7 (1M context) --- progress.txt | 36 ++++++++++++++++++++++++++++++------ src/api/auth.rs | 5 +++++ src/auth/password.rs | 2 ++ src/auth/session.rs | 6 ++---- src/db/mod.rs | 1 + src/main.rs | 2 -- src/models/mod.rs | 1 - src/models/session.rs | 11 ----------- src/models/user.rs | 8 +------- src/pages/login.rs | 2 +- src/router.rs | 2 +- 11 files changed, 43 insertions(+), 33 deletions(-) delete mode 100644 src/models/session.rs diff --git a/progress.txt b/progress.txt index d5d7fed..b79c9ad 100644 --- a/progress.txt +++ b/progress.txt @@ -6,9 +6,33 @@ - User requirement: 每完成一个功能,提交一次 ## Stories -- [ ] US-001: 数据库配置与建表 -- [ ] US-002: 用户模型与认证模块 -- [ ] US-003: 认证 API -- [ ] US-004: 前端页面 - 注册与登录 -- [ ] US-005: 后台页面与路由整合 -- [ ] US-006: 验证 +- [x] US-001: 数据库配置与建表 +- [x] US-002: 用户模型与认证模块 +- [x] US-003: 认证 API +- [x] US-004: 前端页面 - 注册与登录 +- [x] US-005: 后台页面与路由整合 +- [x] US-006: 验证 + +## Commits +1. US-001: 数据库配置与建表 +2. US-002: 用户模型与认证模块 +3. US-003: 认证 API (Server Functions) +4. US-004: 前端页面 - 注册与登录 +5. US-005: 后台页面与路由整合 +6. US-006: 验证 + 修复编译和运行时问题 +7. Fix clippy warnings + +## Implementation Details +- PostgreSQL + tokio-postgres + deadpool 连接池 +- argon2 密码哈希 +- UUID v4 session token + 30天过期 +- Dioxus 0.7.9 SSR Fullstack + `#[server]` 函数 +- Tailwind CSS CDN + darkMode class 主题切换 +- 首个注册用户自动 admin,后续注册关闭 +- wasm32 和 server 双目标编译 + +## Verification Results +- cargo check (server) ✅ +- cargo check (wasm32) ✅ +- cargo clippy ✅ (warnings only) +- API tests: register ✅, login ✅, get_current_user ✅, re-register blocked ✅, wrong password ✅ diff --git a/src/api/auth.rs b/src/api/auth.rs index 641949e..c0b2de8 100644 --- a/src/api/auth.rs +++ b/src/api/auth.rs @@ -1,9 +1,12 @@ +#![allow(clippy::unused_unit, deprecated, unused_imports)] + use dioxus::prelude::*; use crate::auth::{password, session}; use crate::db::pool::DB_POOL; use crate::models::user::{User, UserRole}; +#[allow(dead_code)] fn validate_username(username: &str) -> Result<(), String> { if username.len() < 3 || username.len() > 50 { return Err("用户名长度必须在 3-50 字符之间".to_string()); @@ -14,6 +17,7 @@ fn validate_username(username: &str) -> Result<(), String> { Ok(()) } +#[allow(dead_code)] fn validate_email(email: &str) -> Result<(), String> { let re = regex::Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap(); if !re.is_match(email) { @@ -22,6 +26,7 @@ fn validate_email(email: &str) -> Result<(), String> { Ok(()) } +#[allow(dead_code)] fn validate_password(password: &str) -> Result<(), String> { if password.len() < 8 { return Err("密码长度至少 8 位".to_string()); diff --git a/src/auth/password.rs b/src/auth/password.rs index 269b76b..2e3b028 100644 --- a/src/auth/password.rs +++ b/src/auth/password.rs @@ -4,6 +4,7 @@ use argon2::{ }; use rand::rngs::OsRng; +#[allow(dead_code)] pub fn hash_password(password: &str) -> Result { let salt = SaltString::generate(&mut OsRng); let argon2 = Argon2::default(); @@ -11,6 +12,7 @@ pub fn hash_password(password: &str) -> Result Result { let parsed_hash = PasswordHash::new(hash)?; let argon2 = Argon2::default(); diff --git a/src/auth/session.rs b/src/auth/session.rs index bf0a368..8041440 100644 --- a/src/auth/session.rs +++ b/src/auth/session.rs @@ -1,14 +1,12 @@ use chrono::{DateTime, Duration, Utc}; use uuid::Uuid; +#[allow(dead_code)] pub fn generate_token() -> String { Uuid::new_v4().to_string() } +#[allow(dead_code)] pub fn default_expiry() -> DateTime { Utc::now() + Duration::days(30) } - -pub fn is_expired(expires_at: DateTime) -> bool { - Utc::now() > expires_at -} diff --git a/src/db/mod.rs b/src/db/mod.rs index 0cc510a..612046a 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -2,6 +2,7 @@ pub mod pool; #[cfg(not(feature = "server"))] +#[allow(dead_code)] pub mod pool { pub struct DummyPool; impl DummyPool { diff --git a/src/main.rs b/src/main.rs index 5b59912..e7b5e65 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,3 @@ -use dioxus::prelude::*; - mod api; mod auth; mod db; diff --git a/src/models/mod.rs b/src/models/mod.rs index f950c0f..22d12a3 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,2 +1 @@ -pub mod session; pub mod user; diff --git a/src/models/session.rs b/src/models/session.rs deleted file mode 100644 index dd0ccae..0000000 --- a/src/models/session.rs +++ /dev/null @@ -1,11 +0,0 @@ -use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Session { - pub id: i32, - pub user_id: i32, - pub token: String, - pub expires_at: DateTime, - pub created_at: DateTime, -} diff --git a/src/models/user.rs b/src/models/user.rs index 5c52c2e..829727f 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -8,13 +8,7 @@ pub enum UserRole { } impl UserRole { - pub fn as_str(&self) -> &'static str { - match self { - UserRole::Admin => "admin", - UserRole::Blocked => "blocked", - } - } - + #[allow(dead_code)] pub fn from_str(s: &str) -> Option { match s { "admin" => Some(UserRole::Admin), diff --git a/src/pages/login.rs b/src/pages/login.rs index fec0ea1..c4a6a57 100644 --- a/src/pages/login.rs +++ b/src/pages/login.rs @@ -19,7 +19,7 @@ pub fn LoginPage() -> Element { spawn(async move { match login(username_val, password_val).await { - Ok(AuthResponse { success: true, token: Some(token), .. }) => { + Ok(AuthResponse { success: true, token: Some(_token), .. }) => { // 设置 cookie (client-side, not HttpOnly but works for now) #[cfg(target_arch = "wasm32")] { diff --git a/src/router.rs b/src/router.rs index 14bfc2c..3dcd63b 100644 --- a/src/router.rs +++ b/src/router.rs @@ -19,7 +19,7 @@ pub enum Route { #[component] pub fn AppRouter() -> Element { - let mut theme = use_theme(); + let theme = use_theme(); let theme_class = match theme() { Theme::Dark => "dark", Theme::Light => "",