diff --git a/ffplayout-api/src/api/routes.rs b/ffplayout-api/src/api/routes.rs index 6e0c65e9..fd6d1e69 100644 --- a/ffplayout-api/src/api/routes.rs +++ b/ffplayout-api/src/api/routes.rs @@ -32,6 +32,7 @@ use regex::Regex; use serde::{Deserialize, Serialize}; use simplelog::*; use sqlx::{Pool, Sqlite}; +use tokio::task; use crate::db::{ handles, @@ -160,40 +161,48 @@ pub async fn login(pool: web::Data>, credentials: web::Json) let conn = pool.into_inner(); match handles::select_login(&conn, &credentials.username).await { Ok(mut user) => { - let pass = user.password.clone(); - let hash = PasswordHash::new(&pass).unwrap(); - user.password = "".into(); + let role = handles::select_role(&conn, &user.role_id.unwrap_or_default()) + .await + .unwrap_or(Role::Guest); + + let res = task::spawn_blocking(move || { + let pass = user.password.clone(); + let hash = PasswordHash::new(&pass).unwrap(); + user.password = "".into(); + + if Argon2::default() + .verify_password(credentials.password.as_bytes(), &hash) + .is_ok() + { + let claims = Claims::new(user.id, user.username.clone(), role.clone()); + + if let Ok(token) = create_jwt(claims) { + user.token = Some(token); + }; + + info!("user {} login, with role: {role}", credentials.username); + + web::Json(UserObj { + message: "login correct!".into(), + user: Some(user), + }) + .customize() + .with_status(StatusCode::OK) + } else { + error!("Wrong password for {}!", credentials.username); + + web::Json(UserObj { + message: "Wrong password!".into(), + user: None, + }) + .customize() + .with_status(StatusCode::FORBIDDEN) + } + }) + .await + .unwrap(); - if Argon2::default() - .verify_password(credentials.password.as_bytes(), &hash) - .is_ok() - { - let role = handles::select_role(&conn, &user.role_id.unwrap_or_default()) - .await - .unwrap_or(Role::Guest); - let claims = Claims::new(user.id, user.username.clone(), role.clone()); - - if let Ok(token) = create_jwt(claims) { - user.token = Some(token); - }; - - info!("user {} login, with role: {role}", credentials.username); - - web::Json(UserObj { - message: "login correct!".into(), - user: Some(user), - }) - .customize() - .with_status(StatusCode::OK) - } else { - error!("Wrong password for {}!", credentials.username); - web::Json(UserObj { - message: "Wrong password!".into(), - user: None, - }) - .customize() - .with_status(StatusCode::FORBIDDEN) - } + res } Err(e) => { error!("Login {} failed! {e}", credentials.username); diff --git a/ffplayout-api/src/db/handles.rs b/ffplayout-api/src/db/handles.rs index 1ecee715..7bbf6846 100644 --- a/ffplayout-api/src/db/handles.rs +++ b/ffplayout-api/src/db/handles.rs @@ -8,6 +8,7 @@ use argon2::{ use rand::{distributions::Alphanumeric, Rng}; use simplelog::*; use sqlx::{migrate::MigrateDatabase, sqlite::SqliteQueryResult, Pool, Sqlite}; +use tokio::task; use crate::db::{ db_pool, @@ -243,17 +244,23 @@ pub async fn insert_user( conn: &Pool, user: User, ) -> Result { - let salt = SaltString::generate(&mut OsRng); - let password_hash = Argon2::default() - .hash_password(user.password.clone().as_bytes(), &salt) - .unwrap(); + let password_hash = task::spawn_blocking(move || { + let salt = SaltString::generate(&mut OsRng); + let hash = Argon2::default() + .hash_password(user.password.clone().as_bytes(), &salt) + .unwrap(); + + hash.to_string() + }) + .await + .unwrap(); let query = "INSERT INTO user (mail, username, password, role_id) VALUES($1, $2, $3, $4)"; sqlx::query(query) .bind(user.mail) .bind(user.username) - .bind(password_hash.to_string()) + .bind(password_hash) .bind(user.role_id) .execute(conn) .await