diff --git a/sql/schema/user/find_with_id.sql b/sql/schema/user/find_with_id.sql new file mode 100644 index 0000000..522d7f0 --- /dev/null +++ b/sql/schema/user/find_with_id.sql @@ -0,0 +1,3 @@ +SELECT * +FROM user +WHERE user.id = ? \ No newline at end of file diff --git a/src/dao/main_dao.rs b/src/dao/main_dao.rs index af26feb..7b27013 100644 --- a/src/dao/main_dao.rs +++ b/src/dao/main_dao.rs @@ -1,8 +1,8 @@ use std::collections::HashMap; -use sqlx::{MySqlConnection, Connection}; +use sqlx::{MySqlPool}; -pub async fn start_database_connection(env_vars: &HashMap) -> Result{ +pub async fn start_database_connection(env_vars: &HashMap) -> Result{ let db_user = match env_vars.get("DB_USER") { Some(str) => str, None => panic!("DB_USER env var not found") @@ -20,9 +20,9 @@ pub async fn start_database_connection(env_vars: &HashMap) -> Re None => panic!("DB_DATABASE_NAME env var not found") }; let formatted_db_url = &format!("mysql://{db_user}:{db_pass}@{db_host}/{db_database_name}"); - sqlx::MySqlConnection::connect(&formatted_db_url).await + sqlx::MySqlPool::connect(&formatted_db_url).await } -pub async fn run_all_migrations(conn: &mut MySqlConnection){ +pub async fn run_all_migrations(conn: &MySqlPool){ match sqlx::migrate!("./migrations").run(conn).await { Ok(()) => {println!("{}", "Successfully ran migrations.")}, Err(error) => {panic!("{error}")} diff --git a/src/dao/token_dao.rs b/src/dao/token_dao.rs index d260a2f..5cbb23c 100644 --- a/src/dao/token_dao.rs +++ b/src/dao/token_dao.rs @@ -1,18 +1,19 @@ -use sqlx::{MySqlConnection, mysql::MySqlQueryResult}; +use sqlx::MySqlPool; +use sqlx::{mysql::MySqlQueryResult}; use crate::r#do::token::Token; use crate::r#do::token::{AUTH_TOKEN_EXPIRATION_TIME_IN_DAYS, REFRESH_TOKEN_EXPIRATION_TIME_IN_DAYS}; -pub async fn insert_token(conn: &mut MySqlConnection, token: &Token) -> Result { +pub async fn insert_token(conn: &MySqlPool, token: &Token) -> Result { sqlx::query_file!("sql/schema/token/insert.sql", token.user_id, token.auth_token, token.refresh_token).execute(conn).await } -pub async fn get_tokens_with_user_id(conn: &mut MySqlConnection, user_id: &i32) -> Result, sqlx::Error> { +pub async fn get_tokens_with_user_id(conn: &MySqlPool, user_id: &i32) -> Result, sqlx::Error> { sqlx::query_file_as!(Token, "sql/schema/token/find_with_user_id.sql", user_id).fetch_all(conn).await } -pub async fn update_token_with_id(conn: &mut MySqlConnection, token: &Token ) -> Result { +pub async fn update_token_with_id(conn: &MySqlPool, token: &Token ) -> Result { sqlx::query_file!("sql/schema/token/update.sql", token.auth_token, token.refresh_token, token.id).execute(conn).await } -pub async fn delete_expired_tokens(conn: &mut MySqlConnection) -> Result{ +pub async fn delete_expired_tokens(conn: &MySqlPool) -> Result{ sqlx::query_file!("sql/schema/token/delete_expired_tokens.sql", AUTH_TOKEN_EXPIRATION_TIME_IN_DAYS, REFRESH_TOKEN_EXPIRATION_TIME_IN_DAYS) .execute(conn).await diff --git a/src/dao/user_dao.rs b/src/dao/user_dao.rs index ac31438..ebf8771 100644 --- a/src/dao/user_dao.rs +++ b/src/dao/user_dao.rs @@ -1,15 +1,18 @@ -use sqlx::{MySqlConnection, mysql::MySqlQueryResult}; +use sqlx::{mysql::MySqlQueryResult, MySqlPool}; use crate::r#do::user::User; -pub async fn insert_user(conn: &mut MySqlConnection, user_to_insert: &User) -> Result{ +pub async fn insert_user(conn: &MySqlPool, user_to_insert: &User) -> Result{ sqlx::query_file!("sql/schema/user/insert.sql", user_to_insert.app, user_to_insert.email, user_to_insert.name, user_to_insert.password, user_to_insert.salt) .execute(conn).await } -pub async fn find_user_by_email(conn: &mut MySqlConnection, email: &String, app: &String) -> Result{ +pub async fn find_user_by_email(conn: &MySqlPool, email: &String, app: &String) -> Result{ sqlx::query_file_as!(User, "sql/schema/user/find_with_email.sql", email, app).fetch_one(conn).await } +pub async fn _find_user_by_id(conn: &MySqlPool, id: &i32) -> Result { + sqlx::query_file_as!(User, "sql/schema/user/find_with_id.sql", id).fetch_one(conn).await +} //pub async fn _update_user(conn: &mut MySqlConnection, user_to_modify: &User) -> Result<(), sqlx::Error>{ // Ok(()) //} diff --git a/src/do/shared_state.rs b/src/do/shared_state.rs index a125f7b..9557390 100644 --- a/src/do/shared_state.rs +++ b/src/do/shared_state.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; -use sqlx::MySqlConnection; +use sqlx::{MySqlPool}; pub struct SharedStateObj{ - pub db_conn: MySqlConnection, + pub db_conn: MySqlPool, pub env_vars: HashMap, } \ No newline at end of file diff --git a/src/routes/main_router.rs b/src/routes/main_router.rs index c49fb29..29141b2 100644 --- a/src/routes/main_router.rs +++ b/src/routes/main_router.rs @@ -1,4 +1,4 @@ -use std::sync::Mutex; +use std::sync::{Mutex, Arc}; use actix_web::{HttpServer, App, web}; use crate::r#do::shared_state::SharedStateObj; use super::user_routes; @@ -29,9 +29,8 @@ pub async fn start_all_routes(after_startup_fn_call: &dyn Fn(), state: SharedSta // Extract variables to be put into shared app state & clone them - let db_conn_state = web::Data::new(Mutex::new(state.db_conn)); + let db_conn_state = web::Data::new(Arc::new(state.db_conn)); let env_vars_state = web::Data::new(Mutex::new(state.env_vars.clone())); - // Start server code that turns into a future to be executed below let server_future = HttpServer::new( move || { App::new() diff --git a/src/routes/user_routes.rs b/src/routes/user_routes.rs index bb52da9..1ab0346 100644 --- a/src/routes/user_routes.rs +++ b/src/routes/user_routes.rs @@ -1,14 +1,14 @@ use core::panic; -use std::{sync::Mutex}; +use std::{sync::{Arc}}; use actix_web::{web::{self, Data}, HttpResponse, post, patch, HttpRequest}; use chrono::{Utc}; -use sqlx::MySqlConnection; +use sqlx::{MySqlPool}; use crate::{r#do::user::User, dao::{user_dao::{insert_user, find_user_by_email}, token_dao::{insert_token, self, update_token_with_id}}, dto::{user_dtos::{UserForCreationDto, UserForLoginDto}, message_resources_dtos::MessageResourceDto}, validation::user_validator, util::hasher::{self, generate_multiple_random_token_with_rng}, r#do::token::Token, resources::error_messages::{ERROR_USER_ALREADY_EXISTS, ERROR_USER_DOES_NOT_EXIST, ERROR_PASSWORD_INCORRECT, ERROR_INVALID_TOKEN, ERROR_MISSING_TOKEN, ERROR_INCORRECT_TOKEN, ERROR_EXPIRED_TOKEN}, r#do::token::AUTH_TOKEN_EXPIRATION_TIME_IN_DAYS, r#do::token::REFRESH_TOKEN_EXPIRATION_TIME_IN_DAYS}; #[post("/user")] -pub async fn create_user(incoming_user: web::Json, db_conn: Data>) -> HttpResponse { +pub async fn create_user(incoming_user: web::Json, db_conn: Data>) -> HttpResponse { let mut message_resources: Vec = Vec::new(); // Get user object from json @@ -23,7 +23,7 @@ pub async fn create_user(incoming_user: web::Json, db_conn: user_validator::validate_user_for_creation(incoming_user_obj, &mut message_resources); // Find if user exists - match find_user_by_email(&mut db_conn.lock().unwrap(), &user_to_insert.email, &user_to_insert.app).await{ + match find_user_by_email(&db_conn, &user_to_insert.email, &user_to_insert.app).await{ Ok(_usr) => { message_resources.push(MessageResourceDto::new_from_error_message(ERROR_USER_ALREADY_EXISTS)); return HttpResponse::BadRequest().json(web::Json(message_resources)); @@ -40,7 +40,7 @@ pub async fn create_user(incoming_user: web::Json, db_conn: user_to_insert.salt = hash_result.salt; // Insert user in DB - match insert_user(&mut db_conn.lock().unwrap(), &user_to_insert).await{ + match insert_user(&db_conn, &user_to_insert).await{ Ok(resultrs) => { user_to_insert.id = resultrs.last_insert_id() as i32; }, @@ -58,7 +58,7 @@ pub async fn create_user(incoming_user: web::Json, db_conn: ); // Insert token in DB - match insert_token(&mut db_conn.lock().unwrap(), &token_to_insert).await{ + match insert_token(&db_conn, &token_to_insert).await{ Ok(resultrs) => {token_to_insert.id = resultrs.last_insert_id() as i32}, Err(e) => {panic!("{e}")} } @@ -68,7 +68,7 @@ pub async fn create_user(incoming_user: web::Json, db_conn: } #[post("/user/auth/password")] -pub async fn authenticate_user_with_password(incoming_user: web::Json, db_conn: Data>) -> HttpResponse { +pub async fn authenticate_user_with_password(incoming_user: web::Json, db_conn: Data>) -> HttpResponse { let mut message_resources: Vec = Vec::new(); let incoming_user_obj = incoming_user.0; @@ -79,7 +79,7 @@ pub async fn authenticate_user_with_password(incoming_user: web::Json 0 { return HttpResponse::BadRequest().json(web::Json(message_resources)); } // If user exists get it, if it doesn't blow up to the client - let persisted_user = match find_user_by_email(&mut db_conn.lock().unwrap(), &incoming_user_obj.email, &incoming_user_obj.app).await { + let persisted_user = match find_user_by_email(&db_conn, &incoming_user_obj.email, &incoming_user_obj.app).await { Ok(rs) => {rs}, Err(_e) => { message_resources.push(MessageResourceDto::new_from_error_message(ERROR_USER_DOES_NOT_EXIST)); @@ -104,7 +104,7 @@ pub async fn authenticate_user_with_password(incoming_user: web::Json {token_to_insert.id = resultrs.last_insert_id() as i32}, Err(e) => {panic!("{e}")} }; @@ -113,7 +113,7 @@ pub async fn authenticate_user_with_password(incoming_user: web::Json, db_conn: Data>) -> HttpResponse{ +pub async fn authenticate_user_with_auth_token(request: HttpRequest, user_id: web::Path, db_conn: Data>) -> HttpResponse{ let mut message_resources: Vec = Vec::new(); let headers = request.headers(); let auth_token = match headers.get("auth-token") { @@ -130,11 +130,11 @@ pub async fn authenticate_user_with_auth_token(request: HttpRequest, user_id: we return HttpResponse::BadRequest().json(web::Json(message_resources)); }}; - match token_dao::delete_expired_tokens(&mut db_conn.lock().unwrap()).await + match token_dao::delete_expired_tokens(&db_conn).await { Ok(_res) => {}, Err(_err) => {} }; let mut _persisted_token = - match token_dao::get_tokens_with_user_id(&mut db_conn.lock().unwrap(), &user_id).await { + match token_dao::get_tokens_with_user_id(&db_conn, &user_id).await { Ok(tokens) => { for token in tokens{ let now = Utc::now().naive_utc(); @@ -161,7 +161,7 @@ pub async fn authenticate_user_with_auth_token(request: HttpRequest, user_id: we } #[patch("/user/refresh/{user_id}")] -pub async fn refresh_auth_token(request: HttpRequest, user_id: web::Path, db_conn: Data>) -> HttpResponse{ +pub async fn refresh_auth_token(request: HttpRequest, user_id: web::Path, db_conn: Data>) -> HttpResponse{ let mut message_resources: Vec = Vec::new(); let headers = request.headers(); let refresh_token = match headers.get("refresh-token") { @@ -178,11 +178,11 @@ pub async fn refresh_auth_token(request: HttpRequest, user_id: web::Path, d return HttpResponse::BadRequest().json(web::Json(message_resources)); }}; - match token_dao::delete_expired_tokens(&mut db_conn.lock().unwrap()).await + match token_dao::delete_expired_tokens(&db_conn).await { Ok(_res) => {}, Err(_err) => {} }; let mut persisted_token = - match token_dao::get_tokens_with_user_id(&mut db_conn.lock().unwrap(), &user_id).await { + match token_dao::get_tokens_with_user_id(&db_conn, &user_id).await { Ok(tokens) => { let mut matched_token: Option = None; for token in tokens{ @@ -209,7 +209,7 @@ pub async fn refresh_auth_token(request: HttpRequest, user_id: web::Path, d return HttpResponse::InternalServerError().json(web::Json(message_resources)); }}; persisted_token.auth_token = generate_multiple_random_token_with_rng(1).await.expect("msg").get(0).expect("msg").to_string(); - match update_token_with_id(&mut db_conn.lock().unwrap(), &persisted_token).await { + match update_token_with_id(&db_conn, &persisted_token).await { Ok(_rs) => { return HttpResponse::Ok().json(web::Json(persisted_token)); },