diff --git a/sql/schema/token/delete_expired_tokens.sql b/sql/schema/token/delete_expired_tokens.sql new file mode 100644 index 0000000..6d6ffcb --- /dev/null +++ b/sql/schema/token/delete_expired_tokens.sql @@ -0,0 +1,4 @@ +DELETE FROM token +where +TIMESTAMPDIFF(DAY, NOW(), last_updated) > ? AND +TIMESTAMPDIFF(DAY, NOW(), time_created) > ? \ No newline at end of file diff --git a/src/dao/token_dao.rs b/src/dao/token_dao.rs index a2aef62..d9edf2a 100644 --- a/src/dao/token_dao.rs +++ b/src/dao/token_dao.rs @@ -1,13 +1,20 @@ use sqlx::{MySqlConnection, 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 { sqlx::query_file!("sql/schema/token/insert.sql", token.user_id, token.auth_token, token.refresh_token).execute(conn).await } -pub async fn get_token_with_user_id(conn: &mut MySqlConnection, user_id: &i32) -> Result { - sqlx::query_file_as!(Token, "sql/schema/token/find_with_user_id.sql", user_id).fetch_one(conn).await +pub async fn get_tokens_with_user_id(conn: &mut MySqlConnection, 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 { - 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 + 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{ + 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/do/token.rs b/src/do/token.rs index b043e66..6d65dc6 100644 --- a/src/do/token.rs +++ b/src/do/token.rs @@ -1,5 +1,9 @@ use chrono::NaiveDateTime; use serde::{Serialize, Deserialize}; + +pub const AUTH_TOKEN_EXPIRATION_TIME_IN_DAYS:i32 = 1; +pub const REFRESH_TOKEN_EXPIRATION_TIME_IN_DAYS: i32 = 20; + #[derive(Serialize, Deserialize)] pub struct Token { pub id: i32, diff --git a/src/routes/user_routes.rs b/src/routes/user_routes.rs index 6dc81ab..ed5c098 100644 --- a/src/routes/user_routes.rs +++ b/src/routes/user_routes.rs @@ -121,9 +121,44 @@ 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 auth_token = match headers.get("auth-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)); + }}; + + match token_dao::delete_expired_tokens(&mut db_conn.lock().unwrap()).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 { + Ok(tokens) => { + for token in tokens{ + if token.auth_token == auth_token{ return HttpResponse::Ok().finish(); } + }; + message_resources.push(MessageResourceDto::new_from_error_message(ERROR_INCORRECT_TOKEN)); + return HttpResponse::Unauthorized().json(web::Json(message_resources)); + }, + Err(err) if matches!(err, sqlx::Error::RowNotFound) => { + return HttpResponse::NotFound().json(web::Json(message_resources)); + } + Err(err) => { + println!("{}", err); + return HttpResponse::InternalServerError().json(web::Json(message_resources)); + }}; +} -//TODO: Change auth token in db when this is used. #[patch("/user/refresh/{user_id}")] pub async fn refresh_auth_token(request: HttpRequest, user_id: web::Path, db_conn: Data>) -> HttpResponse{ let mut message_resources: Vec = Vec::new(); @@ -141,33 +176,41 @@ pub async fn refresh_auth_token(request: HttpRequest, user_id: web::Path, d message_resources.push(MessageResourceDto::new_from_error_message(ERROR_MISSING_TOKEN)); return HttpResponse::BadRequest().json(web::Json(message_resources)); }}; + + match token_dao::delete_expired_tokens(&mut db_conn.lock().unwrap()).await + { Ok(_res) => {}, Err(_err) => {} }; let mut persisted_token = - match token_dao::get_token_with_user_id(&mut db_conn.lock().unwrap(), &user_id).await { - Ok(token) => {token}, + match token_dao::get_tokens_with_user_id(&mut db_conn.lock().unwrap(), &user_id).await { + Ok(tokens) => { + let mut matched_token: Option = None; + for token in tokens{ + if token.refresh_token == refresh_token{ + matched_token = Some(token); + } + }; + match matched_token { + Some(token) => {token}, + None => { + message_resources.push(MessageResourceDto::new_from_error_message(ERROR_INCORRECT_TOKEN)); + return HttpResponse::Unauthorized().json(web::Json(message_resources)); + } + } + }, 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)); - }}; + 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)); + }}; } \ No newline at end of file