Skip to content

Commit

Permalink
Merge pull request #31 from Rajdip019/debajyotisaha14/refactoring
Browse files Browse the repository at this point in the history
Final Refactoring Done
  • Loading branch information
Rajdip019 authored May 12, 2024
2 parents f1da2ad + 236f78c commit 0309e3c
Show file tree
Hide file tree
Showing 10 changed files with 294 additions and 226 deletions.
147 changes: 147 additions & 0 deletions src/core/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
use bson::doc;
use mongodb::{Client, Collection};

use crate::{
core::{dek::Dek, session::Session, user::User},
errors::{Error, Result},
models::auth_model::{SessionResponseForSignInOrSignUp, SignInOrSignUpResponse},
utils::{encryption_utils::Encryption, password_utils::Password},
};

pub struct Auth;

impl Auth {
pub async fn sign_up(
mongo_client: &Client,
name: &str,
email: &str,
role: &str,
password: &str,
) -> Result<SignInOrSignUpResponse> {
println!(">> HANDLER: add_user_handler called");

let db = mongo_client.database("test");

let collection: Collection<User> = db.collection("users");
let cursor = collection
.find_one(
Some(doc! {
"email": email
}),
None,
)
.await
.unwrap();

if cursor.is_some() {
return Err(Error::UserAlreadyExists {
message: "User already exists".to_string(),
});
}

let dek = Dek::generate(); // create a data encryption key for new user
let user = match User::new(name, email, role, password)
.encrypt_and_add(&mongo_client, &dek)
.await
{
Ok(user) => user,
Err(e) => return Err(e),
};

// add the dek to the deks collection
let dek_data = match Dek::new(&user.uid, &user.email, &dek)
.encrypt_and_add(&mongo_client)
.await
{
Ok(dek_data) => dek_data,
Err(e) => return Err(e),
};

let session = match Session::new(&user, "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36").encrypt_add(&mongo_client, &dek).await {
Ok(session) => session,
Err(e) => return Err(e),
};

Ok(SignInOrSignUpResponse {
message: "Signup successful".to_string(),
uid: user.uid,
name: user.name,
email: user.email,
role: user.role,
created_at: user.created_at,
updated_at: user.updated_at,
email_verified: user.email_verified,
is_active: user.is_active,
session: SessionResponseForSignInOrSignUp {
session_id: Encryption::encrypt_data(&session.session_id, &dek_data.dek),
id_token: session.id_token,
refresh_token: session.refresh_token,
},
})
}

pub async fn sign_in(
mongo_client: &Client,
email: &str,
password: &str,
) -> Result<SignInOrSignUpResponse> {
let user = match User::get_from_email(&mongo_client, email).await {
Ok(user) => user,
Err(e) => return Err(e),
};

let dek_data = match Dek::get(&mongo_client, &user.uid).await {
Ok(dek_data) => dek_data,
Err(e) => return Err(e),
};

// verify the password
if Password::verify_hash(password, &user.password) {
let session = match Session::new(&user, "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36").encrypt_add(&mongo_client, &dek_data.dek).await {
Ok(session) => session,
Err(e) => return Err(e),
};
// let res = Json(json!({
// "message": "Signin successful",
// "user": {
// "uid": user.uid,
// "name": user.name,
// "email": user.email,
// "role": user.role,
// "created_at": user.created_at,
// "updated_at": user.updated_at,
// "email_verified": user.email_verified,
// "is_active": user.is_active,
// "session": {
// "session_id": Encryption::encrypt_data(&session.session_id, &dek_data.dek),
// "id_token" : session.id_token,
// "refresh_token" : session.refresh_token,
// },
// },
// }));

let res = SignInOrSignUpResponse {
message: "Signin successful".to_string(),
uid: user.uid,
name: user.name,
email: user.email,
role: user.role,
created_at: user.created_at,
updated_at: user.updated_at,
email_verified: user.email_verified,
is_active: user.is_active,
session: SessionResponseForSignInOrSignUp {
session_id: Encryption::encrypt_data(&session.session_id, &dek_data.dek),
id_token: session.id_token,
refresh_token: session.refresh_token,
},
};

Ok(res)
} else {
Err(Error::UserNotFound {
message: "User not found".to_string(),
})
}
}
}
5 changes: 3 additions & 2 deletions src/core/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod user;
pub mod auth;
pub mod dek;
pub mod session;
pub mod session;
pub mod user;
18 changes: 5 additions & 13 deletions src/core/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
models::{password_model::ForgetPasswordRequest, user_model::UserResponse},
traits::{decryption::Decrypt, encryption::Encrypt},
utils::{
email_utils::Email, encryption_utils::Encryption, hashing_utils::{salt_and_hash_password, verify_password_hash}
email_utils::Email, encryption_utils::Encryption, password_utils::Password
},
};
use bson::{doc, oid::ObjectId, uuid, DateTime};
Expand Down Expand Up @@ -48,7 +48,7 @@ impl User {
pub async fn encrypt_and_add(&self, mongo_client: &Client, dek: &str) -> Result<Self> {
let db = mongo_client.database("test");
let mut user = self.clone();
user.password = salt_and_hash_password(user.password.as_str());
user.password = Password::salt_and_hash(user.password.as_str());
let collection: Collection<User> = db.collection("users");
match collection.insert_one(user.encrypt(&dek), None).await {
Ok(_) => return Ok(user),
Expand All @@ -61,12 +61,6 @@ impl User {
}

pub async fn get_from_email(mongo_client: &Client, email: &str) -> Result<User> {
// check if the payload is empty
match email.is_empty() {
true => Err(Error::InvalidPayload {
message: "Invalid payload".to_string(),
}),
false => {
let user_collection: Collection<User> =
mongo_client.database("test").collection("users");
let dek_data = match Dek::get(&mongo_client, email).await {
Expand Down Expand Up @@ -98,8 +92,6 @@ impl User {
message: "Failed to get User".to_string(),
}),
}
}
}
}

pub async fn get_from_uid(mongo_client: &Client, uid: &str) -> Result<User> {
Expand Down Expand Up @@ -328,13 +320,13 @@ impl User {

let decrypted_user = user.decrypt(&dek_data.dek);

if !verify_password_hash(&old_password, &decrypted_user.password) {
if !Password::verify_hash(&old_password, &decrypted_user.password) {
return Err(Error::InvalidPassword {
message: "New password cannot be the same as the old password".to_string(),
});
}
// hash and salt the new password
let hashed_and_salted_pass = salt_and_hash_password(&new_password);
let hashed_and_salted_pass = Password::salt_and_hash(&new_password);
// encrypt the new password
let encrypted_password = Encryption::encrypt_data(&hashed_and_salted_pass, &dek_data.dek);

Expand Down Expand Up @@ -459,7 +451,7 @@ impl User {
};

// hash and salt the new password
let hashed_and_salted_pass = salt_and_hash_password(&new_password);
let hashed_and_salted_pass = Password::salt_and_hash(&new_password);
// encrypt the new password
let encrypted_password = Encryption::encrypt_data(&hashed_and_salted_pass, &dek_data.dek);

Expand Down
55 changes: 41 additions & 14 deletions src/handlers/auth_handler.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,62 @@
use axum::{extract::State, Json};
use axum_macros::debug_handler;
use serde_json::Value;

use crate::{
core::session::Session, errors::{Error, Result}, models::{auth_model::{SignInPayload, SignUpPayload}, session_model::{RevokeSessionsPayload, RevokeSessionsResult}}, utils::auth_utils::{sign_in, sign_up}, AppState
core::{auth::Auth, session::Session},
errors::{Error, Result},
models::{
auth_model::{SignInOrSignUpResponse, SignInPayload, SignUpPayload},
session_model::{RevokeSessionsPayload, RevokeSessionsResult},
},
AppState,
};

#[debug_handler]
pub async fn signup_handler(
State(state): State<AppState>,
payload: Json<SignUpPayload>,
) -> Result<Json<Value>> {
) -> Result<Json<SignInOrSignUpResponse>> {
println!(">> HANDLER: signup_handler called");

match sign_up(&state.mongo_client, payload).await {
Ok(res) => Ok(res),
// check if the payload is empty
if payload.name.is_empty()
|| payload.email.is_empty()
|| payload.role.is_empty()
|| payload.password.is_empty()
{
return Err(Error::InvalidPayload {
message: "Invalid payload".to_string(),
});
}

match Auth::sign_up(
&state.mongo_client,
&payload.name,
&payload.email,
&payload.role,
&payload.password,
)
.await
{
Ok(res) => Ok(Json(res)),
Err(e) => Err(e),
}
}

pub async fn signin_handler(
State(state): State<AppState>,
payload: Json<SignInPayload>,
) -> Result<Json<Value>> {
) -> Result<Json<SignInOrSignUpResponse>> {
println!(">> HANDLER: signin_handler called");
// check if the payload is empty
if payload.email.is_empty() || payload.password.is_empty() {
return Err(Error::InvalidPayload {
message: "Invalid payload".to_string(),
});
}

match sign_in(&state.mongo_client, payload).await {
Ok(res) => Ok(res),
match Auth::sign_in(&state.mongo_client, &payload.email, &payload.password).await {
Ok(res) => Ok(Json(res)),
Err(e) => Err(e),
}
}
Expand All @@ -44,12 +74,9 @@ pub async fn signout_handler(
}

match Session::revoke(&state.mongo_client, &payload.session_id).await {
Ok(_) => Ok(Json(
RevokeSessionsResult {
message: "Session revoked successfully".to_string(),
}
)),
Ok(_) => Ok(Json(RevokeSessionsResult {
message: "Session revoked successfully".to_string(),
})),
Err(e) => Err(e),
}

}
56 changes: 35 additions & 21 deletions src/handlers/user_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,18 +150,25 @@ pub async fn get_user_email_handler(
payload: Json<UserEmailPayload>,
) -> Result<Json<UserResponse>> {
println!(">> HANDLER: get_user_by_email_handler called");
if payload.email.is_empty() {
return Err(Error::InvalidPayload {
message: "Invalid payload".to_string(),
});
}

match User::get_from_email(&state.mongo_client, &payload.email).await {
Ok(user) => return Ok(Json(UserResponse {
uid: user.uid,
email: user.email,
name: user.name,
role: user.role,
is_active: user.is_active,
email_verified: user.email_verified,
created_at: user.created_at,
updated_at: user.updated_at,
})),
Ok(user) => {
return Ok(Json(UserResponse {
uid: user.uid,
email: user.email,
name: user.name,
role: user.role,
is_active: user.is_active,
email_verified: user.email_verified,
created_at: user.created_at,
updated_at: user.updated_at,
}))
}
Err(e) => return Err(e),
}
}
Expand All @@ -172,18 +179,25 @@ pub async fn get_user_id_handler(
payload: Json<UserIdPayload>,
) -> Result<Json<UserResponse>> {
println!(">> HANDLER: get_user_by_id handler called");
if payload.uid.is_empty() {
return Err(Error::InvalidPayload {
message: "Invalid payload".to_string(),
});
}

match User::get_from_uid(&state.mongo_client, &payload.uid).await {
Ok(user) => return Ok(Json(UserResponse {
uid: user.uid,
email: user.email,
name: user.name,
role: user.role,
is_active: user.is_active,
email_verified: user.email_verified,
created_at: user.created_at,
updated_at: user.updated_at,
})),
Ok(user) => {
return Ok(Json(UserResponse {
uid: user.uid,
email: user.email,
name: user.name,
role: user.role,
is_active: user.is_active,
email_verified: user.email_verified,
created_at: user.created_at,
updated_at: user.updated_at,
}))
}
Err(e) => return Err(e),
}
}
Expand All @@ -210,7 +224,7 @@ pub async fn delete_user_handler(
return Ok(Json(UserEmailResponse {
message: "User deleted".to_string(),
email: payload.email.to_owned(),
}))
}));
}
Err(e) => return Err(e),
}
Expand Down
Loading

0 comments on commit 0309e3c

Please sign in to comment.