caldir_core/remote/
config.rs1mod params;
2
3use crate::ProviderSlug;
4use serde::{Deserialize, Serialize};
5
6pub use params::RemoteConfigParams;
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9pub struct RemoteConfig {
10 #[serde(rename = "provider")]
11 provider_slug: ProviderSlug,
12
13 #[serde(flatten)]
14 params: RemoteConfigParams,
15}
16
17impl RemoteConfig {
20 pub fn new(provider_slug: ProviderSlug, params: RemoteConfigParams) -> Self {
21 Self {
22 provider_slug,
23 params,
24 }
25 }
26
27 pub fn provider_slug(&self) -> &ProviderSlug {
28 &self.provider_slug
29 }
30
31 pub fn get(&self, key: &str) -> Option<&toml::Value> {
32 self.params().get(key)
33 }
34
35 pub(crate) fn params(&self) -> &RemoteConfigParams {
36 &self.params
37 }
38
39 pub fn account_identifier(&self) -> Option<&str> {
46 let key = format!("{}_account", self.provider_slug());
47 self.params().get(&key).and_then(|v| v.as_str())
48 }
49
50 pub fn account_email(&self) -> Option<&str> {
52 let key = format!("{}_email", self.provider_slug());
53 self.params()
54 .get(&key)
55 .and_then(|v| v.as_str())
56 .or_else(|| self.account_identifier())
57 .filter(|email| email.contains('@'))
58 }
59
60 #[cfg(test)]
61 fn from_toml(s: &str) -> Result<Self, toml::de::Error> {
62 toml::from_str(s)
63 }
64
65 #[cfg(test)]
66 fn to_toml(&self) -> Result<String, toml::ser::Error> {
67 toml::to_string(self)
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn parses_provider_and_flattened_params() {
77 let toml_str = r#"
78provider = "hooli"
79hooli_calendar_id = "abc@group.calendar.hooli.com"
80hooli_account = "user@hmail.com"
81"#;
82
83 let remote_config = RemoteConfig::from_toml(toml_str).unwrap();
84
85 assert_eq!(remote_config.provider_slug.to_string(), "hooli");
86 assert_eq!(
87 remote_config.get("hooli_account"),
88 Some(&toml::Value::String("user@hmail.com".to_string()))
89 );
90 assert_eq!(
91 remote_config.get("hooli_calendar_id"),
92 Some(&toml::Value::String(
93 "abc@group.calendar.hooli.com".to_string()
94 ))
95 );
96 }
97
98 #[test]
99 fn parses_provider_with_no_params() {
100 let remote_config = RemoteConfig::from_toml(r#"provider = "caldav""#).unwrap();
101
102 assert_eq!(remote_config.provider_slug.to_string(), "caldav");
103 assert!(remote_config.params().is_empty());
104 }
105
106 #[test]
107 fn round_trip_preserves_provider_and_params() {
108 let mut params = RemoteConfigParams::new();
109 params.insert(
110 "hooli_account".to_string(),
111 toml::Value::String("user@hmail.com".to_string()),
112 );
113 params.insert(
114 "hooli_calendar_id".to_string(),
115 toml::Value::String("abc@group.calendar.hooli.com".to_string()),
116 );
117
118 let remote = RemoteConfig::new(ProviderSlug::from("hooli"), params);
119
120 let serialized = remote.to_toml().unwrap();
121 let parsed = RemoteConfig::from_toml(&serialized).unwrap();
122
123 assert_eq!(parsed, remote);
124 }
125
126 #[test]
127 fn account_identifier_returns_provider_account_field() {
128 let toml_str = r#"
129provider = "hooli"
130hooli_account = "user@hmail.com"
131"#;
132
133 let remote_config = RemoteConfig::from_toml(toml_str).unwrap();
134
135 assert_eq!(remote_config.account_identifier(), Some("user@hmail.com"));
136 }
137
138 #[test]
139 fn account_identifier_returns_none_when_missing() {
140 let remote_config = RemoteConfig::from_toml(r#"provider = "hooli""#).unwrap();
141
142 assert_eq!(remote_config.account_identifier(), None);
143 }
144
145 #[test]
146 fn account_email_prefers_provider_email_field() {
147 let toml_str = r#"
148provider = "caldav"
149caldav_account = "AB12345@sync.infomaniak.com"
150caldav_email = "alice@example.com"
151"#;
152
153 let remote_config = RemoteConfig::from_toml(toml_str).unwrap();
154
155 assert_eq!(remote_config.account_email(), Some("alice@example.com"));
156 }
157
158 #[test]
159 fn account_email_falls_back_to_account_identifier() {
160 let toml_str = r#"
161provider = "hooli"
162hooli_account = "user@hmail.com"
163"#;
164
165 let remote_config = RemoteConfig::from_toml(toml_str).unwrap();
166
167 assert_eq!(remote_config.account_email(), Some("user@hmail.com"));
168 }
169
170 #[test]
171 fn account_email_ignores_non_email_identifier() {
172 let toml_str = r#"
173provider = "hooli"
174hooli_account = "12345"
175"#;
176
177 let remote_config = RemoteConfig::from_toml(toml_str).unwrap();
178
179 assert_eq!(remote_config.account_email(), None);
180 }
181
182 #[test]
183 fn missing_provider_errors() {
184 let result = RemoteConfig::from_toml(r#"hooli_account = "user@hmail.com""#);
185
186 assert!(result.is_err());
187 }
188}