Cargo fmt & extra token daos

This commit is contained in:
Franklin 2023-09-20 20:01:17 -04:00
parent d3ec69b3b5
commit 67a990de1f
28 changed files with 279 additions and 157 deletions

View File

@ -1,22 +1,34 @@
use chrono::Utc;
use sqlx::{Error, PgPool};
use crate::domain::credential::Credential; use crate::domain::credential::Credential;
use crate::dto::credential::CredentialDto; use crate::dto::credential::CredentialDto;
use chrono::Utc;
use sqlx::{Error, PgPool};
pub async fn insert_credentials(conn: &PgPool, credentials: Vec<CredentialDto>, user_id: &i32) -> Result<Vec<Credential>, Error> { pub async fn insert_credentials(
conn: &PgPool,
credentials: Vec<CredentialDto>,
user_id: &i32,
) -> Result<Vec<Credential>, Error> {
let insert_query_base = r#"INSERT INTO credential let insert_query_base = r#"INSERT INTO credential
(user_id, credential_type, credential, validated, time_created, last_updated) (user_id, credential_type, credential, validated, time_created, last_updated)
VALUES ($1, $2, $3, $4, $5, $5) RETURNING user_id, credential_type as "credential_type: _", credential, validated, time_created, last_updated"#; VALUES ($1, $2, $3, $4, $5, $5) RETURNING user_id, credential_type as "credential_type: _", credential, validated, time_created, last_updated"#;
let mut persisted_credentials = Vec::new(); let mut persisted_credentials = Vec::new();
for credential_dto in credentials { for credential_dto in credentials {
let persisted_credential: Credential = sqlx::query_as(insert_query_base) let persisted_credential: Credential = sqlx::query_as(insert_query_base)
.bind(user_id).bind(credential_dto.credential_type).bind(credential_dto.credential).bind(false).bind(Utc::now()) .bind(user_id)
.fetch_one(conn).await?; .bind(credential_dto.credential_type)
.bind(credential_dto.credential)
.bind(false)
.bind(Utc::now())
.fetch_one(conn)
.await?;
persisted_credentials.push(persisted_credential); persisted_credentials.push(persisted_credential);
} }
Ok(persisted_credentials) Ok(persisted_credentials)
} }
pub async fn fetch_user_credentials(conn: &PgPool, user_id: &i32) -> Result<Vec<Credential>, Error> { pub async fn fetch_user_credentials(
conn: &PgPool,
user_id: &i32,
) -> Result<Vec<Credential>, Error> {
sqlx::query_as(r#"SELECT user_id, credential_type as "credential_type: _", credential, validated, time_created, last_updated FROM credential WHERE user_id = $1 "#).bind(user_id).fetch_all(conn).await sqlx::query_as(r#"SELECT user_id, credential_type as "credential_type: _", credential, validated, time_created, last_updated FROM credential WHERE user_id = $1 "#).bind(user_id).fetch_all(conn).await
} }

View File

@ -1,4 +1,4 @@
pub mod pg_queries;
pub mod user;
pub mod credential; pub mod credential;
pub mod pg_queries;
pub mod token; pub mod token;
pub mod user;

View File

@ -0,0 +1 @@

View File

@ -1,6 +1,6 @@
use crate::domain::token::Token;
use chrono::Utc; use chrono::Utc;
use sqlx::{Error, PgPool}; use sqlx::{Error, PgPool};
use crate::domain::token::Token;
pub async fn insert_token(conn: &PgPool, token: Token) -> Result<Token, Error> { pub async fn insert_token(conn: &PgPool, token: Token) -> Result<Token, Error> {
sqlx::query_as(r#"INSERT INTO token ( sqlx::query_as(r#"INSERT INTO token (
@ -9,13 +9,40 @@ pub async fn insert_token(conn: &PgPool, token: Token) -> Result<Token, Error> {
.fetch_one(conn).await .fetch_one(conn).await
} }
pub async fn update_token(conn: &PgPool, token_id: &i32, auth_token: String) -> Result<Token, Error> { pub async fn update_token(
sqlx::query_as(r#"UPDATE token set conn: &PgPool,
auth_token = $2, last_updated token_id: &i32,
WHERE id = $1 RETURNING *;"#) refresh_token: String,
.bind(token_id).bind(auth_token).bind(Utc::now()) new_auth_token: String,
.fetch_one(conn).await ) -> Result<Token, Error> {
sqlx::query_as(
r#"UPDATE token set
auth_token = $3, last_updated = $4
WHERE id = $1 AND refresh_token = $2 RETURNING *;"#,
)
.bind(token_id)
.bind(refresh_token)
.bind(new_auth_token)
.bind(Utc::now())
.fetch_one(conn)
.await
}
pub async fn remove_token(conn: &PgPool, token_id: &i32) -> Result<Option<Token>, Error> {
sqlx::query_as(r#"DELETE FROM token WHERE id = $1 RETURNING *;"#)
.bind(token_id)
.fetch_optional(conn)
.await
}
pub async fn validate_user_token(
conn: &PgPool,
user_id: &i32,
auth_token: String,
) -> Result<Option<Token>, Error> {
sqlx::query_as(r#"SELECT * FROM token where user_id = $1 AND auth_token = $2;"#)
.bind(user_id)
.bind(auth_token)
.fetch_optional(conn)
.await
} }
// TODO: add validate_user token (user_id, auth_token)
// Update user token (refresh_token, user_id)
// Delete user token (token_id)

View File

@ -1,40 +1,55 @@
use sqlx::{PgPool, query_as, query_as_with};
use crate::domain::user::User; use crate::domain::user::User;
use sqlx::{query_as, query_as_with, PgPool};
pub async fn insert_user(conn: &PgPool, user: User) -> Result<User, sqlx::Error> { pub async fn insert_user(conn: &PgPool, user: User) -> Result<User, sqlx::Error> {
sqlx::query_as(r#" sqlx::query_as(
r#"
INSERT INTO user (name, password, salt, time_created, last_updated) INSERT INTO user (name, password, salt, time_created, last_updated)
VALUES ($1, $2, $3, $4, $4) RETURNING *; VALUES ($1, $2, $3, $4, $4) RETURNING *;
"#) "#,
.bind(user.name).bind(user.password).bind(user.salt).bind(user.time_created) )
.bind(user.name)
.bind(user.password)
.bind(user.salt)
.bind(user.time_created)
.fetch_one(conn) .fetch_one(conn)
.await .await
} }
pub async fn get_user_with_id(conn: &PgPool, user_id: &i32) -> Result<Option<User>, sqlx::Error> { pub async fn get_user_with_id(conn: &PgPool, user_id: &i32) -> Result<Option<User>, sqlx::Error> {
sqlx::query_as(r#" sqlx::query_as(
r#"
SELECT * FROM user where id = $1; SELECT * FROM user where id = $1;
"#, ) "#,
)
.bind(user_id) .bind(user_id)
.fetch_optional(conn) .fetch_optional(conn)
.await .await
} }
pub async fn update_user(conn: &PgPool, user: User) -> Result<User, sqlx::Error> { pub async fn update_user(conn: &PgPool, user: User) -> Result<User, sqlx::Error> {
sqlx::query_as(r#" sqlx::query_as(
r#"
UPDATE user SET UPDATE user SET
name = $2, password = $3, salt = $4, last_updated = $5 name = $2, password = $3, salt = $4, last_updated = $5
WHERE id = $1 RETURNING *; WHERE id = $1 RETURNING *;
"#, ) "#,
.bind(user.id).bind(user.name).bind(user.password).bind(user.salt).bind(user.last_updated) )
.bind(user.id)
.bind(user.name)
.bind(user.password)
.bind(user.salt)
.bind(user.last_updated)
.fetch_one(conn) .fetch_one(conn)
.await .await
} }
pub async fn delete_user(conn: &PgPool, user_id: &i32) -> Result<Option<User>, sqlx::Error> { pub async fn delete_user(conn: &PgPool, user_id: &i32) -> Result<Option<User>, sqlx::Error> {
sqlx::query_as(r#" sqlx::query_as(
r#"
DELETE FROM user where id = $1 RETURNING *; DELETE FROM user where id = $1 RETURNING *;
"#, ) "#,
)
.bind(user_id) .bind(user_id)
.fetch_optional(conn) .fetch_optional(conn)
.await .await

View File

@ -1,8 +1,10 @@
use crate::resources::variable_lengths::{
MAX_EMAIL_LENGTH, MAX_NAME_LENGTH, MAX_PHONE_NUMBER_LENGTH, MAX_USERNAME_LENGTH,
MIN_EMAIL_LENGTH, MIN_PHONE_NUMBER_LENGTH, MIN_USERNAME_LENGTH,
};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
use sqlx::FromRow; use sqlx::FromRow;
use crate::resources::variable_lengths::{MAX_EMAIL_LENGTH, MAX_NAME_LENGTH, MAX_PHONE_NUMBER_LENGTH, MAX_USERNAME_LENGTH, MIN_EMAIL_LENGTH, MIN_PHONE_NUMBER_LENGTH, MIN_USERNAME_LENGTH};
/// Is used in the user struct to signal what type of credential will be used in the credential Column. /// Is used in the user struct to signal what type of credential will be used in the credential Column.
/// Defaults to email. /// Defaults to email.
@ -15,7 +17,9 @@ pub enum CredentialType {
} }
/// Can only have one per user per cred_type /// Can only have one per user per cred_type
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, FromRow)] #[derive(
Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, FromRow,
)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Credential { pub struct Credential {
pub user_id: i32, pub user_id: i32,

View File

@ -1,6 +1,5 @@
use std::fmt::Display; use std::fmt::Display;
/// Used to return a simple error from FromStr implementations /// Used to return a simple error from FromStr implementations
#[derive(Debug)] #[derive(Debug)]
pub struct FromStrError; pub struct FromStrError;

View File

@ -1,6 +1,11 @@
use std::{str::FromStr, fmt::Display}; use std::{fmt::Display, str::FromStr};
use sqlx::{Postgres, postgres::{PgValueRef, PgArgumentBuffer, PgTypeInfo}, error::BoxDynError, encode::IsNull}; use sqlx::{
encode::IsNull,
error::BoxDynError,
postgres::{PgArgumentBuffer, PgTypeInfo, PgValueRef},
Postgres,
};
use crate::domain::{credential::CredentialType, error::FromStrError}; use crate::domain::{credential::CredentialType, error::FromStrError};
@ -12,7 +17,7 @@ impl FromStr for CredentialType {
"PhoneNumber" => Ok(Self::PhoneNumber), "PhoneNumber" => Ok(Self::PhoneNumber),
"Email" => Ok(Self::Email), "Email" => Ok(Self::Email),
"Username" => Ok(Self::Username), "Username" => Ok(Self::Username),
_ => Err(FromStrError) _ => Err(FromStrError),
} }
} }
} }

View File

@ -1,5 +1,5 @@
pub mod credential; pub mod credential;
pub mod error;
pub mod impls;
pub mod token; pub mod token;
pub mod user; pub mod user;
pub mod impls;
pub mod error;

View File

@ -1,10 +1,10 @@
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
use sqlx::FromRow; use sqlx::FromRow;
#[derive(
#[derive(FromRow)] FromRow, Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord,
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] )]
pub struct Token { pub struct Token {
#[serde(skip_serializing, skip_deserializing)] #[serde(skip_serializing, skip_deserializing)]
pub id: i32, pub id: i32,

View File

@ -1,9 +1,10 @@
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize}; use serde::{Deserialize, Serialize};
use sqlx::FromRow; use sqlx::FromRow;
#[derive(FromRow)] #[derive(
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)] FromRow, Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord,
)]
pub struct User { pub struct User {
pub id: i32, pub id: i32,
pub name: String, pub name: String,

View File

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::domain::credential::CredentialType; use crate::domain::credential::CredentialType;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]

View File

@ -1,6 +1,6 @@
pub struct HashResult { pub struct HashResult {
pub salt: String, pub salt: String,
pub hash: String pub hash: String,
} }
impl HashResult { impl HashResult {

View File

@ -1,4 +1,4 @@
pub mod users;
pub mod credential; pub mod credential;
pub mod token;
pub mod hash_result; pub mod hash_result;
pub mod token;
pub mod users;

View File

@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};
use crate::domain::credential::CredentialType; use crate::domain::credential::CredentialType;
use crate::dto::credential::CredentialDto; use crate::dto::credential::CredentialDto;
use serde::{Deserialize, Serialize};
/// Used for logging in when you don't have a token. /// Used for logging in when you don't have a token.
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]

View File

@ -1,7 +1,7 @@
pub mod dao; pub mod dao;
pub mod service;
pub mod utils;
pub mod domain; pub mod domain;
pub mod dto; pub mod dto;
pub mod validation;
pub mod resources; pub mod resources;
pub mod service;
pub mod utils;
pub mod validation;

View File

@ -2,28 +2,61 @@
// Template: pub const ERROR_KEY_OR_NAME: (&str, &str) = ("ERROR.KEY", "ERROR VALUE"); // Template: pub const ERROR_KEY_OR_NAME: (&str, &str) = ("ERROR.KEY", "ERROR VALUE");
pub type ErrorResource<'a> = (&'a str, &'a str); pub type ErrorResource<'a> = (&'a str, &'a str);
pub const ERROR_INVALID_EMAIL: (&str, &str) = ("ERROR.INVALID_EMAIL", "Invalid email. Needs to be at least 4 characters, at most 254 and correctly formatted."); pub const ERROR_INVALID_EMAIL: (&str, &str) = (
"ERROR.INVALID_EMAIL",
"Invalid email. Needs to be at least 4 characters, at most 254 and correctly formatted.",
);
pub const ERROR_INVALID_PHONE_NUMBER: (&str, &str) = ("ERROR.INVALID_PHONE_NUMBER", "Invalid Phone number. Needs to be 10 characters."); pub const ERROR_INVALID_PHONE_NUMBER: (&str, &str) = (
"ERROR.INVALID_PHONE_NUMBER",
"Invalid Phone number. Needs to be 10 characters.",
);
pub const ERROR_INVALID_USERNAME: (&str, &str) = ("ERROR.INVALID_USERNAME", "Invalid Username. "); pub const ERROR_INVALID_USERNAME: (&str, &str) = ("ERROR.INVALID_USERNAME", "Invalid Username. ");
pub const ERROR_INVALID_NAME: (&str, &str) = ("ERROR.INVALID_NAME", "Invalid name. Names should have at least 4 characters in length and at most 254."); pub const ERROR_INVALID_NAME: (&str, &str) = (
"ERROR.INVALID_NAME",
"Invalid name. Names should have at least 4 characters in length and at most 254.",
);
pub const ERROR_INVALID_PASSWORD: (&str, &str) = ("ERROR.INVALID_PASSWORD", "Invalid password. Password should have at least 8 characters and at most 128."); pub const ERROR_INVALID_PASSWORD: (&str, &str) = (
"ERROR.INVALID_PASSWORD",
"Invalid password. Password should have at least 8 characters and at most 128.",
);
pub const ERROR_USER_ALREADY_EXISTS: (&str, &str) = ("ERROR.USER_ALREADY_EXISTS", "A user with that email already exists."); pub const ERROR_USER_ALREADY_EXISTS: (&str, &str) = (
"ERROR.USER_ALREADY_EXISTS",
"A user with that email already exists.",
);
pub const ERROR_USER_DOES_NOT_EXIST: (&str, &str) = ("ERROR.USER_DOES_NOT_EXIST", "User with this email does not exist."); pub const ERROR_USER_DOES_NOT_EXIST: (&str, &str) = (
"ERROR.USER_DOES_NOT_EXIST",
"User with this email does not exist.",
);
pub const ERROR_PASSWORD_INCORRECT: (&str, &str) = ("ERROR.PASSWORD_INCORRECT", "The password you have entered is incorrect."); pub const ERROR_PASSWORD_INCORRECT: (&str, &str) = (
"ERROR.PASSWORD_INCORRECT",
"The password you have entered is incorrect.",
);
pub const ERROR_INVALID_TOKEN: (&str, &str) = ("ERROR.INVALID_TOKEN", "The token you have supplied is not formattable."); pub const ERROR_INVALID_TOKEN: (&str, &str) = (
"ERROR.INVALID_TOKEN",
"The token you have supplied is not formattable.",
);
pub const ERROR_INCORRECT_TOKEN: (&str, &str) = ("ERROR.INCORRECT_TOKEN", "The token you have supplied does not belong to this user."); pub const ERROR_INCORRECT_TOKEN: (&str, &str) = (
"ERROR.INCORRECT_TOKEN",
"The token you have supplied does not belong to this user.",
);
pub const ERROR_MISSING_TOKEN: (&str, &str) = ("ERROR.MISSING_TOKEN", "No token supplied."); pub const ERROR_MISSING_TOKEN: (&str, &str) = ("ERROR.MISSING_TOKEN", "No token supplied.");
pub const ERROR_EXPIRED_TOKEN: (&str, &str) = ("ERROR.EXPIRED_TOKEN", "The token you have supplied is expired."); pub const ERROR_EXPIRED_TOKEN: (&str, &str) = (
"ERROR.EXPIRED_TOKEN",
"The token you have supplied is expired.",
);
pub const ERROR_CREATING_TOKEN: (&str, &str) = ("ERROR.CREATING_TOKEN", "The server had an error creating the auth tokens."); pub const ERROR_CREATING_TOKEN: (&str, &str) = (
"ERROR.CREATING_TOKEN",
"The server had an error creating the auth tokens.",
);

View File

@ -1,4 +1,3 @@
pub const MIN_EMAIL_LENGTH: usize = 4; pub const MIN_EMAIL_LENGTH: usize = 4;
pub const MAX_EMAIL_LENGTH: usize = 254; pub const MAX_EMAIL_LENGTH: usize = 254;

View File

@ -1,2 +1,2 @@
mod user;
mod token; mod token;
mod user;

View File

@ -0,0 +1 @@

View File

@ -1,6 +1,5 @@
use crate::dto::users::UserRegisterPayload; use crate::dto::users::UserRegisterPayload;
pub async fn register_user(db_conn: &sqlx::PgPool, user: UserRegisterPayload) -> Result<(), ()> { pub async fn register_user(db_conn: &sqlx::PgPool, user: UserRegisterPayload) -> Result<(), ()> {
Ok(()) Ok(())
} }

View File

@ -1,8 +1,11 @@
use std::num::NonZeroU32;
use data_encoding::BASE64;
use ring::{digest, rand::{SecureRandom, SystemRandom}, pbkdf2};
use tokio::task::JoinError;
use crate::dto::hash_result::HashResult; use crate::dto::hash_result::HashResult;
use data_encoding::BASE64;
use ring::{
digest, pbkdf2,
rand::{SecureRandom, SystemRandom},
};
use std::num::NonZeroU32;
use tokio::task::JoinError;
const SALT_ROUNDS: u32 = 1000; const SALT_ROUNDS: u32 = 1000;
@ -17,17 +20,24 @@ pub async fn generate_multiple_random_token_with_rng(amount: u8) -> Result<Vec<S
let future_token = async move { let future_token = async move {
let mut token_arr = [0u8; digest::SHA512_OUTPUT_LEN]; let mut token_arr = [0u8; digest::SHA512_OUTPUT_LEN];
match cloned_rng.fill(&mut token_arr) { match cloned_rng.fill(&mut token_arr) {
Ok(()) => {BASE64.encode(&token_arr)}, //TODO: Remove this panic, make your own error and fix this Ok(()) => BASE64.encode(&token_arr), //TODO: Remove this panic, make your own error and fix this
Err(_e) => { panic!("Failed to generate random token for some reason.") } Err(_e) => {
}}; panic!("Failed to generate random token for some reason.")
}
}
};
tokens.push(tokio::spawn(future_token)); tokens.push(tokio::spawn(future_token));
} }
let all_tokens = futures_util::future::join_all(tokens).await; let all_tokens = futures_util::future::join_all(tokens).await;
let all_tokens_solved: Vec<String> = all_tokens.into_iter().map(|result| match result { let all_tokens_solved: Vec<String> = all_tokens
Ok(string) => {string}, .into_iter()
Err(_e) => {"".to_string()} .map(|result| match result {
}).rev().collect(); Ok(string) => string,
Err(_e) => "".to_string(),
})
.rev()
.collect();
Ok(all_tokens_solved) Ok(all_tokens_solved)
} }
@ -56,7 +66,6 @@ pub fn hash_password_with_existing_salt(password: &String, input_salt: &String)
} }
pub fn hash_password(password: &String) -> HashResult { pub fn hash_password(password: &String) -> HashResult {
// Get output length from a sha512 hash // Get output length from a sha512 hash
const CREDENTIAL_LEN: usize = digest::SHA512_OUTPUT_LEN; const CREDENTIAL_LEN: usize = digest::SHA512_OUTPUT_LEN;
let n_iter = NonZeroU32::new(SALT_ROUNDS).unwrap(); let n_iter = NonZeroU32::new(SALT_ROUNDS).unwrap();
@ -67,8 +76,10 @@ pub fn hash_password(password: &String) -> HashResult{
// Fill array with random-generated salt // Fill array with random-generated salt
match rng.fill(&mut salt) { match rng.fill(&mut salt) {
Ok(()) => {}, Ok(()) => {}
Err(_e) => {panic!("Failed to generate random salt for some reason.")} Err(_e) => {
panic!("Failed to generate random salt for some reason.")
}
} }
// Create empty 64-bit byte array for the hash + salt // Create empty 64-bit byte array for the hash + salt

View File

@ -1,50 +1,59 @@
use crate::{resources::{variable_lengths::{MAX_EMAIL_LENGTH, MIN_EMAIL_LENGTH, MIN_NAME_LENGTH, MAX_NAME_LENGTH, MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH}, error_messages::{ERROR_INVALID_NAME, ERROR_INVALID_EMAIL, ERROR_INVALID_PASSWORD, ERROR_INVALID_PHONE_NUMBER}}};
use crate::domain::credential::CredentialType; use crate::domain::credential::CredentialType;
use crate::dto::users::{UserLoginPayload, UserRegisterPayload}; use crate::dto::users::{UserLoginPayload, UserRegisterPayload};
use crate::resources::error_messages::{ERROR_INVALID_USERNAME, ErrorResource}; use crate::resources::error_messages::{ErrorResource, ERROR_INVALID_USERNAME};
use crate::resources::{
error_messages::{
ERROR_INVALID_EMAIL, ERROR_INVALID_NAME, ERROR_INVALID_PASSWORD, ERROR_INVALID_PHONE_NUMBER,
},
variable_lengths::{
MAX_EMAIL_LENGTH, MAX_NAME_LENGTH, MAX_PASSWORD_LENGTH, MIN_EMAIL_LENGTH, MIN_NAME_LENGTH,
MIN_PASSWORD_LENGTH,
},
};
fn validate_user_email(email: &String) -> bool { fn validate_user_email(email: &String) -> bool {
email.len() >= MIN_EMAIL_LENGTH.into() && email.len() >= MIN_EMAIL_LENGTH.into()
email.len() <= MAX_EMAIL_LENGTH.into() && && email.len() <= MAX_EMAIL_LENGTH.into()
email.contains('@') && && email.contains('@')
email.contains('.') && email.contains('.')
} }
fn validate_user_phone_number(email: &String) -> bool { fn validate_user_phone_number(email: &String) -> bool {
email.len() >= CredentialType::get_max_length(&CredentialType::PhoneNumber) && email.len() >= CredentialType::get_max_length(&CredentialType::PhoneNumber)
email.len() <= CredentialType::get_min_length(&CredentialType::PhoneNumber) && email.len() <= CredentialType::get_min_length(&CredentialType::PhoneNumber)
} }
fn validate_user_username(username: &String) -> bool { fn validate_user_username(username: &String) -> bool {
username.len() >= CredentialType::get_max_length(&CredentialType::PhoneNumber) && username.len() >= CredentialType::get_max_length(&CredentialType::PhoneNumber)
username.len() <= CredentialType::get_min_length(&CredentialType::PhoneNumber) && username.len() <= CredentialType::get_min_length(&CredentialType::PhoneNumber)
} }
fn validate_user_name(name: &String) -> bool { fn validate_user_name(name: &String) -> bool {
name.len() >= MIN_NAME_LENGTH.into() && name.len() >= MIN_NAME_LENGTH.into() && name.len() <= MAX_NAME_LENGTH.into()
name.len() <= MAX_NAME_LENGTH.into()
} }
fn validate_user_password(password: &String) -> bool { fn validate_user_password(password: &String) -> bool {
password.len() >= MIN_PASSWORD_LENGTH.into() && password.len() >= MIN_PASSWORD_LENGTH.into() && password.len() <= MAX_PASSWORD_LENGTH.into()
password.len() <= MAX_PASSWORD_LENGTH.into()
} }
pub fn validate_user_for_creation(user: &UserRegisterPayload, error_resources: &mut Vec<ErrorResource>){ pub fn validate_user_for_creation(
for credential_dto in user.credentials { user: &UserRegisterPayload,
error_resources: &mut Vec<ErrorResource>,
) {
for credential_dto in user.credentials.iter() {
match credential_dto.credential_type { match credential_dto.credential_type {
CredentialType::Email => CredentialType::Email => {
if !validate_user_email(&credential_dto.credential) { if !validate_user_email(&credential_dto.credential) {
error_resources.push(ERROR_INVALID_EMAIL); error_resources.push(ERROR_INVALID_EMAIL);
}, }
CredentialType::PhoneNumber => }
CredentialType::PhoneNumber => {
if !validate_user_phone_number(&credential_dto.credential) { if !validate_user_phone_number(&credential_dto.credential) {
error_resources.push(ERROR_INVALID_PHONE_NUMBER); error_resources.push(ERROR_INVALID_PHONE_NUMBER);
}, }
CredentialType::Username => }
CredentialType::Username => {
if !validate_user_username(&credential_dto.credential) { if !validate_user_username(&credential_dto.credential) {
error_resources.push(ERROR_INVALID_USERNAME); error_resources.push(ERROR_INVALID_USERNAME);
}, }
}
}; };
} }
@ -55,20 +64,26 @@ pub fn validate_user_for_creation(user: &UserRegisterPayload, error_resources: &
error_resources.push(ERROR_INVALID_PASSWORD); error_resources.push(ERROR_INVALID_PASSWORD);
} }
} }
pub fn validate_user_for_password_authentication(user: &UserLoginPayload, error_resources: &mut Vec<ErrorResource>){ pub fn validate_user_for_password_authentication(
user: &UserLoginPayload,
error_resources: &mut Vec<ErrorResource>,
) {
match user.credential_type { match user.credential_type {
CredentialType::Email => CredentialType::Email => {
if !validate_user_email(&user.credential) { if !validate_user_email(&user.credential) {
error_resources.push(ERROR_INVALID_EMAIL); error_resources.push(ERROR_INVALID_EMAIL);
}, }
CredentialType::PhoneNumber => }
CredentialType::PhoneNumber => {
if !validate_user_phone_number(&user.credential) { if !validate_user_phone_number(&user.credential) {
error_resources.push(ERROR_INVALID_PHONE_NUMBER); error_resources.push(ERROR_INVALID_PHONE_NUMBER);
}, }
CredentialType::Username => }
CredentialType::Username => {
if !validate_user_username(&user.credential) { if !validate_user_username(&user.credential) {
error_resources.push(ERROR_INVALID_USERNAME); error_resources.push(ERROR_INVALID_USERNAME);
}, }
}
} }
if !validate_user_password(&user.password) { if !validate_user_password(&user.password) {
error_resources.push(ERROR_INVALID_PASSWORD); error_resources.push(ERROR_INVALID_PASSWORD);