Added authentication with token and deleting expired user. Plus, constants for how long tokens should be expired for

This commit is contained in:
franklinblanco 2022-07-07 11:45:50 -04:00
parent 19fdedc49e
commit aaa91cc330
4 changed files with 84 additions and 26 deletions

View File

@ -0,0 +1,4 @@
DELETE FROM token
where
TIMESTAMPDIFF(DAY, NOW(), last_updated) > ? AND
TIMESTAMPDIFF(DAY, NOW(), time_created) > ?

View File

@ -1,13 +1,20 @@
use sqlx::{MySqlConnection, mysql::MySqlQueryResult}; use sqlx::{MySqlConnection, mysql::MySqlQueryResult};
use crate::r#do::token::Token; 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<MySqlQueryResult, sqlx::Error> { pub async fn insert_token(conn: &mut MySqlConnection, token: &Token) -> Result<MySqlQueryResult, sqlx::Error> {
sqlx::query_file!("sql/schema/token/insert.sql", token.user_id, token.auth_token, token.refresh_token).execute(conn).await 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<Token, sqlx::Error> { pub async fn get_tokens_with_user_id(conn: &mut MySqlConnection, user_id: &i32) -> Result<Vec<Token>, sqlx::Error> {
sqlx::query_file_as!(Token, "sql/schema/token/find_with_user_id.sql", user_id).fetch_one(conn).await 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<MySqlQueryResult, sqlx::Error> { pub async fn update_token_with_id(conn: &mut MySqlConnection, token: &Token ) -> Result<MySqlQueryResult, sqlx::Error> {
sqlx::query_file_as!(Token, "sql/schema/token/update.sql", token.auth_token, token.refresh_token, token.id).execute(conn).await 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<MySqlQueryResult, sqlx::Error>{
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
}

View File

@ -1,5 +1,9 @@
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use serde::{Serialize, Deserialize}; 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)] #[derive(Serialize, Deserialize)]
pub struct Token { pub struct Token {
pub id: i32, pub id: i32,

View File

@ -121,9 +121,44 @@ pub async fn authenticate_user_with_password(incoming_user: web::Json<UserForLog
pub async fn _authenticate_user_with_auth_token(){} pub async fn _authenticate_user_with_auth_token(request: HttpRequest, user_id: web::Path<i32>, db_conn: Data<Mutex<MySqlConnection>>) -> HttpResponse{
let mut message_resources: Vec<MessageResourceDto> = 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}")] #[patch("/user/refresh/{user_id}")]
pub async fn refresh_auth_token(request: HttpRequest, user_id: web::Path<i32>, db_conn: Data<Mutex<MySqlConnection>>) -> HttpResponse{ pub async fn refresh_auth_token(request: HttpRequest, user_id: web::Path<i32>, db_conn: Data<Mutex<MySqlConnection>>) -> HttpResponse{
let mut message_resources: Vec<MessageResourceDto> = Vec::new(); let mut message_resources: Vec<MessageResourceDto> = Vec::new();
@ -141,33 +176,41 @@ pub async fn refresh_auth_token(request: HttpRequest, user_id: web::Path<i32>, d
message_resources.push(MessageResourceDto::new_from_error_message(ERROR_MISSING_TOKEN)); message_resources.push(MessageResourceDto::new_from_error_message(ERROR_MISSING_TOKEN));
return HttpResponse::BadRequest().json(web::Json(message_resources)); 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 = let mut persisted_token =
match token_dao::get_token_with_user_id(&mut db_conn.lock().unwrap(), &user_id).await { match token_dao::get_tokens_with_user_id(&mut db_conn.lock().unwrap(), &user_id).await {
Ok(token) => {token}, Ok(tokens) => {
let mut matched_token: Option<Token> = 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) => { Err(err) if matches!(err, sqlx::Error::RowNotFound) => {
println!("{}", err);
return HttpResponse::NotFound().json(web::Json(message_resources)); return HttpResponse::NotFound().json(web::Json(message_resources));
} }
Err(err) => { Err(err) => {
println!("{}", err); println!("{}", err);
return HttpResponse::InternalServerError().json(web::Json(message_resources)); 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 persisted_token.refresh_token == refresh_token{ match update_token_with_id(&mut db_conn.lock().unwrap(), &persisted_token).await {
true => { Ok(_rs) => {
persisted_token.auth_token = generate_multiple_random_token_with_rng(1).await.expect("msg").get(0).expect("msg").to_string(); return HttpResponse::Ok().json(web::Json(persisted_token));
match update_token_with_id(&mut db_conn.lock().unwrap(), &persisted_token).await { },
Ok(_rs) => { Err(err) => {
return HttpResponse::Ok().json(web::Json(persisted_token)); println!("{}", err);
}, return HttpResponse::InternalServerError().json(web::Json(message_resources));
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));
}};
} }