feat: get refresh token

This commit is contained in:
Sebastian Pravda 2022-10-28 10:36:14 +02:00
parent a58cf73acc
commit 9378dcbead
No known key found for this signature in database
GPG key ID: F3BC84F08EFA3F57
5 changed files with 86 additions and 5 deletions

View file

@ -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<candidate::Model>) ->
Ok(plain_text_password)
}
#[get("/refresh")]
async fn refresh_token(conn: Connection<'_, Db>, token_req: Result<TokenRequest, Status>) -> Result<String, Custom<String>> {
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 = "<login_form>")]
async fn login(conn: Connection<'_, Db>, login_form: Json<LoginRequest>) -> Result<String, Custom<String>> {
let db = conn.into_inner();
@ -72,7 +84,13 @@ async fn whoami(conn: Connection<'_, Db>, token_req: Result<TokenRequest, Status
let user = CandidateService::authenticate_candidate(db, token).await;
match user {
Ok(user) => 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

View file

@ -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<String, argon2::password_hash::Error> {
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());
}

View file

@ -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::Model, DbErr> {
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
}
}

View file

@ -1 +1,2 @@
pub mod candidate_service;
pub mod candidate_service;
pub mod session_service;

View file

@ -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<String, ServiceError> {
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())
}
}