Error refactor

This commit is contained in:
Franklin 2023-09-24 12:42:11 -04:00
parent 06d5b6ef9d
commit a15c4d807f
8 changed files with 149 additions and 277 deletions

View File

@ -3,7 +3,7 @@
<option name="myName" value="Project Default" /> <option name="myName" value="Project Default" />
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true"> <inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<Languages> <Languages>
<language minSize="83" name="Rust" /> <language minSize="86" name="Rust" />
</Languages> </Languages>
</inspection_tool> </inspection_tool>
<inspection_tool class="SqlDialectInspection" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="SqlDialectInspection" enabled="false" level="WARNING" enabled_by_default="false" />

16
Cargo.lock generated
View File

@ -50,6 +50,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]] [[package]]
name = "atoi" name = "atoi"
version = "2.0.0" version = "2.0.0"
@ -1427,18 +1433,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.44" version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.44" version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1606,6 +1612,7 @@ dependencies = [
name = "user-lib" name = "user-lib"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow",
"chrono", "chrono",
"data-encoding", "data-encoding",
"futures-util", "futures-util",
@ -1613,6 +1620,7 @@ dependencies = [
"ring", "ring",
"serde", "serde",
"sqlx", "sqlx",
"thiserror",
"tokio", "tokio",
] ]

View File

@ -18,3 +18,5 @@ ring = "0.16.20"
data-encoding = "2.3.2" data-encoding = "2.3.2"
futures-util = "0.3" futures-util = "0.3"
log = "0.4.19" log = "0.4.19"
thiserror = "1.0.48"
anyhow = { version = "1.0" }

View File

@ -1,13 +1,39 @@
use std::fmt::Display; use thiserror::Error;
/// Used to return a simple error from FromStr implementations #[derive(Error, Debug)]
#[derive(Debug)] pub enum Error {
pub struct FromStrError; /// Used to return a simple error from FromStr implementations.
#[error("Error parsing string into value")]
impl Display for FromStrError { FromStrError,
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { /// Every error that is returned from a DAO operation.
write!(f, "Error parsing string into value. FromStrError.") #[error("Error from the Database: {0}")]
} DatabaseError(#[from] sqlx::Error),
/// A vec of ValidationErrors
#[error("Validation Errors: {0:?}")]
ValidationErrors(Vec<ValidationError>),
/// Something already exists. That something should be {0}
/// Example: "User" "Credential"
#[error("Error {0} Already exists.")]
AlreadyExistsError(String),
/// Example: "User with id X"
#[error("{0} Not found.")]
NotFoundError(String),
/// Used to specify authentication error.
/// Example: Password incorrect for user
#[error("Credential supplied is incorrect. {0}")]
IncorrectCredentialError(String),
#[error("Too many credentials supplied, maximum is 3.")]
TooManyCredentialsError,
/// Used for anything else.
#[error("Unexpected Error: {0}")]
UnexpectedError(String),
} }
impl std::error::Error for FromStrError {} /// Any string validation error such as Phone number validation or email, etc...
/// Reason should be a Key for internationalization
#[derive(Error, Debug)]
#[error("Error validating `{what}`. Reason: {reason}")]
pub struct ValidationError {
pub what: String,
pub reason: String,
}

View File

