junobuild_auth/profile/
impls.rs

1use crate::profile::constants::{
2    EMAIL_MAX_LENGTH, LOCALE_MAX_LENGTH, NAME_MAX_LENGTH, SHORT_NAME_MAX_LENGTH,
3};
4use crate::profile::errors::{
5    JUNO_AUTH_ERROR_PROFILE_EMAIL_INVALID_LENGTH,
6    JUNO_AUTH_ERROR_PROFILE_FAMILY_NAME_INVALID_LENGTH,
7    JUNO_AUTH_ERROR_PROFILE_GIVEN_NAME_INVALID_LENGTH,
8    JUNO_AUTH_ERROR_PROFILE_LOCALE_INVALID_LENGTH, JUNO_AUTH_ERROR_PROFILE_NAME_INVALID_LENGTH,
9    JUNO_AUTH_ERROR_PROFILE_PICTURE_INVALID_SCHEME, JUNO_AUTH_ERROR_PROFILE_PICTURE_INVALID_URL,
10};
11use crate::profile::types::{OpenIdProfile, Validated};
12use url::Url;
13
14impl<T: OpenIdProfile> Validated for T {
15    fn validate(&self) -> Result<(), String> {
16        if let Some(email) = self.email().as_ref() {
17            if email.len() > EMAIL_MAX_LENGTH {
18                return Err(JUNO_AUTH_ERROR_PROFILE_EMAIL_INVALID_LENGTH.to_string());
19            }
20        }
21
22        if let Some(name) = self.name().as_ref() {
23            if name.chars().count() > NAME_MAX_LENGTH {
24                return Err(JUNO_AUTH_ERROR_PROFILE_NAME_INVALID_LENGTH.to_string());
25            }
26        }
27
28        if let Some(given_name) = self.given_name().as_ref() {
29            if given_name.chars().count() > SHORT_NAME_MAX_LENGTH {
30                return Err(JUNO_AUTH_ERROR_PROFILE_GIVEN_NAME_INVALID_LENGTH.to_string());
31            }
32        }
33
34        if let Some(family_name) = self.family_name().as_ref() {
35            if family_name.chars().count() > SHORT_NAME_MAX_LENGTH {
36                return Err(JUNO_AUTH_ERROR_PROFILE_FAMILY_NAME_INVALID_LENGTH.to_string());
37            }
38        }
39
40        if let Some(locale) = self.locale().as_ref() {
41            if locale.chars().count() > LOCALE_MAX_LENGTH {
42                return Err(JUNO_AUTH_ERROR_PROFILE_LOCALE_INVALID_LENGTH.to_string());
43            }
44        }
45
46        if let Some(picture) = self.picture().as_ref() {
47            let url = Url::parse(picture)
48                .map_err(|_| JUNO_AUTH_ERROR_PROFILE_PICTURE_INVALID_URL.to_string())?;
49
50            if url.scheme() != "https" {
51                return Err(JUNO_AUTH_ERROR_PROFILE_PICTURE_INVALID_SCHEME.to_string());
52            }
53        }
54
55        Ok(())
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    pub struct OpenIdDataTest {
64        pub email: Option<String>,
65        pub name: Option<String>,
66        pub given_name: Option<String>,
67        pub family_name: Option<String>,
68        pub picture: Option<String>,
69        pub locale: Option<String>,
70    }
71
72    impl OpenIdProfile for OpenIdDataTest {
73        fn email(&self) -> Option<&str> {
74            self.email.as_deref()
75        }
76        fn name(&self) -> Option<&str> {
77            self.name.as_deref()
78        }
79        fn given_name(&self) -> Option<&str> {
80            self.given_name.as_deref()
81        }
82        fn family_name(&self) -> Option<&str> {
83            self.family_name.as_deref()
84        }
85        fn picture(&self) -> Option<&str> {
86            self.picture.as_deref()
87        }
88        fn locale(&self) -> Option<&str> {
89            self.locale.as_deref()
90        }
91    }
92
93    #[test]
94    fn test_google_valid_data() {
95        let data = OpenIdDataTest {
96            email: Some("user@example.com".to_string()),
97            name: Some("Ada Lovelace".to_string()),
98            given_name: Some("Ada".to_string()),
99            family_name: Some("Lovelace".to_string()),
100            picture: Some("https://example.com/avatar.png".to_string()),
101            locale: Some("en".to_string()),
102        };
103
104        assert!(data.validate().is_ok());
105    }
106
107    #[test]
108    fn test_google_invalid_email_length() {
109        let long_email = "a".repeat(EMAIL_MAX_LENGTH + 1);
110        let data = OpenIdDataTest {
111            email: Some(long_email),
112            name: None,
113            given_name: None,
114            family_name: None,
115            picture: None,
116            locale: None,
117        };
118        assert!(data.validate().is_err());
119    }
120
121    #[test]
122    fn test_google_invalid_picture_url() {
123        let data = OpenIdDataTest {
124            email: None,
125            name: None,
126            given_name: None,
127            family_name: None,
128            picture: Some("not-a-valid-url".to_string()),
129            locale: None,
130        };
131        assert!(data.validate().is_err());
132    }
133
134    #[test]
135    fn test_google_invalid_picture_scheme() {
136        let data = OpenIdDataTest {
137            email: None,
138            name: None,
139            given_name: None,
140            family_name: None,
141            picture: Some("http://example.com/avatar.png".to_string()),
142            locale: None,
143        };
144        assert!(data.validate().is_err());
145    }
146
147    #[test]
148    fn test_google_invalid_name_length() {
149        let data = OpenIdDataTest {
150            email: None,
151            name: Some("a".repeat(NAME_MAX_LENGTH + 1)),
152            given_name: None,
153            family_name: None,
154            picture: None,
155            locale: None,
156        };
157        assert!(data.validate().is_err());
158    }
159
160    #[test]
161    fn test_google_invalid_given_name_length() {
162        let data = OpenIdDataTest {
163            email: None,
164            name: None,
165            given_name: Some("a".repeat(SHORT_NAME_MAX_LENGTH + 1)),
166            family_name: None,
167            picture: None,
168            locale: None,
169        };
170        assert!(data.validate().is_err());
171    }
172
173    #[test]
174    fn test_google_invalid_family_name_length() {
175        let data = OpenIdDataTest {
176            email: None,
177            name: None,
178            given_name: None,
179            family_name: Some("a".repeat(SHORT_NAME_MAX_LENGTH + 1)),
180            picture: None,
181            locale: None,
182        };
183        assert!(data.validate().is_err());
184    }
185
186    #[test]
187    fn test_google_invalid_locale_length() {
188        let data = OpenIdDataTest {
189            email: None,
190            name: None,
191            given_name: None,
192            family_name: None,
193            picture: None,
194            locale: Some("a".repeat(LOCALE_MAX_LENGTH + 1)),
195        };
196        assert!(data.validate().is_err());
197    }
198}