132 lines
3.9 KiB
Rust
132 lines
3.9 KiB
Rust
use std::{error::Error, fmt};
|
|
|
|
use module_auth::{InMemoryPasswordUserStore, PasswordEntryService};
|
|
use platform_auth::{
|
|
JwtConfig, JwtError, RefreshCookieConfig, RefreshCookieError, RefreshCookieSameSite,
|
|
};
|
|
use platform_oss::{OssClient, OssConfig, OssError};
|
|
|
|
use crate::config::AppConfig;
|
|
|
|
// 当前阶段先保留最小共享状态壳,后续逐步接入配置、客户端与平台适配。
|
|
#[derive(Clone, Debug)]
|
|
pub struct AppState {
|
|
// 配置会在后续中间件、路由和平台适配接入时逐步消费。
|
|
#[allow(dead_code)]
|
|
pub config: AppConfig,
|
|
auth_jwt_config: JwtConfig,
|
|
refresh_cookie_config: RefreshCookieConfig,
|
|
oss_client: Option<OssClient>,
|
|
password_entry_service: PasswordEntryService,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum AppStateInitError {
|
|
Jwt(JwtError),
|
|
RefreshCookie(RefreshCookieError),
|
|
Oss(OssError),
|
|
}
|
|
|
|
impl AppState {
|
|
pub fn new(config: AppConfig) -> Result<Self, AppStateInitError> {
|
|
let auth_jwt_config = JwtConfig::new(
|
|
config.jwt_issuer.clone(),
|
|
config.jwt_secret.clone(),
|
|
config.jwt_access_token_ttl_seconds,
|
|
)?;
|
|
let refresh_cookie_same_site =
|
|
RefreshCookieSameSite::parse(&config.refresh_cookie_same_site).ok_or(
|
|
RefreshCookieError::InvalidConfig("refresh cookie SameSite 取值非法"),
|
|
)?;
|
|
let refresh_cookie_config = RefreshCookieConfig::new(
|
|
config.refresh_cookie_name.clone(),
|
|
config.refresh_cookie_path.clone(),
|
|
config.refresh_cookie_secure,
|
|
refresh_cookie_same_site,
|
|
config.refresh_session_ttl_days,
|
|
)?;
|
|
let oss_client = build_oss_client(&config)?;
|
|
let password_entry_service =
|
|
PasswordEntryService::new(InMemoryPasswordUserStore::default());
|
|
|
|
Ok(Self {
|
|
config,
|
|
auth_jwt_config,
|
|
refresh_cookie_config,
|
|
oss_client,
|
|
password_entry_service,
|
|
})
|
|
}
|
|
|
|
pub fn auth_jwt_config(&self) -> &JwtConfig {
|
|
&self.auth_jwt_config
|
|
}
|
|
|
|
pub fn refresh_cookie_config(&self) -> &RefreshCookieConfig {
|
|
&self.refresh_cookie_config
|
|
}
|
|
|
|
pub fn oss_client(&self) -> Option<&OssClient> {
|
|
self.oss_client.as_ref()
|
|
}
|
|
|
|
pub fn password_entry_service(&self) -> &PasswordEntryService {
|
|
&self.password_entry_service
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for AppStateInitError {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Self::Jwt(error) => write!(f, "{error}"),
|
|
Self::RefreshCookie(error) => write!(f, "{error}"),
|
|
Self::Oss(error) => write!(f, "{error}"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Error for AppStateInitError {}
|
|
|
|
impl From<JwtError> for AppStateInitError {
|
|
fn from(value: JwtError) -> Self {
|
|
Self::Jwt(value)
|
|
}
|
|
}
|
|
|
|
impl From<RefreshCookieError> for AppStateInitError {
|
|
fn from(value: RefreshCookieError) -> Self {
|
|
Self::RefreshCookie(value)
|
|
}
|
|
}
|
|
|
|
impl From<OssError> for AppStateInitError {
|
|
fn from(value: OssError) -> Self {
|
|
Self::Oss(value)
|
|
}
|
|
}
|
|
|
|
fn build_oss_client(config: &AppConfig) -> Result<Option<OssClient>, AppStateInitError> {
|
|
let has_any_oss_field = config.oss_bucket.is_some()
|
|
|| config.oss_endpoint.is_some()
|
|
|| config.oss_access_key_id.is_some()
|
|
|| config.oss_access_key_secret.is_some()
|
|
|| config.oss_public_base_url.is_some();
|
|
|
|
if !has_any_oss_field {
|
|
return Ok(None);
|
|
}
|
|
|
|
let oss_config = OssConfig::new(
|
|
config.oss_bucket.clone().unwrap_or_default(),
|
|
config.oss_endpoint.clone().unwrap_or_default(),
|
|
config.oss_access_key_id.clone().unwrap_or_default(),
|
|
config.oss_access_key_secret.clone().unwrap_or_default(),
|
|
config.oss_public_base_url.clone(),
|
|
config.oss_post_expire_seconds,
|
|
config.oss_post_max_size_bytes,
|
|
config.oss_success_action_status,
|
|
)?;
|
|
|
|
Ok(Some(OssClient::new(oss_config)))
|
|
}
|