refactor: extract session parsing to auth/session.rs and db error helpers to api/utils.rs
This commit is contained in:
parent
9da060ac32
commit
d3be04bcec
@ -5,6 +5,7 @@ use dioxus::prelude::*;
|
|||||||
use http::header::{HeaderValue, SET_COOKIE};
|
use http::header::{HeaderValue, SET_COOKIE};
|
||||||
|
|
||||||
use crate::auth::{password, session};
|
use crate::auth::{password, session};
|
||||||
|
use crate::auth::session::get_session_from_ctx;
|
||||||
use crate::db::pool::get_conn;
|
use crate::db::pool::get_conn;
|
||||||
use crate::models::user::{PublicUser, User, UserRole};
|
use crate::models::user::{PublicUser, User, UserRole};
|
||||||
|
|
||||||
@ -36,20 +37,6 @@ fn validate_password(password: &str) -> Result<(), String> {
|
|||||||
Ok(())
|
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)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct AuthResponse {
|
pub struct AuthResponse {
|
||||||
pub success: bool,
|
pub success: bool,
|
||||||
@ -216,17 +203,7 @@ pub async fn login(username: String, password: String) -> Result<AuthResponse, S
|
|||||||
|
|
||||||
#[server(Logout, "/api")]
|
#[server(Logout, "/api")]
|
||||||
pub async fn logout() -> Result<AuthResponse, ServerFnError> {
|
pub async fn logout() -> Result<AuthResponse, ServerFnError> {
|
||||||
let token = if let Some(ctx) = dioxus::fullstack::FullstackContext::current() {
|
let token = get_session_from_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())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let client = get_conn().await.map_err(|e| {
|
let client = get_conn().await.map_err(|e| {
|
||||||
tracing::error!("Logout DB connection failed: {:?}", e);
|
tracing::error!("Logout DB connection failed: {:?}", e);
|
||||||
@ -266,17 +243,7 @@ pub struct CurrentUserResponse {
|
|||||||
|
|
||||||
#[server(GetCurrentUser, "/api")]
|
#[server(GetCurrentUser, "/api")]
|
||||||
pub async fn get_current_user() -> Result<CurrentUserResponse, ServerFnError> {
|
pub async fn get_current_user() -> Result<CurrentUserResponse, ServerFnError> {
|
||||||
let token = if let Some(ctx) = dioxus::fullstack::FullstackContext::current() {
|
let token = get_session_from_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())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(token) = token else {
|
let Some(token) = token else {
|
||||||
return Ok(CurrentUserResponse { user: None });
|
return Ok(CurrentUserResponse { user: None });
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod posts;
|
pub mod posts;
|
||||||
|
pub mod utils;
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
use dioxus::prelude::*;
|
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::db::pool::get_conn;
|
||||||
use crate::models::post::{Post, PostStats, PostStatus, Tag};
|
use crate::models::post::{Post, PostStats, PostStatus, Tag};
|
||||||
use crate::models::user::{User, UserRole};
|
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)
|
// 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")]
|
#[cfg(feature = "server")]
|
||||||
async fn get_current_admin_user() -> Result<User, ServerFnError> {
|
async fn get_current_admin_user() -> Result<User, ServerFnError> {
|
||||||
let token = if let Some(ctx) = dioxus::fullstack::FullstackContext::current() {
|
let token = get_session_from_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())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(token) = token else {
|
let Some(token) = token else {
|
||||||
return Err(ServerFnError::new("未登录"));
|
return Err(ServerFnError::new("未登录"));
|
||||||
};
|
};
|
||||||
|
|
||||||
let client = get_conn().await.map_err(|e| {
|
let client = get_conn().await.map_err(db_conn_error)?;
|
||||||
tracing::error!("DB connection failed: {:?}", e);
|
|
||||||
ServerFnError::new(format!("数据库连接失败: {}", e))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let row = client
|
let row = client
|
||||||
.query_opt(
|
.query_opt(
|
||||||
@ -56,10 +31,7 @@ async fn get_current_admin_user() -> Result<User, ServerFnError> {
|
|||||||
&[&token],
|
&[&token],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(query_error)?;
|
||||||
tracing::error!("query failed: {:?}", e);
|
|
||||||
ServerFnError::new(format!("查询失败: {}", e))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let user = match row {
|
let user = match row {
|
||||||
Some(row) => {
|
Some(row) => {
|
||||||
|
|||||||
15
src/api/utils.rs
Normal file
15
src/api/utils.rs
Normal 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))
|
||||||
|
}
|
||||||
@ -10,3 +10,31 @@ pub fn generate_token() -> String {
|
|||||||
pub fn default_expiry() -> DateTime<Utc> {
|
pub fn default_expiry() -> DateTime<Utc> {
|
||||||
Utc::now() + Duration::days(30)
|
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())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user