Skip to main content

shared/settings/
app.rs

1use crate::prelude::StringExt;
2
3use super::{
4    ExtensionSettings, SettingsDeserializeExt, SettingsDeserializer, SettingsSerializeExt,
5    SettingsSerializer,
6};
7use compact_str::ToCompactString;
8use serde::{Deserialize, Serialize};
9use utoipa::ToSchema;
10
11#[derive(ToSchema, Serialize, Deserialize, Clone, Copy)]
12#[serde(rename_all = "snake_case")]
13pub enum TwoFactorRequirement {
14    Admins,
15    AllUsers,
16    None,
17}
18
19#[derive(Clone, ToSchema, Serialize, Deserialize)]
20pub struct AppSettingsApp {
21    pub name: compact_str::CompactString,
22    pub icon: compact_str::CompactString,
23    pub banner: Option<compact_str::CompactString>,
24    pub url: compact_str::CompactString,
25    pub language: compact_str::CompactString,
26    pub two_factor_requirement: TwoFactorRequirement,
27
28    pub session_cookie: compact_str::CompactString,
29    pub session_duration_seconds: u64,
30
31    pub telemetry_enabled: bool,
32    pub registration_enabled: bool,
33}
34
35#[async_trait::async_trait]
36impl SettingsSerializeExt for AppSettingsApp {
37    async fn serialize(
38        &self,
39        serializer: SettingsSerializer,
40    ) -> Result<SettingsSerializer, anyhow::Error> {
41        Ok(serializer
42            .write_raw_setting("name", &*self.name)
43            .write_raw_setting("icon", &*self.icon)
44            .write_raw_setting("banner", self.banner.as_deref().unwrap_or(""))
45            .write_raw_setting("url", &*self.url)
46            .write_raw_setting("language", &*self.language)
47            .write_raw_setting(
48                "two_factor_requirement",
49                match self.two_factor_requirement {
50                    TwoFactorRequirement::Admins => "admins",
51                    TwoFactorRequirement::AllUsers => "all_users",
52                    TwoFactorRequirement::None => "none",
53                },
54            )
55            .write_raw_setting("session_cookie", &*self.session_cookie)
56            .write_raw_setting(
57                "session_duration_seconds",
58                self.session_duration_seconds.to_compact_string(),
59            )
60            .write_raw_setting(
61                "telemetry_enabled",
62                self.telemetry_enabled.to_compact_string(),
63            )
64            .write_raw_setting(
65                "registration_enabled",
66                self.registration_enabled.to_compact_string(),
67            ))
68    }
69}
70
71pub struct AppSettingsAppDeserializer;
72
73#[async_trait::async_trait]
74impl SettingsDeserializeExt for AppSettingsAppDeserializer {
75    async fn deserialize_boxed(
76        &self,
77        mut deserializer: SettingsDeserializer<'_>,
78    ) -> Result<ExtensionSettings, anyhow::Error> {
79        Ok(Box::new(AppSettingsApp {
80            name: deserializer
81                .take_raw_setting("name")
82                .unwrap_or_else(|| "Calagopus".into()),
83            icon: deserializer
84                .take_raw_setting("icon")
85                .unwrap_or_else(|| "/icon.svg".into()),
86            banner: deserializer
87                .take_raw_setting("banner")
88                .and_then(|s| s.into_optional()),
89            url: deserializer
90                .take_raw_setting("url")
91                .unwrap_or_else(|| "http://localhost:8000".into()),
92            language: deserializer
93                .take_raw_setting("language")
94                .unwrap_or_else(|| "en".into()),
95            two_factor_requirement: match deserializer
96                .take_raw_setting("two_factor_requirement")
97                .as_deref()
98            {
99                Some("admins") => TwoFactorRequirement::Admins,
100                Some("all_users") => TwoFactorRequirement::AllUsers,
101                _ => TwoFactorRequirement::None,
102            },
103            session_cookie: deserializer
104                .take_raw_setting("session_cookie")
105                .unwrap_or_else(|| "calagopus_session".into()),
106            session_duration_seconds: deserializer
107                .take_raw_setting("session_duration_seconds")
108                .and_then(|s| s.parse::<u64>().ok())
109                .unwrap_or(7 * 24 * 3600),
110            telemetry_enabled: deserializer
111                .take_raw_setting("telemetry_enabled")
112                .map(|s| s == "true")
113                .unwrap_or(true),
114            registration_enabled: deserializer
115                .take_raw_setting("registration_enabled")
116                .map(|s| s == "true")
117                .unwrap_or(true),
118        }))
119    }
120}