From 9378dcbead6d46d1c7477bb1fdb5aa89404eeea7 Mon Sep 17 00:00:00 2001 From: Sebastian Pravda Date: Fri, 28 Oct 2022 10:36:14 +0200 Subject: [PATCH] feat: get refresh token --- api/src/lib.rs | 22 ++++++++++++++++++++-- core/src/crypto.rs | 16 ++++++++++++++++ core/src/mutation.rs | 23 +++++++++++++++++++++-- core/src/services/mod.rs | 3 ++- core/src/services/session_service.rs | 27 +++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 core/src/services/session_service.rs diff --git a/api/src/lib.rs b/api/src/lib.rs index b4d16c9..1dde6de 100644 --- a/api/src/lib.rs +++ b/api/src/lib.rs @@ -4,6 +4,7 @@ extern crate rocket; use guard::candidate_jwt::TokenRequest; use portfolio_core::error::ServiceError; use portfolio_core::services::candidate_service::CandidateService; +use portfolio_core::services::session_service::SessionService; use requests::LoginRequest; use rocket::http::Status; use rocket::{Rocket, Build}; @@ -45,6 +46,17 @@ async fn create(conn: Connection<'_, Db>, post_form: Json) -> Ok(plain_text_password) } +#[get("/refresh")] +async fn refresh_token(conn: Connection<'_, Db>, token_req: Result) -> Result> { + let db = conn.into_inner(); + let jwt = token_req.ok().unwrap().to_token(); + + let refresh_token = SessionService::new_refresh_token(db, jwt.application_id).await; + + Ok(refresh_token.ok().unwrap()) + +} + #[post("/login", data = "")] async fn login(conn: Connection<'_, Db>, login_form: Json) -> Result> { let db = conn.into_inner(); @@ -72,7 +84,13 @@ async fn whoami(conn: Connection<'_, Db>, token_req: Result Ok(format!("{} {}", user.name.unwrap(), user.surname.unwrap())), + Ok(user) => Ok( + format!("{} {} {}", + user.application, + user.name.unwrap_or("".to_owned()), + user.surname.unwrap_or("".to_owned()) + ) + ), Err(e) => Err(custom_err_from_service_err(e)), } } @@ -94,7 +112,7 @@ async fn start() -> Result<(), rocket::Error> { .attach(Db::init()) .attach(AdHoc::try_on_ignite("Migrations", run_migrations)) //.mount("/", FileServer::from(relative!("/static"))) - .mount("/", routes![create, login, hello, whoami]) + .mount("/", routes![create, login, hello, whoami, refresh_token]) .register("/", catchers![]) .launch() .await diff --git a/core/src/crypto.rs b/core/src/crypto.rs index 7047e55..73778e7 100644 --- a/core/src/crypto.rs +++ b/core/src/crypto.rs @@ -2,6 +2,7 @@ use argon2::{ Argon2, PasswordHasher as ArgonPasswordHasher, PasswordVerifier as ArgonPasswordVerifier, }; use rand::Rng; +use sha2::{Sha256, Digest}; /// Foolproof random 8 char string @@ -28,6 +29,14 @@ pub fn random_8_char_string() -> String { s } +pub fn hash_sha256(s: String) -> String { + let mut hasher = Sha256::new(); + hasher.update(s); + let result = hasher.finalize(); + format!("{result:x}") + +} + pub fn hash_password(password_plaint_text: &str) -> Result { let password = password_plaint_text.as_bytes(); let salt = "c2VjcmV0bHl0ZXN0aW5nZXZlcnl0aGluZw"; @@ -51,3 +60,10 @@ pub fn verify_password( .verify_password(password_plaint_text.as_bytes(), &parsed_hash) .is_ok()); } + +#[test] +fn verify_password_test() { + let password = "test"; + let hash = hash_password(password).unwrap(); + assert!(verify_password(password, &hash).unwrap()); +} \ No newline at end of file diff --git a/core/src/mutation.rs b/core/src/mutation.rs index ac04626..9bc32bf 100644 --- a/core/src/mutation.rs +++ b/core/src/mutation.rs @@ -1,5 +1,6 @@ -use ::entity::{candidate}; -use sea_orm::*; +use chrono::Utc; +use ::entity::{candidate, session}; +use sea_orm::{*, prelude::Uuid}; use crate::crypto::hash_password; pub struct Mutation; @@ -24,4 +25,22 @@ impl Mutation { .insert(db) .await } + + + pub async fn insert_session( + db: &DbConn, + user_id: i32, + random_uuid: Uuid, + hashed_jwt: String + ) -> Result { + session::ActiveModel { + id: Set(random_uuid), + hashed_token: Set(hashed_jwt), + user_id: Set(user_id), + created_at: Set(Utc::now().naive_local()), + updated_at: Set(Utc::now().naive_local()), + } + .insert(db) + .await + } } diff --git a/core/src/services/mod.rs b/core/src/services/mod.rs index 1992ce2..1bafcbb 100644 --- a/core/src/services/mod.rs +++ b/core/src/services/mod.rs @@ -1 +1,2 @@ -pub mod candidate_service; \ No newline at end of file +pub mod candidate_service; +pub mod session_service; \ No newline at end of file diff --git a/core/src/services/session_service.rs b/core/src/services/session_service.rs new file mode 100644 index 0000000..dade2b4 --- /dev/null +++ b/core/src/services/session_service.rs @@ -0,0 +1,27 @@ +use sea_orm::{prelude::Uuid, DbConn}; + +use crate::{token::{generate_candidate_token}, Query, error::{USER_NOT_FOUND_ERROR, DB_ERROR, ServiceError}, crypto::hash_sha256, Mutation}; + +pub struct SessionService; + +impl SessionService { + pub async fn new_refresh_token(db: &DbConn, id: i32) -> Result { + let candidate = match Query::find_candidate_by_id(db, id).await { + Ok(candidate) => match candidate { + Some(candidate) => candidate, + None => return Err(USER_NOT_FOUND_ERROR) + }, + Err(_) => {return Err(DB_ERROR)} + }; + let random_uuid: Uuid = Uuid::new_v4(); + + let jwt = generate_candidate_token(candidate); + + let session = match Mutation::insert_session(db, id, random_uuid, hash_sha256(jwt)).await { + Ok(session) => session, + Err(_) => return Err(DB_ERROR) + }; + + Ok(session.id.to_string()) + } +} \ No newline at end of file