Skip to main content

yggdrasil/api/settings/
site.rs

1// 与 posts 模块一致:Dioxus `#[server]` 宏触发 deprecated/unit/too_many_arguments
2// 提示,按项目惯例放行(限流/运行器等配置项天然参数多)。
3#![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::SiteSettings;
14
15// ============================================================================
16// 站点公开配置
17// ============================================================================
18
19/// 读取站点公开配置。
20///
21/// **公开接口**(无需登录):供前台页脚 SSR 读取 GitHub 链接等。先查 moka 缓存,
22/// 未命中查 settings 表,缺失键回退默认值(空串=不展示图标)。
23#[server(GetSiteSettings, "/api")]
24pub async fn get_site_settings() -> Result<SiteSettings, ServerFnError> {
25    #[cfg(feature = "server")]
26    {
27        use crate::models::settings::DEFAULT_SITE_GITHUB_URL;
28
29        if let Some(cached) = crate::cache::get_site_settings().await {
30            return Ok(cached);
31        }
32
33        let client = get_conn().await.map_err(AppError::db_conn)?;
34
35        let github_url: String = client
36            .query_opt(
37                "SELECT value FROM settings WHERE key = 'site_github_url'",
38                &[],
39            )
40            .await
41            .map_err(AppError::query)?
42            .map(|r| r.get::<_, String>("value"))
43            .unwrap_or_else(|| DEFAULT_SITE_GITHUB_URL.to_string());
44
45        let settings = SiteSettings { github_url };
46        crate::cache::set_site_settings(settings.clone()).await;
47        Ok(settings)
48    }
49
50    #[cfg(not(feature = "server"))]
51    {
52        Ok(SiteSettings::default())
53    }
54}
55
56/// 更新站点公开配置。
57///
58/// 仅 admin。写入前规范化(trim / 截断 / 补 https://);写后失效 moka 站点配置缓存
59/// 与全部公开页 SSR 缓存(页脚出现在每个前台页面,无法定向失效)。
60#[server(UpdateSiteSettings, "/api")]
61pub async fn update_site_settings(github_url: String) -> Result<SiteSettings, ServerFnError> {
62    let _user = get_current_admin_user().await?;
63
64    let github_url = SiteSettings::normalize_github_url(&github_url);
65
66    #[cfg(feature = "server")]
67    {
68        let client = get_conn().await.map_err(AppError::db_conn)?;
69
70        client
71            .execute(
72                "INSERT INTO settings (key, value, updated_at) VALUES ('site_github_url', $1, NOW())
73                 ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW()",
74                &[&github_url],
75            )
76            .await
77            .map_err(AppError::query)?;
78
79        crate::cache::invalidate_site_settings();
80        crate::ssr_cache::invalidate_ssr_all_public();
81        tracing::info!("Site settings updated: github_url={}", github_url);
82    }
83
84    Ok(SiteSettings { github_url })
85}