yggdrasil/api/settings/
asset_purge.rs1#![allow(clippy::unused_unit, deprecated, clippy::too_many_arguments)]
4
5use dioxus::prelude::*;
6
7#[cfg(feature = "server")]
8use crate::api::auth::get_current_admin_user;
9#[cfg(feature = "server")]
10use crate::api::error::AppError;
11#[cfg(feature = "server")]
12use crate::db::pool::get_conn;
13use crate::models::settings::AssetPurgeSettings;
14
15#[cfg(feature = "server")]
25pub(crate) async fn seed_asset_purge_settings_from_env(
26 client: &tokio_postgres::Client,
27) -> Result<(), AppError> {
28 let mut seeds: Vec<(&'static str, String)> = Vec::new();
29
30 if let Ok(v) = std::env::var("ASSET_ORPHAN_PURGE_ENABLED") {
31 match v.trim().parse::<bool>() {
32 Ok(b) => seeds.push(("asset_orphan_purge_enabled", b.to_string())),
33 Err(_) => {
34 tracing::warn!("ASSET_ORPHAN_PURGE_ENABLED={v:?} 非法(期望 true/false),跳过")
35 }
36 }
37 }
38 if let Ok(v) = std::env::var("ASSET_ORPHAN_RETENTION_DAYS") {
39 match v.trim().parse::<i32>() {
40 Ok(n) => seeds.push((
41 "asset_orphan_retention_days",
42 crate::models::settings::AssetPurgeSettings::clamp_retention(n).to_string(),
43 )),
44 Err(_) => {
45 tracing::warn!("ASSET_ORPHAN_RETENTION_DAYS={v:?} 非法(期望正整数),跳过")
46 }
47 }
48 }
49
50 for (key, value) in seeds {
51 client
52 .execute(
53 "INSERT INTO settings (key, value) VALUES ($1, $2) ON CONFLICT (key) DO NOTHING",
54 &[&key, &value],
55 )
56 .await
57 .map_err(AppError::query)?;
58 tracing::info!("孤儿素材清理配置已从环境变量播种: {key}={value}(仅键缺失时生效)");
59 }
60 Ok(())
61}
62
63#[server(GetAssetPurgeSettings, "/api")]
67pub async fn get_asset_purge_settings() -> Result<AssetPurgeSettings, ServerFnError> {
68 let _user = get_current_admin_user().await?;
69
70 #[cfg(feature = "server")]
71 {
72 let client = get_conn().await.map_err(AppError::db_conn)?;
73
74 let enabled: bool = client
75 .query_opt(
76 "SELECT value FROM settings WHERE key = 'asset_orphan_purge_enabled'",
77 &[],
78 )
79 .await
80 .map_err(AppError::query)?
81 .and_then(|r| r.get::<_, String>("value").parse().ok())
82 .unwrap_or(crate::models::settings::DEFAULT_ASSET_ORPHAN_PURGE_ENABLED);
83
84 let days: i32 = client
85 .query_opt(
86 "SELECT value FROM settings WHERE key = 'asset_orphan_retention_days'",
87 &[],
88 )
89 .await
90 .map_err(AppError::query)?
91 .and_then(|r| r.get::<_, String>("value").parse().ok())
92 .unwrap_or(crate::models::settings::DEFAULT_ASSET_ORPHAN_RETENTION_DAYS);
93
94 Ok(AssetPurgeSettings {
95 auto_purge_enabled: enabled,
96 retention_days: AssetPurgeSettings::clamp_retention(days),
97 })
98 }
99
100 #[cfg(not(feature = "server"))]
101 {
102 Ok(AssetPurgeSettings::default())
103 }
104}
105
106#[server(UpdateAssetPurgeSettings, "/api")]
111pub async fn update_asset_purge_settings(
112 auto_purge_enabled: bool,
113 retention_days: i32,
114) -> Result<AssetPurgeSettings, ServerFnError> {
115 let _user = get_current_admin_user().await?;
116
117 let retention_days = AssetPurgeSettings::clamp_retention(retention_days);
118
119 #[cfg(feature = "server")]
120 {
121 let client = get_conn().await.map_err(AppError::db_conn)?;
122
123 for (key, value) in [
124 ("asset_orphan_purge_enabled", auto_purge_enabled.to_string()),
125 ("asset_orphan_retention_days", retention_days.to_string()),
126 ] {
127 client
128 .execute(
129 "INSERT INTO settings (key, value, updated_at) VALUES ($1, $2, NOW())
130 ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW()",
131 &[&key, &value],
132 )
133 .await
134 .map_err(AppError::query)?;
135 }
136
137 tracing::info!(
138 "Asset purge settings updated: auto_purge={}, retention_days={}",
139 auto_purge_enabled,
140 retention_days
141 );
142 }
143
144 Ok(AssetPurgeSettings {
145 auto_purge_enabled,
146 retention_days,
147 })
148}