Skip to content

Commit

Permalink
added blocktime
Browse files Browse the repository at this point in the history
  • Loading branch information
Rajdip019 committed May 12, 2024
1 parent df6415a commit 967d67e
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 55 deletions.
23 changes: 20 additions & 3 deletions src/core/auth.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use bson::doc;
use bson::{doc, DateTime};
use mongodb::{Client, Collection};

use crate::{
Expand Down Expand Up @@ -91,6 +91,19 @@ impl Auth {
Err(e) => return Err(e),
};

// check if the user has a blocked_until date greater than the current date check in milliseconds from DateTime type
match user.blocked_until {
Some(blocked_until_time) => {
let current_time = DateTime::now().timestamp_millis();
if blocked_until_time.timestamp_millis() > current_time {
return Err(Error::UserBlocked {
message: "User is blocked".to_string(),
});
}
}
None => {}
}

let dek_data = match Dek::get(&mongo_client, &user.uid).await {
Ok(dek_data) => dek_data,
Err(e) => return Err(e),
Expand Down Expand Up @@ -122,8 +135,12 @@ impl Auth {

Ok(res)
} else {
Err(Error::UserNotFound {
message: "User not found".to_string(),
match User::increase_failed_login_attempt(&mongo_client, &user.email).await {
Ok(_) => {}
Err(e) => return Err(e),
}
Err(Error::WrongCredentials {
message: "Invalid credentials".to_string(),
})
}
}
Expand Down
144 changes: 144 additions & 0 deletions src/core/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ pub struct User {
pub password: String,
pub email_verified: bool,
pub is_active: bool,
pub failed_login_attempts: i32,
pub blocked_until: Option<DateTime>,
pub created_at: Option<DateTime>,
pub updated_at: Option<DateTime>,
}
Expand All @@ -40,6 +42,8 @@ impl User {
password: password.to_string(),
email_verified: false,
is_active: true,
failed_login_attempts: 0,
blocked_until: None,
created_at: Some(DateTime::now()),
updated_at: Some(DateTime::now()),
}
Expand Down Expand Up @@ -288,6 +292,146 @@ impl User {
}
}

pub async fn increase_failed_login_attempt(
mongo_client: &Client,
email: &str,
) -> Result<i32> {
let db = mongo_client.database("test");
let collection: Collection<User> = db.collection("users");
let dek_data = match Dek::get(&mongo_client, email).await {
Ok(dek) => dek,
Err(e) => {
return Err(e);
}
};

// find the user in the users collection using the uid
match collection
.update_one(
doc! {
"uid": Encryption::encrypt_data(&dek_data.uid, &dek_data.dek),
},
doc! {
"$inc": {
"failed_login_attempts": 1
},
"$set": {
"updated_at": DateTime::now(),
}
},
None,
)
.await
{
Ok(cursor) => {
let modified_count = cursor.modified_count;

// Return Error if User is not there
if modified_count == 0 {
// send back a 404 to
return Err(Error::UserNotFound {
message: "User not found".to_string(),
});
}

// check if the failed login attempts is greater than 5 then add_block_user_until 180 seconds and if it is 10 then for 10 minutes if its 15 then 1hr
let user = match User::get_from_email(&mongo_client, email).await {
Ok(user) => user,
Err(e) => {
return Err(e);
}
};

if user.failed_login_attempts == 5 {
let blocked_until = DateTime::now().timestamp_millis() + 180000;
match collection
.update_one(
doc! {
"uid": Encryption::encrypt_data(&dek_data.uid, &dek_data.dek),
},
doc! {
"$set": {
"blocked_until": DateTime::from_millis(blocked_until),
"updated_at": DateTime::now(),
}
},
None,
)
.await
{
Ok(_) => {
return Ok(5);
}
Err(_) => {
return Err(Error::ServerError {
message: "Failed to update User".to_string(),
});
}
}
} else if user.failed_login_attempts == 10 {
let blocked_until = DateTime::now().timestamp_millis() + 600000;
match collection
.update_one(
doc! {
"uid": Encryption::encrypt_data(&dek_data.uid, &dek_data.dek),
},
doc! {
"$set": {
"blocked_until": DateTime::from_millis(blocked_until),
"updated_at": DateTime::now(),
}
},
None,
)
.await
{
Ok(_) => {
return Ok(10);
}
Err(_) => {
return Err(Error::ServerError {
message: "Failed to update User".to_string(),
});
}
}
} else if user.failed_login_attempts == 15 {
let blocked_until = DateTime::now().timestamp_millis() + 3600000;
match collection
.update_one(
doc! {
"uid": Encryption::encrypt_data(&dek_data.uid, &dek_data.dek),
},
doc! {
"$set": {
"blocked_until": DateTime::from_millis(blocked_until),
"updated_at": DateTime::now(),
}
},
None,
)
.await
{
Ok(_) => {
return Ok(15);
}
Err(_) => {
return Err(Error::ServerError {
message: "Failed to update User".to_string(),
});
}
}
} else {
return Ok(user.failed_login_attempts);
}
}
Err(_) => {
return Err(Error::ServerError {
message: "Failed to update User".to_string(),
})
}
}
}

pub async fn change_password(mongo_client: &Client, email: &str, old_password: &str, new_password: &str) -> Result<String> {
let db = mongo_client.database("test");
let collection: Collection<User> = db.collection("users");
Expand Down
12 changes: 12 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ pub enum Error {
// -- User Errors
UserNotFound { message: String },
UserAlreadyExists { message: String },
WrongCredentials { message: String },
UserBlocked { message: String },

// -- Password Errors
InvalidPassword { message: String },
Expand Down Expand Up @@ -75,6 +77,14 @@ impl Error {
(StatusCode::UNAUTHORIZED, ClientError::INVALID_PASSWORD)
}

Self::WrongCredentials { message: _ } => {
(StatusCode::UNAUTHORIZED, ClientError::WRONG_CREDENTIALS)
}

Self::UserBlocked { message: _ } => {
(StatusCode::UNAUTHORIZED, ClientError::USER_BLOCKED)
}

Self::KeyNotFound { message: _ } => (
StatusCode::INTERNAL_SERVER_ERROR,
ClientError::SERVICE_ERROR,
Expand Down Expand Up @@ -149,6 +159,8 @@ pub enum ClientError {
SERVICE_ERROR,
USER_ALREADY_EXISTS,
INVALID_PASSWORD,
WRONG_CREDENTIALS,
USER_BLOCKED,
RESET_PASSWORD_LINK_EXPIRED,
INVALID_TOKEN,
SIGNATURE_VERIFICATION_ERROR,
Expand Down
50 changes: 0 additions & 50 deletions src/utils/refresh_token_utils.rs

This file was deleted.

4 changes: 2 additions & 2 deletions src/utils/session_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub struct IDToken {
pub data: Option<HashMap<String, String>>,
}

fn load_private_key() -> Result<Vec<u8>, Error> {
pub fn load_private_key() -> Result<Vec<u8>, Error> {
let private_key_content = fs::read("private_key.pem");
let rsa = Rsa::private_key_from_pem(&private_key_content.unwrap()).unwrap();
let private_key = PKey::from_rsa(rsa).unwrap();
Expand All @@ -32,7 +32,7 @@ fn load_private_key() -> Result<Vec<u8>, Error> {
}

// Load public key from the private key
fn load_public_key() -> Result<Vec<u8>, Error> {
pub fn load_public_key() -> Result<Vec<u8>, Error> {
let private_key_content = fs::read("private_key.pem");
let rsa = Rsa::private_key_from_pem(&private_key_content.unwrap()).unwrap();
let private_key = PKey::from_rsa(rsa).unwrap();
Expand Down

0 comments on commit 967d67e

Please sign in to comment.