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 icon_light: Option<compact_str::CompactString>,
24 pub banner: Option<compact_str::CompactString>,
25 pub banner_light: Option<compact_str::CompactString>,
26 pub url: compact_str::CompactString,
27 pub language: compact_str::CompactString,
28 pub two_factor_requirement: TwoFactorRequirement,
29
30 pub session_cookie: compact_str::CompactString,
31 pub session_duration_seconds: u64,
32
33 pub telemetry_enabled: bool,
34 pub registration_enabled: bool,
35}
36
37#[async_trait::async_trait]
38impl SettingsSerializeExt for AppSettingsApp {
39 async fn serialize(
40 &self,
41 serializer: SettingsSerializer,
42 ) -> Result<SettingsSerializer, anyhow::Error> {
43 Ok(serializer
44 .write_raw_setting("name", &*self.name)
45 .write_raw_setting("icon", &*self.icon)
46 .write_raw_setting("icon_light", self.icon_light.as_deref().unwrap_or(""))
47 .write_raw_setting("banner", self.banner.as_deref().unwrap_or(""))
48 .write_raw_setting("banner_light", self.banner_light.as_deref().unwrap_or(""))
49 .write_raw_setting("url", &*self.url)
50 .write_raw_setting("language", &*self.language)
51 .write_raw_setting(
52 "two_factor_requirement",
53 match self.two_factor_requirement {
54 TwoFactorRequirement::Admins => "admins",
55 TwoFactorRequirement::AllUsers => "all_users",
56 TwoFactorRequirement::None => "none",
57 },
58 )
59 .write_raw_setting("session_cookie", &*self.session_cookie)
60 .write_raw_setting(
61 "session_duration_seconds",
62 self.session_duration_seconds.to_compact_string(),
63 )
64 .write_raw_setting(
65 "telemetry_enabled",
66 self.telemetry_enabled.to_compact_string(),
67 )
68 .write_raw_setting(
69 "registration_enabled",
70 self.registration_enabled.to_compact_string(),
71 ))
72 }
73}
74
75pub struct AppSettingsAppDeserializer;
76
77#[async_trait::async_trait]
78impl SettingsDeserializeExt for AppSettingsAppDeserializer {
79 async fn deserialize_boxed(
80 &self,
81 mut deserializer: SettingsDeserializer<'_>,
82 ) -> Result<ExtensionSettings, anyhow::Error> {
83 Ok(Box::new(AppSettingsApp {
84 name: deserializer
85 .take_raw_setting("name")
86 .unwrap_or_else(|| "Calagopus".into()),
87 icon: deserializer
88 .take_raw_setting("icon")
89 .unwrap_or_else(|| "/icon.svg".into()),
90 icon_light: deserializer
91 .take_raw_setting("icon_light")
92 .and_then(|s| s.into_optional()),
93 banner: deserializer
94 .take_raw_setting("banner")
95 .and_then(|s| s.into_optional()),
96 banner_light: deserializer
97 .take_raw_setting("banner_light")
98 .and_then(|s| s.into_optional()),
99 url: deserializer
100 .take_raw_setting("url")
101 .unwrap_or_else(|| "http://localhost:8000".into()),
102 language: deserializer
103 .take_raw_setting("language")
104 .unwrap_or_else(|| "en".into()),
105 two_factor_requirement: match deserializer
106 .take_raw_setting("two_factor_requirement")
107 .as_deref()
108 {
109 Some("admins") => TwoFactorRequirement::Admins,
110 Some("all_users") => TwoFactorRequirement::AllUsers,
111 _ => TwoFactorRequirement::None,
112 },
113 session_cookie: deserializer
114 .take_raw_setting("session_cookie")
115 .unwrap_or_else(|| "calagopus_session".into()),
116 session_duration_seconds: deserializer
117 .take_raw_setting("session_duration_seconds")
118 .and_then(|s| s.parse::<u64>().ok())
119 .unwrap_or(7 * 24 * 3600),
120 telemetry_enabled: deserializer
121 .take_raw_setting("telemetry_enabled")
122 .map(|s| s == "true")
123 .unwrap_or(true),
124 registration_enabled: deserializer
125 .take_raw_setting("registration_enabled")
126 .map(|s| s == "true")
127 .unwrap_or(true),
128 }))
129 }
130}