shared/settings/
app.rs

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