polyphony_types/schema/auth.rs
1use crate::errors::FieldFormatError;
2use regex::Regex;
3use serde::{Deserialize, Serialize};
4
5/**
6A struct that represents a well-formed email address.
7 */
8#[derive(Clone, PartialEq, Eq, Debug)]
9pub struct AuthEmail {
10 pub email: String,
11}
12
13impl AuthEmail {
14 /**
15 Returns a new [`Result<AuthEmail, FieldFormatError>`].
16 ## Arguments
17 The email address you want to validate.
18 ## Errors
19 You will receive a [`FieldFormatError`], if:
20 - The email address is not in a valid format.
21
22 */
23 pub fn new(email: String) -> Result<AuthEmail, FieldFormatError> {
24 let regex = Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap();
25 if !regex.is_match(email.as_str()) {
26 return Err(FieldFormatError::EmailError);
27 }
28 Ok(AuthEmail { email })
29 }
30}
31
32/**
33A struct that represents a well-formed username.
34## Arguments
35Please use new() to create a new instance of this struct.
36## Errors
37You will receive a [`FieldFormatError`], if:
38- The username is not between 2 and 32 characters.
39 */
40#[derive(Clone, PartialEq, Eq, Debug)]
41pub struct AuthUsername {
42 pub username: String,
43}
44
45impl AuthUsername {
46 /**
47 Returns a new [`Result<AuthUsername, FieldFormatError>`].
48 ## Arguments
49 The username you want to validate.
50 ## Errors
51 You will receive a [`FieldFormatError`], if:
52 - The username is not between 2 and 32 characters.
53 */
54 pub fn new(username: String) -> Result<AuthUsername, FieldFormatError> {
55 if username.len() < 2 || username.len() > 32 {
56 Err(FieldFormatError::UsernameError)
57 } else {
58 Ok(AuthUsername { username })
59 }
60 }
61}
62
63/**
64A struct that represents a well-formed password.
65## Arguments
66Please use new() to create a new instance of this struct.
67## Errors
68You will receive a [`FieldFormatError`], if:
69- The password is not between 1 and 72 characters.
70 */
71#[derive(Clone, PartialEq, Eq, Debug)]
72pub struct AuthPassword {
73 pub password: String,
74}
75
76impl AuthPassword {
77 /**
78 Returns a new [`Result<AuthPassword, FieldFormatError>`].
79 ## Arguments
80 The password you want to validate.
81 ## Errors
82 You will receive a [`FieldFormatError`], if:
83 - The password is not between 1 and 72 characters.
84 */
85 pub fn new(password: String) -> Result<AuthPassword, FieldFormatError> {
86 if password.is_empty() || password.len() > 72 {
87 Err(FieldFormatError::PasswordError)
88 } else {
89 Ok(AuthPassword { password })
90 }
91 }
92}
93
94/**
95A struct that represents a well-formed register request.
96## Arguments
97Please use new() to create a new instance of this struct.
98## Errors
99You will receive a [`FieldFormatError`], if:
100- The username is not between 2 and 32 characters.
101- The password is not between 1 and 72 characters.
102 */
103
104#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
105#[serde(rename_all = "snake_case")]
106pub struct RegisterSchema {
107 username: String,
108 password: Option<String>,
109 consent: bool,
110 email: Option<String>,
111 fingerprint: Option<String>,
112 invite: Option<String>,
113 date_of_birth: Option<String>,
114 gift_code_sku_id: Option<String>,
115 captcha_key: Option<String>,
116 promotional_email_opt_in: Option<bool>,
117}
118
119impl RegisterSchema {
120 /**
121 Returns a new [`Result<RegisterSchema, FieldFormatError>`].
122 ## Arguments
123 All but "String::username" and "bool::consent" are optional.
124
125 ## Errors
126 You will receive a [`FieldFormatError`], if:
127 - The username is less than 2 or more than 32 characters in length
128 - You supply a `password` which is less than 1 or more than 72 characters in length.
129
130 These constraints have been defined [in the Spacebar-API](https://docs.spacebar.chat/routes/)
131 */
132 pub fn new(
133 username: String,
134 password: Option<String>,
135 consent: bool,
136 email: Option<String>,
137 fingerprint: Option<String>,
138 invite: Option<String>,
139 date_of_birth: Option<String>,
140 gift_code_sku_id: Option<String>,
141 captcha_key: Option<String>,
142 promotional_email_opt_in: Option<bool>,
143 ) -> Result<RegisterSchema, FieldFormatError> {
144 let username = AuthUsername::new(username)?.username;
145
146 let email = if let Some(email) = email {
147 Some(AuthEmail::new(email)?.email)
148 } else {
149 None
150 };
151
152 let password = if let Some(password) = password {
153 Some(AuthPassword::new(password)?.password)
154 } else {
155 None
156 };
157
158 if !consent {
159 return Err(FieldFormatError::ConsentError);
160 }
161
162 Ok(RegisterSchema {
163 username,
164 password,
165 consent,
166 email,
167 fingerprint,
168 invite,
169 date_of_birth,
170 gift_code_sku_id,
171 captcha_key,
172 promotional_email_opt_in,
173 })
174 }
175}
176
177/**
178A struct that represents a well-formed login request.
179## Arguments
180Please use new() to create a new instance of this struct.
181## Errors
182You will receive a [`FieldFormatError`], if:
183- The username is not between 2 and 32 characters.
184- The password is not between 1 and 72 characters.
185 */
186#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
187#[serde(rename_all = "snake_case")]
188pub struct LoginSchema {
189 pub login: String,
190 pub password: String,
191 pub undelete: Option<bool>,
192 pub captcha_key: Option<String>,
193 pub login_source: Option<String>,
194 pub gift_code_sku_id: Option<String>,
195}
196
197impl LoginSchema {
198 /**
199 Returns a new [`Result<LoginSchema, FieldFormatError>`].
200 ## Arguments
201 login: The username you want to login with.
202 password: The password you want to login with.
203 undelete: Honestly no idea what this is for.
204 captcha_key: The captcha key you want to login with.
205 login_source: The login source.
206 gift_code_sku_id: The gift code sku id.
207 ## Errors
208 You will receive a [`FieldFormatError`], if:
209 - The username is less than 2 or more than 32 characters in length
210 */
211 pub fn new(
212 login: String,
213 password: String,
214 undelete: Option<bool>,
215 captcha_key: Option<String>,
216 login_source: Option<String>,
217 gift_code_sku_id: Option<String>,
218 ) -> Result<LoginSchema, FieldFormatError> {
219 let login = AuthUsername::new(login)?.username;
220 let password = AuthPassword::new(password)?.password;
221
222 Ok(LoginSchema {
223 login,
224 password,
225 undelete,
226 captcha_key,
227 login_source,
228 gift_code_sku_id,
229 })
230 }
231}
232
233#[derive(Debug, Serialize, Deserialize)]
234#[serde(rename_all = "snake_case")]
235pub struct TotpSchema {
236 code: String,
237 ticket: String,
238 gift_code_sku_id: Option<String>,
239 login_source: Option<String>,
240}