fix otp and password validation
This commit is contained in:
@@ -3,10 +3,23 @@ use lazy_static::lazy_static;
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use utoipa::ToSchema;
|
use utoipa::ToSchema;
|
||||||
use validator::Validate;
|
use validator::{Validate, ValidationError};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref PASSWORD_REGEX: Regex = Regex::new(r"^[A-Za-z\d@$!%*?&]{8,}$").unwrap();
|
static ref PASSWORD_REGEX: Regex = Regex::new(r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_password_complexity(password: &str) -> Result<(), ValidationError> {
|
||||||
|
let has_uppercase = password.chars().any(|c| c.is_ascii_uppercase());
|
||||||
|
let has_lowercase = password.chars().any(|c| c.is_ascii_lowercase());
|
||||||
|
let has_digit = password.chars().any(|c| c.is_ascii_digit());
|
||||||
|
let has_special = password.chars().any(|c| "@$!%*?&".contains(c));
|
||||||
|
|
||||||
|
if has_uppercase && has_lowercase && has_digit && has_special {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(ValidationError::new("complexity"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)]
|
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)]
|
||||||
@@ -56,8 +69,8 @@ pub struct AuthRegisterRequestDto {
|
|||||||
min = 8,
|
min = 8,
|
||||||
message = "Password must have at least 8 characters"
|
message = "Password must have at least 8 characters"
|
||||||
))]
|
))]
|
||||||
#[validate(regex(
|
#[validate(custom(
|
||||||
path = "PASSWORD_REGEX",
|
function = "validate_password_complexity",
|
||||||
message = "Password must include uppercase, lowercase, number, and special character"
|
message = "Password must include uppercase, lowercase, number, and special character"
|
||||||
))]
|
))]
|
||||||
pub password: String,
|
pub password: String,
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ impl<'a> AuthRepository<'a> {
|
|||||||
|
|
||||||
pub async fn query_store_otp(&self, email: String, otp: u32) -> Result<String> {
|
pub async fn query_store_otp(&self, email: String, otp: u32) -> Result<String> {
|
||||||
let expires_at = Utc::now() + Duration::seconds(300);
|
let expires_at = Utc::now() + Duration::seconds(300);
|
||||||
let table = ResourceEnum::OtpCache.to_string();
|
let table: String = ResourceEnum::OtpCache.to_string();
|
||||||
let record: Option<AuthOtpSchema> = self
|
let record: Option<AuthOtpSchema> = self
|
||||||
.state
|
.state
|
||||||
.surrealdb_mem
|
.surrealdb_mem
|
||||||
|
|||||||
@@ -202,10 +202,18 @@ impl AuthService {
|
|||||||
if let Err((status, message)) = validate_request(&payload) {
|
if let Err((status, message)) = validate_request(&payload) {
|
||||||
return common_response(status, &message);
|
return common_response(status, &message);
|
||||||
}
|
}
|
||||||
let repository = AuthRepository::new(state);
|
|
||||||
|
let user_repo = UsersRepository::new(state);
|
||||||
|
if user_repo.query_user_by_email(payload.email.clone()).await.is_err() {
|
||||||
|
return common_response(StatusCode::BAD_REQUEST, "User not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
let auth_repo = AuthRepository::new(state);
|
||||||
|
let _ = auth_repo.query_get_stored_otp(payload.email.clone()).await;
|
||||||
|
|
||||||
let otp = generate_otp::OtpManager::generate_otp();
|
let otp = generate_otp::OtpManager::generate_otp();
|
||||||
let message = format!("Your OTP code is {}", otp);
|
let message = format!("Your OTP code is {}", otp);
|
||||||
match repository.query_store_otp(payload.email.clone(), otp).await {
|
match auth_repo.query_store_otp(payload.email.clone(), otp).await {
|
||||||
Ok(_) => match send_email(&payload.email, "OTP Verification", &message) {
|
Ok(_) => match send_email(&payload.email, "OTP Verification", &message) {
|
||||||
Ok(_) => common_response(StatusCode::OK, "OTP resent successfully"),
|
Ok(_) => common_response(StatusCode::OK, "OTP resent successfully"),
|
||||||
Err(err) => common_response(StatusCode::BAD_REQUEST, &err.to_string()),
|
Err(err) => common_response(StatusCode::BAD_REQUEST, &err.to_string()),
|
||||||
|
|||||||
Reference in New Issue
Block a user