junobuild_auth/profile/
impls.rs1use 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}