yggdrasil/api/settings/
image_limit.rs1#![allow(clippy::unused_unit, deprecated, clippy::too_many_arguments)]
4
5use crate::api::error::ApiError;
6use leptos::prelude::*;
7
8#[cfg(feature = "server")]
9use crate::api::auth::get_current_admin_user;
10#[cfg(feature = "server")]
11use crate::api::error::AppError;
12#[cfg(feature = "server")]
13use crate::db::pool::get_conn;
14use crate::models::settings::ImageLimitSettings;
15
16#[cfg(feature = "server")]
23pub(crate) async fn seed_image_limit_settings_from_env(
24 client: &tokio_postgres::Client,
25) -> Result<(), AppError> {
26 use crate::models::settings as m;
27
28 let mut seeds: Vec<(&'static str, String)> = Vec::new();
29
30 if let Ok(v) = std::env::var("MAX_IMAGE_DIMENSION") {
31 match v.trim().parse::<u32>() {
32 Ok(n) => seeds.push((
33 "image_max_dimension",
34 m::ImageLimitSettings::clamp_max_dimension(n).to_string(),
35 )),
36 Err(_) => tracing::warn!("MAX_IMAGE_DIMENSION={v:?} 非法(期望正整数),跳过"),
37 }
38 }
39 if let Ok(v) = std::env::var("MAX_IMAGE_PIXELS") {
40 match v.trim().parse::<u64>() {
41 Ok(n) => seeds.push((
42 "image_max_pixels",
43 m::ImageLimitSettings::clamp_max_pixels(n).to_string(),
44 )),
45 Err(_) => tracing::warn!("MAX_IMAGE_PIXELS={v:?} 非法(期望正整数),跳过"),
46 }
47 }
48 if let Ok(v) = std::env::var("IMAGE_DIMENSIONS_CACHE_TTL_SECS") {
49 match v.trim().parse::<u64>() {
50 Ok(n) => seeds.push((
51 "image_dimensions_cache_ttl_secs",
52 m::ImageLimitSettings::clamp_dimensions_cache_ttl_secs(n).to_string(),
53 )),
54 Err(_) => {
55 tracing::warn!("IMAGE_DIMENSIONS_CACHE_TTL_SECS={v:?} 非法(期望正整数),跳过")
56 }
57 }
58 }
59
60 super::insert_env_seeds(client, seeds).await
61}
62
63#[cfg(feature = "server")]
65pub(crate) async fn load_image_limit_settings(
66 client: &tokio_postgres::Client,
67) -> Result<ImageLimitSettings, AppError> {
68 use crate::models::settings as m;
69
70 let values = super::load_setting_values(
71 client,
72 &[
73 "image_max_dimension",
74 "image_max_pixels",
75 "image_dimensions_cache_ttl_secs",
76 ],
77 )
78 .await?;
79 let max_dimension = values
80 .get("image_max_dimension")
81 .and_then(|v| v.parse().ok())
82 .map(m::ImageLimitSettings::clamp_max_dimension)
83 .unwrap_or(m::DEFAULT_IMAGE_MAX_DIMENSION);
84 let max_pixels = values
85 .get("image_max_pixels")
86 .and_then(|v| v.parse().ok())
87 .map(m::ImageLimitSettings::clamp_max_pixels)
88 .unwrap_or(m::DEFAULT_IMAGE_MAX_PIXELS);
89 let dimensions_cache_ttl_secs = values
90 .get("image_dimensions_cache_ttl_secs")
91 .and_then(|v| v.parse().ok())
92 .map(m::ImageLimitSettings::clamp_dimensions_cache_ttl_secs)
93 .unwrap_or(m::DEFAULT_IMAGE_DIMENSIONS_CACHE_TTL_SECS);
94
95 Ok(ImageLimitSettings {
96 max_dimension,
97 max_pixels,
98 dimensions_cache_ttl_secs,
99 })
100}
101
102#[server(GetImageLimitSettings, endpoint = "get_image_limit_settings", input = leptos::server_fn::codec::Json)]
104pub async fn get_image_limit_settings() -> Result<ImageLimitSettings, ApiError> {
105 let _user = get_current_admin_user().await?;
106
107 #[cfg(feature = "server")]
108 {
109 let client = get_conn().await.map_err(AppError::db_conn)?;
110 let s = load_image_limit_settings(&client)
111 .await
112 .map_err(<ApiError>::from)?;
113 Ok(s)
114 }
115
116 #[cfg(not(feature = "server"))]
117 {
118 Ok(ImageLimitSettings::default())
119 }
120}
121
122#[server(UpdateImageLimitSettings, endpoint = "update_image_limit_settings", input = leptos::server_fn::codec::Json)]
126pub async fn update_image_limit_settings(
127 max_dimension: u32,
128 max_pixels: u64,
129 dimensions_cache_ttl_secs: u64,
130) -> Result<ImageLimitSettings, ApiError> {
131 let _user = get_current_admin_user().await?;
132
133 let max_dimension = ImageLimitSettings::clamp_max_dimension(max_dimension);
134 let max_pixels = ImageLimitSettings::clamp_max_pixels(max_pixels);
135 let dimensions_cache_ttl_secs =
136 ImageLimitSettings::clamp_dimensions_cache_ttl_secs(dimensions_cache_ttl_secs);
137
138 #[cfg(feature = "server")]
139 {
140 let client = get_conn().await.map_err(AppError::db_conn)?;
141
142 super::upsert_settings(
143 &**client,
144 &[
145 ("image_max_dimension", max_dimension.to_string()),
146 ("image_max_pixels", max_pixels.to_string()),
147 (
148 "image_dimensions_cache_ttl_secs",
149 dimensions_cache_ttl_secs.to_string(),
150 ),
151 ],
152 )
153 .await?;
154
155 tracing::info!(
156 "Image limit settings updated (需重启生效): max_dimension={}, max_pixels={}, ttl={}s",
157 max_dimension,
158 max_pixels,
159 dimensions_cache_ttl_secs
160 );
161 }
162
163 Ok(ImageLimitSettings {
164 max_dimension,
165 max_pixels,
166 dimensions_cache_ttl_secs,
167 })
168}