This commit is contained in:
Franklin 2023-09-24 12:42:56 -04:00
parent 6cca212c42
commit e853447735
5 changed files with 54 additions and 36 deletions

View File

@ -36,4 +36,4 @@ pub enum Error {
pub struct ValidationError {
pub what: String,
pub reason: String,
}
}

View File

@ -7,7 +7,7 @@ use sqlx::{
Postgres,
};
use crate::domain::{credential::CredentialType};
use crate::domain::credential::CredentialType;
use crate::domain::error::Error;
use crate::domain::error::Error::FromStrError;

View File

@ -7,16 +7,19 @@ use crate::domain::user::User;
use crate::dto::token::{AuthenticateUserDto, RefreshAuthTokenForUserDto};
use crate::dto::users::{UserLoginPayload, UserRegisterPayload, UserResetPasswordPayload};
use crate::domain::error::Error::{
AlreadyExistsError, IncorrectCredentialError, NotFoundError, TooManyCredentialsError,
UnexpectedError,
};
use crate::domain::error::{Error, ValidationError};
use crate::resources::expirations::AUTH_TOKEN_EXPIRATION_TIME_MILLIS;
use crate::utils::hasher::{
generate_multiple_random_token_with_rng, hash_password, hash_password_with_existing_salt,
};
use crate::validation::user_validator::validate_user_for_creation;
use chrono::Utc;
use log::{error};
use log::error;
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>(
transaction: &mut PgConnection,
@ -49,14 +52,13 @@ pub async fn register_user<'a>(
last_updated: now,
};
let persisted_user= insert_user(transaction, user_to_insert).await?;
let persisted_user = insert_user(transaction, user_to_insert).await?;
// Insert Credentials
for credential in user.credentials {
insert_credential(transaction, credential, &persisted_user.id).await?;
}
create_token_for_user(transaction, persisted_user.id).await
}
pub async fn authenticate_user<'a>(
@ -71,15 +73,15 @@ pub async fn authenticate_user<'a>(
};
match validate_user_token(conn, &user.id, user.auth_token.clone()).await? {
None => {
Err(NotFoundError(format!("Auth Token {}", user.auth_token)))
}
None => Err(NotFoundError(format!("Auth Token {}", user.auth_token))),
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.")))
Err(IncorrectCredentialError(String::from(
"Auth Token Expired. Use refresh token to get a new one.",
)))
} else {
// Not expired
Ok(persisted_user)
@ -115,14 +117,15 @@ pub async fn reset_password(
conn: &mut PgConnection,
user: UserResetPasswordPayload,
) -> Result<User, Error> {
let password_matches = validate_user_password(conn, &user.id, user.password).await?;
if let Some(persisted_user) = password_matches {
// Change pass
Ok(change_password(conn, persisted_user, &user.new_password).await?)
} else {
Err(IncorrectCredentialError(String::from("Password incorrect.")))
Err(IncorrectCredentialError(String::from(
"Password incorrect.",
)))
}
}
@ -149,21 +152,18 @@ pub async fn password_login<'a>(
user: UserLoginPayload,
) -> Result<Token, Error> {
let persisted_user_credential = match get_credential(conn, user.credential.clone()).await? {
None => {
return Err(NotFoundError(format!("Credential {}", user.credential)))
}
None => return Err(NotFoundError(format!("Credential {}", user.credential))),
Some(persisted_credential) => persisted_credential,
};
let persisted_user_opt =
validate_user_password(conn, &persisted_user_credential.user_id, user.password).await?;
if let Some(_) = persisted_user_opt {
Ok(create_token_for_user(
conn,
persisted_user_credential.user_id,
)
.await?)
Ok(create_token_for_user(conn, persisted_user_credential.user_id).await?)
} else {
Err(NotFoundError(format!("User with id: {}", persisted_user_credential.user_id)))
Err(NotFoundError(format!(
"User with id: {}",
persisted_user_credential.user_id
)))
}
}
@ -188,14 +188,18 @@ async fn create_token_for_user<'a>(
auth_token: match tokens.get(0) {
None => {
error!("Tokens were not created.");
return Err(Error::UnexpectedError(String::from("Tokens were not created.")));
return Err(Error::UnexpectedError(String::from(
"Tokens were not created.",
)));
}
Some(token) => token.clone(),
},
refresh_token: match tokens.get(1) {
None => {
error!("Tokens were not created.");
return Err(Error::UnexpectedError(String::from("Tokens were not created.")));
return Err(Error::UnexpectedError(String::from(
"Tokens were not created.",
)));
}
Some(token) => token.clone(),
},