@ -7,10 +7,12 @@ use sqlx::{
Postgres, Postgres,
}; };
use crate::domain::{credential::CredentialType, error::FromStrError}; use crate::domain::{credential::CredentialType};
use crate::domain::error::Error;
use crate::domain::error::Error::FromStrError;
impl FromStr for CredentialType { impl FromStr for CredentialType {
type Err = FromStrError; type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s { match s {

View File

@ -19,36 +19,28 @@ use crate::validation::user_validator::validate_user_for_creation;
use chrono::Utc; use chrono::Utc;
use log::{debug, error}; use log::{debug, error};
use sqlx::{PgConnection, Postgres, Transaction}; use sqlx::{PgConnection, Postgres, Transaction};
use crate::domain::error::{Error, ValidationError};
use crate::domain::error::Error::{AlreadyExistsError, IncorrectCredentialError, NotFoundError, TooManyCredentialsError, UnexpectedError};
pub async fn register_user<'a>( pub async fn register_user<'a>(
transaction: &mut PgConnection, transaction: &mut PgConnection,
user: UserRegisterPayload, user: UserRegisterPayload,
) -> Result<Token, Vec<ErrorResource<'a>>> { ) -> Result<Token, Error> {
let mut error_resources: Vec<ErrorResource> = Vec::new(); let mut validation_errors: Vec<ValidationError> = Vec::new();
// Validate user // Validate user
validate_user_for_creation(&user, &mut error_resources); validate_user_for_creation(&user, &mut validation_errors);
// Find if user exists // Find if user exists
if user.credentials.len() > 3 { if user.credentials.len() > 3 {
error_resources.push(ERROR_TOO_MANY_CREDENTIALS); return Err(TooManyCredentialsError);
} }
for credential_dto in user.credentials.iter() { for credential_dto in user.credentials.iter() {
match get_credential(transaction, credential_dto.credential.clone()).await { match get_credential(transaction, credential_dto.credential.clone()).await? {
Ok(credential_opt) => match credential_opt { None => {}
None => {} Some(_) => {
Some(_) => { return Err(AlreadyExistsError(String::from("Credential")));
error_resources.push(ERROR_USER_ALREADY_EXISTS);
}
},
Err(e) => {
error!("{}", e);
error_resources.push(("ERROR.DATABASE_ERROR", ""));
} }
}; };
} }
// If validation gave any errors blow up and send them back to the client
if error_resources.len() > 0 {
return Err(error_resources);
}
// Get salt and hashed password from hashing function then give the results to the user // Get salt and hashed password from hashing function then give the results to the user
let hash_result = hash_password(&user.password); let hash_result = hash_password(&user.password);
let now = Utc::now(); let now = Utc::now();
@ -61,84 +53,41 @@ pub async fn register_user<'a>(
last_updated: now, last_updated: now,
}; };
let persisted_user; let persisted_user= insert_user(transaction, user_to_insert).await?;
// Insert user in DB
match insert_user(transaction, user_to_insert).await {
Ok(user) => {
persisted_user = user;
}
Err(e) => {
error!("{}", e);
error_resources.push(("ERROR.DATABASE_ERROR", ""));
return Err(error_resources);
}
};
// Insert Credentials // Insert Credentials
for credential in user.credentials { for credential in user.credentials {
match insert_credential(transaction, credential, &persisted_user.id).await { insert_credential(transaction, credential, &persisted_user.id).await?;
Ok(_) => {}
Err(e) => {
error!("{}", e);
error_resources.push(("ERROR.DATABASE_ERROR", ""));
return Err(error_resources);
}
};
} }
if let Some(persisted_token) =
create_token_for_user(transaction, persisted_user.id, &mut error_resources).await create_token_for_user(transaction, persisted_user.id).await
{
Ok(persisted_token)
} else {
Err(error_resources)
}
} }
pub async fn authenticate_user<'a>( pub async fn authenticate_user<'a>(
conn: &mut PgConnection, conn: &mut PgConnection,
user: AuthenticateUserDto, user: AuthenticateUserDto,
) -> Result<User, Vec<ErrorResource<'a>>> { ) -> Result<User, Error> {
let mut error_resources = Vec::new(); let persisted_user = match get_user_with_id(conn, &user.id).await? {
let persisted_user = match get_user_with_id(conn, &user.id).await { None => {
Ok(persisted_user_opt) => match persisted_user_opt { return Err(NotFoundError(format!("User with id: {}", user.id)));
None => {
error_resources.push(ERROR_USER_DOES_NOT_EXIST);
return Err(error_resources);
}
Some(persisted_user) => persisted_user,
},
Err(error) => {
error!("{:?}", error);
error_resources.push(("ERROR.DATABASE_ERROR", ""));
return Err(error_resources);
} }
Some(persisted_user) => persisted_user,
}; };
match validate_user_token(conn, &user.id, user.auth_token).await { match validate_user_token(conn, &user.id, user.auth_token.clone()).await? {
Ok(persisted_token_opt) => match persisted_token_opt { None => {
None => { Err(NotFoundError(format!("Auth Token {}", user.auth_token)))
error_resources.push(ERROR_INCORRECT_TOKEN); }
Err(error_resources) Some(persisted_token) => {
// Check if persisted_token expired
if Utc::now().timestamp_millis() - persisted_token.last_updated.timestamp_millis()
> AUTH_TOKEN_EXPIRATION_TIME_MILLIS
{
Err(IncorrectCredentialError(String::from("Auth Token Expired. Use refresh token to get a new one.")))
} else {
// Not expired
Ok(persisted_user)
} }
Some(persisted_token) => {
// Check if persisted_token expired
if Utc::now().timestamp_millis() - persisted_token.last_updated.timestamp_millis()
> AUTH_TOKEN_EXPIRATION_TIME_MILLIS
{
// Expired
debug!("Expired token: {:?}", persisted_token);
error_resources.push(ERROR_EXPIRED_TOKEN);
Err(error_resources)
} else {
// Not expired
Ok(persisted_user)
}
}
},
Err(error) => {
error!("{:?}", error);
error_resources.push(("ERROR.DATABASE_ERROR", ""));
Err(error_resources)
} }
} }
} }
@ -147,76 +96,37 @@ pub async fn authenticate_user<'a>(
pub async fn refresh_auth_token<'a>( pub async fn refresh_auth_token<'a>(
conn: &mut PgConnection, conn: &mut PgConnection,
user: RefreshAuthTokenForUserDto, user: RefreshAuthTokenForUserDto,
) -> Result<Token, Vec<ErrorResource>> { ) -> Result<Token, Error> {
let mut error_resources = Vec::new(); let _persisted_user = match get_user_with_id(conn, &user.id).await? {
let _persisted_user = match get_user_with_id(conn, &user.id).await { None => {
Ok(persisted_user_opt) => match persisted_user_opt { return Err(NotFoundError(format!("User with id: {}", user.id)));
None => {
error_resources.push(ERROR_USER_DOES_NOT_EXIST);
return Err(error_resources);
}
Some(persisted_user) => persisted_user,
},
Err(error) => {
error!("{:?}", error);
error_resources.push(("ERROR.DATABASE_ERROR", ""));
return Err(error_resources);
} }
Some(persisted_user) => persisted_user,
}; };
let mut tokens: Vec<String> = match generate_multiple_random_token_with_rng(2).await { let mut tokens: Vec<String> = generate_multiple_random_token_with_rng(2).await;
Ok(tokens) => tokens,
Err(e) => {
error!("{}", e);
error_resources.push(("ERROR.JOIN_ERROR", ""));
return Err(error_resources);
}
};
if tokens.len() > 0 { if tokens.len() > 0 {
let new_auth_token = tokens.remove(0); let new_auth_token = tokens.remove(0);
return match update_token(conn, user.refresh_token, new_auth_token).await { Ok(update_token(conn, user.refresh_token, new_auth_token).await?)
Ok(persisted_token) => Ok(persisted_token), } else {
Err(e) => { Err(UnexpectedError(String::from("No tokens were created.")))
error!("{:?}", e);
error_resources.push(("ERROR.DATABASE_ERROR", ""));
Err(error_resources)
}
};
} }
Err(error_resources)
} }
/// reset a user's password by validating the user's own password. /// reset a user's password by validating the user's own password.
pub async fn reset_password( pub async fn reset_password(
conn: &mut PgConnection, conn: &mut PgConnection,
user: UserResetPasswordPayload, user: UserResetPasswordPayload,
) -> Result<User, Vec<ErrorResource>> { ) -> Result<User, Error> {
let mut error_resources: Vec<ErrorResource> = Vec::new();
let password_matches = match validate_user_password(conn, &user.id, user.password).await { let password_matches = validate_user_password(conn, &user.id, user.password).await?;
Ok(matches) => matches,
Err(e) => {
error!("{:?}", e);
error_resources.push(e);
return Err(error_resources);
}
};
if let Some(persisted_user) = password_matches { if let Some(persisted_user) = password_matches {
// Change pass // Change pass
match change_password(conn, persisted_user, &user.new_password).await { Ok(change_password(conn, persisted_user, &user.new_password).await?)
Ok(user_changed) => Ok(user_changed),
Err(e) => {
error!("{:?}", e);
error_resources.push(e);
Err(error_resources)
}
}
} else { } else {
error_resources.push(ERROR_PASSWORD_INCORRECT); Err(IncorrectCredentialError(String::from("Password incorrect.")))
Err(error_resources)
} }
} }
@ -226,24 +136,13 @@ pub async fn force_reset_password<'a>(
conn: &mut PgConnection, conn: &mut PgConnection,
user_id: &i32, user_id: &i32,
new_password: String, new_password: String,
) -> Result<User, ErrorResource<'a>> { ) -> Result<User, Error> {
let persisted_user = match get_user_with_id(conn, user_id).await { let persisted_user = match get_user_with_id(conn, user_id).await? {
Ok(persisted_user_opt) => { None => {
match persisted_user_opt { error!("Serious error. User doesn't exist but credentials pointing to the user do.");
None => { return Err(Error::NotFoundError(format!("User with id: {user_id}")));
error!("Serious error. User doesn't exist but credentials pointing to the user do.");
return Err((
"ERROR.DATABASE_ERROR",
"Critical. User doesn't exist but credentials pointing to the user do.",
));
}
Some(persisted_user) => persisted_user,
}
}
Err(e) => {
error!("{}", e);
return Err(("ERROR.DATABASE_ERROR", ""));
} }
Some(persisted_user) => persisted_user,
}; };
Ok(change_password(conn, persisted_user, &new_password).await?) Ok(change_password(conn, persisted_user, &new_password).await?)
} }
@ -252,97 +151,55 @@ pub async fn force_reset_password<'a>(
pub async fn password_login<'a>( pub async fn password_login<'a>(
conn: &mut Transaction<'a, Postgres>, conn: &mut Transaction<'a, Postgres>,
user: UserLoginPayload, user: UserLoginPayload,
) -> Result<Token, Vec<ErrorResource<'a>>> { ) -> Result<Token, Error> {
let mut error_resources = Vec::new(); let persisted_user_credential = match get_credential(conn, user.credential.clone()).await? {
let persisted_user_credential = match get_credential(conn, user.credential).await { None => {
Ok(credential_opt) => match credential_opt { return Err(NotFoundError(format!("Credential {}", user.credential)))
None => {
error!("Credential not found for password login.");
error_resources.push(ERROR_CREDENTIAL_DOES_NOT_EXIST);
return Err(error_resources);
}
Some(persisted_credential) => persisted_credential,
},
Err(e) => {
error!("{}", e);
error_resources.push(("ERROR.DATABASE_ERROR", ""));
return Err(error_resources);
} }
Some(persisted_credential) => persisted_credential,
}; };
let persisted_user_opt = let persisted_user_opt =
match validate_user_password(conn, &persisted_user_credential.user_id, user.password).await validate_user_password(conn, &persisted_user_credential.user_id, user.password).await?;
{
Ok(matches) => matches,
Err(e) => {
error!("{:?}", e);
error_resources.push(e);
return Err(error_resources);
}
};
if let Some(_) = persisted_user_opt { if let Some(_) = persisted_user_opt {
return if let Some(persisted_token) = create_token_for_user( Ok(create_token_for_user(
conn, conn,
persisted_user_credential.user_id, persisted_user_credential.user_id,
&mut error_resources,
) )
.await .await?)
{ } else {
Ok(persisted_token) Err(NotFoundError(format!("User with id: {}", persisted_user_credential.user_id)))
} else {
Err(error_resources)
};
} }
Err(error_resources)
} }
/// ///
pub async fn get_user_credentials<'a>( pub async fn get_user_credentials<'a>(
transaction: &mut Transaction<'a, Postgres>, transaction: &mut Transaction<'a, Postgres>,
user: AuthenticateUserDto, user: AuthenticateUserDto,
) -> Result<Vec<Credential>, Vec<ErrorResource<'a>>> { ) -> Result<Vec<Credential>, Error> {
let mut error_resources = Vec::new();
let persisted_user = authenticate_user(transaction, user).await?; let persisted_user = authenticate_user(transaction, user).await?;
match fetch_user_credentials(transaction, &persisted_user.id).await { Ok(fetch_user_credentials(transaction, &persisted_user.id).await?)
Ok(persisted_credentials) => Ok(persisted_credentials),
Err(e) => {
error!("{}", e);
error_resources.push(("ERROR.DATABASE_ERROR", ""));
Err(error_resources)
}
}
} }
async fn create_token_for_user<'a>( async fn create_token_for_user<'a>(
transaction: &mut PgConnection, transaction: &mut PgConnection,
user_id: i32, user_id: i32,
error_resources: &mut Vec<ErrorResource<'a>>, ) -> Result<Token, Error> {
) -> Option<Token> {
// Create token and send it back. // Create token and send it back.
let tokens: Vec<String> = match generate_multiple_random_token_with_rng(2).await { let tokens: Vec<String> = generate_multiple_random_token_with_rng(2).await;
Ok(tokens) => tokens,
Err(e) => {
error!("{}", e);
error_resources.push(("ERROR.JOIN_ERROR", ""));
return None;
}
};
let token_to_insert = Token { let token_to_insert = Token {
id: 0, id: 0,
user_id, user_id,
auth_token: match tokens.get(0) { auth_token: match tokens.get(0) {
None => { None => {
error!("Tokens were not created.",); error!("Tokens were not created.");
error_resources.push(ERROR_TOKEN_NOT_CREATED); return Err(Error::UnexpectedError(String::from("Tokens were not created.")));
return None;
} }
Some(token) => token.clone(), Some(token) => token.clone(),
}, },
refresh_token: match tokens.get(1) { refresh_token: match tokens.get(1) {
None => { None => {
error!("Tokens were not created.",); error!("Tokens were not created.");
error_resources.push(ERROR_TOKEN_NOT_CREATED); return Err(Error::UnexpectedError(String::from("Tokens were not created.")));
return None;
} }
Some(token) => token.clone(), Some(token) => token.clone(),
}, },
@ -351,39 +208,22 @@ async fn create_token_for_user<'a>(
}; };
// Insert token in DB // Insert token in DB
match insert_token(transaction, token_to_insert).await { Ok(insert_token(transaction, token_to_insert).await?)
Ok(persisted_token) => Some(persisted_token),
Err(e) => {
error!("{}", e);
error_resources.push(("ERROR.DATABASE_ERROR", ""));
None
}
}
} }
async fn validate_user_password<'a>( async fn validate_user_password<'a>(
conn: &mut PgConnection, conn: &mut PgConnection,
user_id: &i32, user_id: &i32,
password: String, password: String,
) -> Result<Option<User>, ErrorResource<'a>> { ) -> Result<Option<User>, Error> {
let persisted_user = match get_user_with_id(conn, user_id).await { let persisted_user = match get_user_with_id(conn, user_id).await? {
Ok(persisted_user_opt) => { None => {
match persisted_user_opt { error!("Serious error. User doesn't exist but credentials pointing to the user do.");
None => { return Err(Error::NotFoundError(format!("User with id: {user_id}")));
error!("Serious error. User doesn't exist but credentials pointing to the user do.");
return Err((
"ERROR.DATABASE_ERROR",
"Critical. User doesn't exist but credentials pointing to the user do.",
));
}
Some(persisted_user) => persisted_user,
}
}
Err(e) => {
error!("{}", e);
return Err(("ERROR.DATABASE_ERROR", ""));
} }
Some(persisted_user) => persisted_user,
}; };
let hashed_password = hash_password_with_existing_salt(&password, &persisted_user.salt); let hashed_password = hash_password_with_existing_salt(&password, &persisted_user.salt);
if hashed_password.hash == persisted_user.password { if hashed_password.hash == persisted_user.password {
Ok(Some(persisted_user)) Ok(Some(persisted_user))
@ -396,15 +236,9 @@ async fn change_password<'a>(
conn: &mut PgConnection, conn: &mut PgConnection,
mut persisted_user: User, mut persisted_user: User,
new_password: &String, new_password: &String,
) -> Result<User, ErrorResource<'a>> { ) -> Result<User, Error> {
let hash_result = hash_password(&new_password); let hash_result = hash_password(&new_password);
persisted_user.password = hash_result.hash; persisted_user.password = hash_result.hash;
persisted_user.salt = hash_result.salt; persisted_user.salt = hash_result.salt;
match update_user(conn, persisted_user).await { Ok(update_user(conn, persisted_user).await?)
Ok(user) => Ok(user),
Err(error) => {
error!("{}", error);
return Err(("ERROR.DATABASE_ERROR", ""));
}
}
} }

