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}