diff --git a/sql/schema/token/update.sql b/sql/schema/token/update.sql index e69de29..8685f22 100644 --- a/sql/schema/token/update.sql +++ b/sql/schema/token/update.sql @@ -0,0 +1,3 @@ +UPDATE token +SET last_updated = NOW(), auth_token = ?, refresh_token = ? +WHERE id = ? \ No newline at end of file diff --git a/src/dao/token_dao.rs b/src/dao/token_dao.rs index dc0d8f1..a2aef62 100644 --- a/src/dao/token_dao.rs +++ b/src/dao/token_dao.rs @@ -7,4 +7,7 @@ pub async fn insert_token(conn: &mut MySqlConnection, token: &Token) -> Result Result { sqlx::query_file_as!(Token, "sql/schema/token/find_with_user_id.sql", user_id).fetch_one(conn).await +} +pub async fn update_token_with_id(conn: &mut MySqlConnection, token: &Token ) -> Result { + sqlx::query_file_as!(Token, "sql/schema/token/update.sql", token.auth_token, token.refresh_token, token.id).execute(conn).await } \ No newline at end of file diff --git a/src/resources/error_messages.rs b/src/resources/error_messages.rs index 7a721a5..1630c3d 100644 --- a/src/resources/error_messages.rs +++ b/src/resources/error_messages.rs @@ -11,4 +11,10 @@ pub const ERROR_USER_ALREADY_EXISTS: (&str, &str) = ("ERROR.USER_ALREADY_EXISTS" pub const ERROR_USER_DOES_NOT_EXIST: (&str, &str) = ("ERROR.USER_DOES_NOT_EXIST", "User with this email does not exist."); -pub const ERROR_PASSWORD_INCORRECT: (&str, &str) = ("ERROR.PASSWORD_INCORRECT", "THe password you have entered is incorrect."); \ No newline at end of file +pub const ERROR_PASSWORD_INCORRECT: (&str, &str) = ("ERROR.PASSWORD_INCORRECT", "The password you have entered is incorrect."); + +pub const ERROR_INVALID_TOKEN: (&str, &str) = ("ERROR.INVALID_TOKEN", "The token you have supplied is not formattable."); + +pub const ERROR_INCORRECT_TOKEN: (&str, &str) = ("ERROR.INCORRECT_TOKEN", "The token you have supplied does not belong to this user."); + +pub const ERROR_MISSING_TOKEN: (&str, &str) = ("ERROR.MISSING_TOKEN", "No token supplied."); \ No newline at end of file diff --git a/src/routes/main_router.rs b/src/routes/main_router.rs index 638e5c0..702224f 100644 --- a/src/routes/main_router.rs +++ b/src/routes/main_router.rs @@ -40,6 +40,7 @@ pub async fn start_all_routes(after_startup_fn_call: &dyn Fn(), state: SharedSta .app_data(env_vars_state.clone()) .service(user_routes::create_user) .service(user_routes::authenticate_user_with_password) + .service(user_routes::refresh_auth_token) //.service(user_routes::get_user_from_db) }) .bind((host_addr, host_port))? diff --git a/src/routes/user_routes.rs b/src/routes/user_routes.rs index 2043933..6dc81ab 100644 --- a/src/routes/user_routes.rs +++ b/src/routes/user_routes.rs @@ -1,10 +1,10 @@ use core::panic; -use std::sync::Mutex; +use std::{sync::Mutex}; -use actix_web::{web::{self, Data}, HttpResponse, post}; +use actix_web::{web::{self, Data}, HttpResponse, post, patch, HttpRequest}; use sqlx::MySqlConnection; -use crate::{r#do::user::User, dao::{user_dao::{insert_user, find_user_by_email}, token_dao::insert_token}, 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}}; +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}}; /*#[get("/u&ser/{id}")] pub async fn get_user_from_db(id: Path, db_conn: Data>) -> HttpResponse { @@ -118,3 +118,56 @@ pub async fn authenticate_user_with_password(incoming_user: web::Json, db_conn: Data>) -> HttpResponse{ + let mut message_resources: Vec = Vec::new(); + let headers = request.headers(); + let refresh_token = match headers.get("refresh-token") { + Some(token) => { + match token.to_str(){ + Ok(value) => {value}, + Err(e) => { + println!("{}", e); + message_resources.push(MessageResourceDto::new_from_error_message(ERROR_INVALID_TOKEN)); + return HttpResponse::BadRequest().json(web::Json(message_resources)); + }}}, + None => { + message_resources.push(MessageResourceDto::new_from_error_message(ERROR_MISSING_TOKEN)); + return HttpResponse::BadRequest().json(web::Json(message_resources)); + }}; + + let mut persisted_token = + match token_dao::get_token_with_user_id(&mut db_conn.lock().unwrap(), &user_id).await { + Ok(token) => {token}, + Err(err) if matches!(err, sqlx::Error::RowNotFound) => { + println!("{}", err); + return HttpResponse::NotFound().json(web::Json(message_resources)); + } + Err(err) => { + println!("{}", err); + return HttpResponse::InternalServerError().json(web::Json(message_resources)); + }}; + + match persisted_token.refresh_token == refresh_token{ + true => { + 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 { + Ok(_rs) => { + return HttpResponse::Ok().json(web::Json(persisted_token)); + }, + Err(err) => { + println!("{}", err); + return HttpResponse::InternalServerError().json(web::Json(message_resources)); + }}; + }, + false => { + message_resources.push(MessageResourceDto::new_from_error_message(ERROR_INCORRECT_TOKEN)); + return HttpResponse::Unauthorized().json(web::Json(message_resources)); + }}; +} \ No newline at end of file