refactor: extract session parsing to auth/session.rs and db error helpers to api/utils.rs

This commit is contained in:
xfy 2026-06-04 15:16:40 +08:00
parent 9da060ac32
commit d3be04bcec
5 changed files with 52 additions and 69 deletions

View File

@ -5,6 +5,7 @@ use dioxus::prelude::*;
use http::header::{HeaderValue, SET_COOKIE};
use crate::auth::{password, session};
use crate::auth::session::get_session_from_ctx;
use crate::db::pool::get_conn;
use crate::models::user::{PublicUser, User, UserRole};
@ -36,20 +37,6 @@ fn validate_password(password: &str) -> Result<(), String> {
Ok(())
}
#[cfg(feature = "server")]
fn parse_session_token(cookie_header: &str) -> Option<&str> {
cookie_header.split(';').map(|s| s.trim()).find_map(|pair| {
let mut parts = pair.splitn(2, '=');
let name = parts.next()?.trim();
let value = parts.next()?.trim();
if name == "session" {
Some(value)
} else {
None
}
})
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct AuthResponse {
pub success: bool,
@ -216,17 +203,7 @@ pub async fn login(username: String, password: String) -> Result<AuthResponse, S
#[server(Logout, "/api")]
pub async fn logout() -> Result<AuthResponse, ServerFnError> {
let token = if let Some(ctx) = dioxus::fullstack::FullstackContext::current() {
let parts = ctx.parts_mut();
parts
.headers
.get("cookie")
.and_then(|h| h.to_str().ok())
.and_then(parse_session_token)
.map(|s| s.to_string())
} else {
None
};
let token = get_session_from_ctx();
let client = get_conn().await.map_err(|e| {
tracing::error!("Logout DB connection failed: {:?}", e);
@ -266,17 +243,7 @@ pub struct CurrentUserResponse {
#[server(GetCurrentUser, "/api")]
pub async fn get_current_user() -> Result<CurrentUserResponse, ServerFnError> {
let token = if let Some(ctx) = dioxus::fullstack::FullstackContext::current() {
let parts = ctx.parts_mut();
parts
.headers
.get("cookie")
.and_then(|h| h.to_str().ok())
.and_then(parse_session_token)
.map(|s| s.to_string())
} else {
None
};
let token = get_session_from_ctx();
let Some(token) = token else {
return Ok(CurrentUserResponse { user: None });

View File

@ -1,2 +1,3 @@
pub mod auth;
pub mod posts;
pub mod utils;

View File

@ -2,6 +2,8 @@
use dioxus::prelude::*;
use crate::auth::session::get_session_from_ctx;
use crate::api::utils::{db_conn_error, query_error};
use crate::db::pool::get_conn;
use crate::models::post::{Post, PostStats, PostStatus, Tag};
use crate::models::user::{User, UserRole};
@ -10,42 +12,15 @@ use crate::models::user::{User, UserRole};
// Server-side helpers (only compiled when server feature is enabled)
// ============================================================================
#[cfg(feature = "server")]
fn parse_session_token(cookie_header: &str) -> Option<&str> {
cookie_header.split(';').map(|s| s.trim()).find_map(|pair| {
let mut parts = pair.splitn(2, '=');
let name = parts.next()?.trim();
let value = parts.next()?.trim();
if name == "session" {
Some(value)
} else {
None
}
})
}
#[cfg(feature = "server")]
async fn get_current_admin_user() -> Result<User, ServerFnError> {
let token = if let Some(ctx) = dioxus::fullstack::FullstackContext::current() {
let parts = ctx.parts_mut();
parts
.headers
.get("cookie")
.and_then(|h| h.to_str().ok())
.and_then(parse_session_token)
.map(|s| s.to_string())
} else {
None
};
let token = get_session_from_ctx();
let Some(token) = token else {
return Err(ServerFnError::new("未登录"));
};
let client = get_conn().await.map_err(|e| {
tracing::error!("DB connection failed: {:?}", e);
ServerFnError::new(format!("数据库连接失败: {}", e))
})?;
let client = get_conn().await.map_err(db_conn_error)?;
let row = client
.query_opt(
@ -56,10 +31,7 @@ async fn get_current_admin_user() -> Result<User, ServerFnError> {
&[&token],
)
.await
.map_err(|e| {
tracing::error!("query failed: {:?}", e);
ServerFnError::new(format!("查询失败: {}", e))
})?;
.map_err(query_error)?;
let user = match row {
Some(row) => {

15
src/api/utils.rs Normal file
View File

@ -0,0 +1,15 @@
#![allow(clippy::unused_unit)]
use dioxus::prelude::*;
#[cfg(feature = "server")]
pub fn db_conn_error(e: impl std::fmt::Display) -> ServerFnError {
tracing::error!("DB connection failed: {}", e);
ServerFnError::new(format!("数据库连接失败: {}", e))
}
#[cfg(feature = "server")]
pub fn query_error(e: impl std::fmt::Display) -> ServerFnError {
tracing::error!("Query failed: {}", e);
ServerFnError::new(format!("查询失败: {}", e))
}

View File

@ -10,3 +10,31 @@ pub fn generate_token() -> String {
pub fn default_expiry() -> DateTime<Utc> {
Utc::now() + Duration::days(30)
}
pub fn parse_session_token(cookie_header: &str) -> Option<&str> {
cookie_header.split(';').map(|s| s.trim()).find_map(|pair| {
let mut parts = pair.splitn(2, '=');
let name = parts.next()?.trim();
let value = parts.next()?.trim();
if name == "session" {
Some(value)
} else {
None
}
})
}
#[cfg(feature = "server")]
pub fn get_session_from_ctx() -> Option<String> {
use dioxus::fullstack::FullstackContext;
FullstackContext::current().and_then(|ctx| {
let parts = ctx.parts_mut();
parts
.headers
.get("cookie")
.and_then(|h| h.to_str().ok())
.and_then(parse_session_token)
.map(|s| s.to_string())
})
}