Skip to main content

wekan_cli/command_result/admin/
login_providers.rs

1use crate::client::admin::login_providers as wire;
2use serde::Serialize;
3
4#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
5pub struct ConfigSource<T> {
6    pub source: String,
7    pub value: Option<T>,
8}
9
10impl<T, U: From<T>> From<wire::ConfigSource<T>> for ConfigSource<U> {
11    fn from(source: wire::ConfigSource<T>) -> Self {
12        Self {
13            source: source.source,
14            value: source.value.map(Into::into),
15        }
16    }
17}
18
19#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
20#[serde(untagged)]
21pub enum BooleanConfigValue {
22    Text(String),
23    Boolean(bool),
24}
25
26impl From<wire::BooleanConfigValue> for BooleanConfigValue {
27    fn from(value: wire::BooleanConfigValue) -> Self {
28        match value {
29            wire::BooleanConfigValue::Text(value) => Self::Text(value),
30            wire::BooleanConfigValue::Boolean(value) => Self::Boolean(value),
31        }
32    }
33}
34
35#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
36pub struct SecretConfigSource {
37    pub source: String,
38    pub has_value: bool,
39}
40
41impl From<wire::SecretConfigSource> for SecretConfigSource {
42    fn from(source: wire::SecretConfigSource) -> Self {
43        Self {
44            source: source.source,
45            has_value: source.has_value,
46        }
47    }
48}
49
50#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
51pub struct OauthProviderSource {
52    pub enabled: ConfigSource<BooleanConfigValue>,
53    pub id: ConfigSource<String>,
54    pub secret: SecretConfigSource,
55}
56
57impl From<wire::OauthProviderSource> for OauthProviderSource {
58    fn from(provider: wire::OauthProviderSource) -> Self {
59        Self {
60            enabled: provider.enabled.into(),
61            id: provider.id.into(),
62            secret: provider.secret.into(),
63        }
64    }
65}
66
67#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
68pub struct OauthProviderSources {
69    pub google: OauthProviderSource,
70    pub github: OauthProviderSource,
71    pub facebook: OauthProviderSource,
72    pub twitter: OauthProviderSource,
73    #[serde(rename = "meteor-developer")]
74    pub meteor_developer: OauthProviderSource,
75    pub weibo: OauthProviderSource,
76    pub meetup: OauthProviderSource,
77}
78
79impl From<wire::OauthProviderSources> for OauthProviderSources {
80    fn from(providers: wire::OauthProviderSources) -> Self {
81        Self {
82            google: providers.google.into(),
83            github: providers.github.into(),
84            facebook: providers.facebook.into(),
85            twitter: providers.twitter.into(),
86            meteor_developer: providers.meteor_developer.into(),
87            weibo: providers.weibo.into(),
88            meetup: providers.meetup.into(),
89        }
90    }
91}
92
93#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
94pub struct OauthProviderSettings {
95    pub providers: OauthProviderSources,
96    pub login_style: ConfigSource<String>,
97    pub merge_existing_users: ConfigSource<BooleanConfigValue>,
98    pub allowed_email_domains: ConfigSource<String>,
99    pub passwordless: ConfigSource<BooleanConfigValue>,
100}
101
102impl From<wire::OauthProviderSettings> for OauthProviderSettings {
103    fn from(settings: wire::OauthProviderSettings) -> Self {
104        Self {
105            providers: settings.providers.into(),
106            login_style: settings.login_style.into(),
107            merge_existing_users: settings.merge_existing_users.into(),
108            allowed_email_domains: settings.allowed_email_domains.into(),
109            passwordless: settings.passwordless.into(),
110        }
111    }
112}
113
114#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
115pub struct PasswordlessSettings {
116    pub passwordless: ConfigSource<BooleanConfigValue>,
117}
118
119impl From<wire::PasswordlessSettings> for PasswordlessSettings {
120    fn from(settings: wire::PasswordlessSettings) -> Self {
121        Self {
122            passwordless: settings.passwordless.into(),
123        }
124    }
125}
126
127#[cfg(test)]
128mod tests {
129    use super::*;
130    use serde_json::json;
131
132    #[test]
133    fn provider_results_preserve_keys_sources_nulls_and_boolean_representations() {
134        let provider = json!({
135            "enabled":{"source":"env","value":"false"},
136            "id":{"source":"default"},
137            "secret":{"source":"database","hasValue":true}
138        });
139        let providers: serde_json::Map<_, _> = [
140            "google",
141            "github",
142            "facebook",
143            "twitter",
144            "meteor-developer",
145            "weibo",
146            "meetup",
147        ]
148        .into_iter()
149        .map(|key| (key.to_owned(), provider.clone()))
150        .collect();
151        let response: wire::OauthProviderSettings = serde_json::from_value(json!({
152            "providers":providers,
153            "loginStyle":{"source":"database","value":"popup"},
154            "mergeExistingUsers":{"source":"database","value":true},
155            "allowedEmailDomains":{"source":"default","value":null},
156            "passwordless":{"source":"env","value":"true"}
157        }))
158        .unwrap();
159        let stable_provider = json!({
160            "enabled":{"source":"env","value":"false"},
161            "id":{"source":"default","value":null},
162            "secret":{"source":"database","has_value":true}
163        });
164        let stable_providers: serde_json::Map<_, _> = [
165            "google",
166            "github",
167            "facebook",
168            "twitter",
169            "meteor-developer",
170            "weibo",
171            "meetup",
172        ]
173        .into_iter()
174        .map(|key| (key.to_owned(), stable_provider.clone()))
175        .collect();
176        assert_eq!(
177            serde_json::to_value(OauthProviderSettings::from(response)).unwrap(),
178            json!({
179                "providers":stable_providers,
180                "login_style":{"source":"database","value":"popup"},
181                "merge_existing_users":{"source":"database","value":true},
182                "allowed_email_domains":{"source":"default","value":null},
183                "passwordless":{"source":"env","value":"true"}
184            })
185        );
186        for value in [json!(false), json!("false"), json!(null)] {
187            let response: wire::PasswordlessSettings = serde_json::from_value(json!({
188                "passwordless":{"source":"default","value":value}
189            }))
190            .unwrap();
191            assert_eq!(
192                serde_json::to_value(PasswordlessSettings::from(response)).unwrap(),
193                json!({"passwordless":{"source":"default","value":value}})
194            );
195        }
196    }
197}