View File

@ -5,13 +5,12 @@ use ring::{
rand::{SecureRandom, SystemRandom}, rand::{SecureRandom, SystemRandom},
}; };
use std::num::NonZeroU32; use std::num::NonZeroU32;
use tokio::task::JoinError;
const SALT_ROUNDS: u32 = 1000; const SALT_ROUNDS: u32 = 1000;
pub(crate) async fn generate_multiple_random_token_with_rng( pub(crate) async fn generate_multiple_random_token_with_rng(
amount: u8, amount: u8,
) -> Result<Vec<String>, JoinError> { ) -> Vec<String> {
// Get a new instance of a Random Number Generator // Get a new instance of a Random Number Generator
let rng = SystemRandom::new(); let rng = SystemRandom::new();
@ -41,7 +40,7 @@ pub(crate) async fn generate_multiple_random_token_with_rng(
.rev() .rev()
.collect(); .collect();
Ok(all_tokens_solved) all_tokens_solved
} }
pub(crate) fn hash_password_with_existing_salt( pub(crate) fn hash_password_with_existing_salt(

View File

@ -1,9 +1,10 @@
use crate::domain::credential::CredentialType; use crate::domain::credential::CredentialType;
use crate::domain::error::ValidationError;
use crate::dto::users::{UserLoginPayload, UserRegisterPayload}; use crate::dto::users::{UserLoginPayload, UserRegisterPayload};
use crate::resources::error_messages::{ErrorResource, ERROR_INVALID_USERNAME}; use crate::resources::error_messages::ERROR_INVALID_USERNAME;
use crate::resources::{ use crate::resources::{
error_messages::{ error_messages::{
ERROR_INVALID_EMAIL, ERROR_INVALID_NAME, ERROR_INVALID_PASSWORD, ERROR_INVALID_PHONE_NUMBER, ERROR_INVALID_EMAIL, ERROR_INVALID_PASSWORD, ERROR_INVALID_PHONE_NUMBER,
}, },
variable_lengths::{ variable_lengths::{
MAX_EMAIL_LENGTH, MAX_NAME_LENGTH, MAX_PASSWORD_LENGTH, MIN_EMAIL_LENGTH, MIN_NAME_LENGTH, MAX_EMAIL_LENGTH, MAX_NAME_LENGTH, MAX_PASSWORD_LENGTH, MIN_EMAIL_LENGTH, MIN_NAME_LENGTH,
@ -35,7 +36,7 @@ fn validate_user_password(password: &String) -> bool {
pub(crate) fn validate_user_for_creation( pub(crate) fn validate_user_for_creation(
user: &UserRegisterPayload, user: &UserRegisterPayload,
error_resources: &mut Vec<ErrorResource>, error_resources: &mut Vec<ValidationError>,
) { ) {
for credential_dto in user.credentials.iter() { for credential_dto in user.credentials.iter() {
validate_credential( validate_credential(
@ -46,41 +47,41 @@ pub(crate) fn validate_user_for_creation(
} }
if !validate_user_name(&user.name) { if !validate_user_name(&user.name) {
error_resources.push(ERROR_INVALID_NAME); error_resources.push(ValidationError { what: String::from("UserName"), reason: ERROR_INVALID_USERNAME.0.to_string() });
} }
if !validate_user_password(&user.password) { if !validate_user_password(&user.password) {
error_resources.push(ERROR_INVALID_PASSWORD); error_resources.push(ValidationError { what: String::from("Password"), reason: ERROR_INVALID_PASSWORD.0.to_string() });
} }
} }
pub(crate) fn validate_user_for_password_authentication( pub(crate) fn validate_user_for_password_authentication(
user: &UserLoginPayload, user: &UserLoginPayload,
error_resources: &mut Vec<ErrorResource>, error_resources: &mut Vec<ValidationError>,
) { ) {
validate_credential(error_resources, &user.credential, &user.credential_type); validate_credential(error_resources, &user.credential, &user.credential_type);
if !validate_user_password(&user.password) { if !validate_user_password(&user.password) {
error_resources.push(ERROR_INVALID_PASSWORD); error_resources.push(ValidationError { what: String::from("Password"), reason: ERROR_INVALID_PASSWORD.0.to_string() });
} }
} }
fn validate_credential( fn validate_credential(
error_resources: &mut Vec<ErrorResource>, error_resources: &mut Vec<ValidationError>,
credential: &String, credential: &String,
credential_type: &CredentialType, credential_type: &CredentialType,
) { ) {
match credential_type { match credential_type {
CredentialType::Email => { CredentialType::Email => {
if !validate_user_email(credential) { if !validate_user_email(credential) {
error_resources.push(ERROR_INVALID_EMAIL); error_resources.push(ValidationError { what: String::from("Email"), reason: ERROR_INVALID_EMAIL.0.to_string() });
} }
} }
CredentialType::PhoneNumber => { CredentialType::PhoneNumber => {
if !validate_user_phone_number(credential) { if !validate_user_phone_number(credential) {
error_resources.push(ERROR_INVALID_PHONE_NUMBER); error_resources.push(ValidationError { what: String::from("Phone Number"), reason: ERROR_INVALID_PHONE_NUMBER.0.to_string() });
} }
} }
CredentialType::Username => { CredentialType::Username => {
if !validate_user_username(credential) { if !validate_user_username(credential) {
error_resources.push(ERROR_INVALID_USERNAME); error_resources.push(ValidationError { what: String::from("UserName"), reason: ERROR_INVALID_USERNAME.0.to_string() });
} }
} }
} }