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}