View File

@ -8,9 +8,7 @@ use std::num::NonZeroU32;
const SALT_ROUNDS: u32 = 1000;
pub(crate) async fn generate_multiple_random_token_with_rng(
amount: u8,
) -> Vec<String> {
pub(crate) async fn generate_multiple_random_token_with_rng(amount: u8) -> Vec<String> {
// Get a new instance of a Random Number Generator
let rng = SystemRandom::new();

View File

@ -3,9 +3,7 @@ use crate::domain::error::ValidationError;
use crate::dto::users::{UserLoginPayload, UserRegisterPayload};
use crate::resources::error_messages::ERROR_INVALID_USERNAME;
use crate::resources::{
error_messages::{
ERROR_INVALID_EMAIL, ERROR_INVALID_PASSWORD, ERROR_INVALID_PHONE_NUMBER,
},
error_messages::{ERROR_INVALID_EMAIL, 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,
@ -47,10 +45,16 @@ pub(crate) fn validate_user_for_creation(
}
if !validate_user_name(&user.name) {
error_resources.push(ValidationError { what: String::from("UserName"), reason: ERROR_INVALID_USERNAME.0.to_string() });
error_resources.push(ValidationError {
what: String::from("UserName"),
reason: ERROR_INVALID_USERNAME.0.to_string(),
});
}
if !validate_user_password(&user.password) {
error_resources.push(ValidationError { what: String::from("Password"), reason: ERROR_INVALID_PASSWORD.0.to_string() });
error_resources.push(ValidationError {
what: String::from("Password"),
reason: ERROR_INVALID_PASSWORD.0.to_string(),
});
}
}
#[allow(unused)]
@ -60,7 +64,10 @@ pub(crate) fn validate_user_for_password_authentication(
) {
validate_credential(error_resources, &user.credential, &user.credential_type);
if !validate_user_password(&user.password) {
error_resources.push(ValidationError { what: String::from("Password"), reason: ERROR_INVALID_PASSWORD.0.to_string() });
error_resources.push(ValidationError {
what: String::from("Password"),
reason: ERROR_INVALID_PASSWORD.0.to_string(),
});
}
}
@ -72,17 +79,26 @@ fn validate_credential(
match credential_type {
CredentialType::Email => {
if !validate_user_email(credential) {
error_resources.push(ValidationError { what: String::from("Email"), reason: ERROR_INVALID_EMAIL.0.to_string() });
error_resources.push(ValidationError {
what: String::from("Email"),
reason: ERROR_INVALID_EMAIL.0.to_string(),
});
}
}
CredentialType::PhoneNumber => {
if !validate_user_phone_number(credential) {
error_resources.push(ValidationError { what: String::from("Phone Number"), reason: ERROR_INVALID_PHONE_NUMBER.0.to_string() });
error_resources.push(ValidationError {
what: String::from("Phone Number"),
reason: ERROR_INVALID_PHONE_NUMBER.0.to_string(),
});
}
}
CredentialType::Username => {
if !validate_user_username(credential) {
error_resources.push(ValidationError { what: String::from("UserName"), reason: ERROR_INVALID_USERNAME.0.to_string() });
error_resources.push(ValidationError {
what: String::from("UserName"),
reason: ERROR_INVALID_USERNAME.0.to_string(),
});
}
}
}