diff --git a/db/auth_copy_2.sqlite b/db/auth_copy_2.sqlite index 312fa53..80bbf23 100644 Binary files a/db/auth_copy_2.sqlite and b/db/auth_copy_2.sqlite differ diff --git a/db/auth_copy_2.sqlite-shm b/db/auth_copy_2.sqlite-shm index 9c010b0..3564af8 100644 Binary files a/db/auth_copy_2.sqlite-shm and b/db/auth_copy_2.sqlite-shm differ diff --git a/db/auth_copy_2.sqlite-wal b/db/auth_copy_2.sqlite-wal index 26eb4de..3f04b9d 100644 Binary files a/db/auth_copy_2.sqlite-wal and b/db/auth_copy_2.sqlite-wal differ diff --git a/src/main.rs b/src/main.rs index 7ab429b..3a391c6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -92,7 +92,7 @@ std::panic::set_hook(Box::new(|info| { let app = create_router(state) .layer(Extension(jwt_keys)); - let listener = TcpListener::bind("0.0.0.0:8080").await?; + let listener = TcpListener::bind("0.0.0.0:7080").await?; serve(listener, app).into_future().await?; Ok(()) } diff --git a/src/utils/auth.rs b/src/utils/auth.rs index 1a48ecf..cef5cba 100644 --- a/src/utils/auth.rs +++ b/src/utils/auth.rs @@ -436,7 +436,7 @@ pub async fn create_refresh_token( .map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "DB connection error".to_string()))?; - //TODO: prend id username password de users + // let mut stmt = conn.prepare( // "SELECT id, password FROM users WHERE username = ?1" @@ -468,7 +468,7 @@ pub async fn create_refresh_token( - //TODO: stmt, querry hotel-id dans hotel-user-link avec l'ID précédant + //TODO: get hotel name let mut stmt = match conn.prepare( "SELECt hotel_id FROM hotel_user_link WHERE user_id = ?1" ) { @@ -478,10 +478,7 @@ pub async fn create_refresh_token( //TODO: compiler les hotel id dans un vecteur pour le feed dans le refresh token //Deja fait ? - - - - let hotel_ids = match stmt + let hotel_ids: Vec = match stmt .query_map(params![&user_id],|row| row.get (0)) { Ok(rows) => rows.collect::,_>>() @@ -489,6 +486,13 @@ pub async fn create_refresh_token( Err(_) => return Err((StatusCode::INTERNAL_SERVER_ERROR, "Error mapping hotel_ids".to_string())), }; + let hotel_ids_json = match serde_json::to_string(&hotel_ids) { + Ok(json) => json, + Err(_) => return Err((StatusCode::INTERNAL_SERVER_ERROR, "Error mapping hotel_ids".to_string())), + }; + + + /*.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "Error mapping hotel_ids".to_string())); */ conn.execute( "INSERT INTO refresh_token (user_id, token_hash, device_id, user_agent, hotel_id_list) @@ -498,7 +502,7 @@ pub async fn create_refresh_token( &hashed_token, &device_id_str, &user_agent_str, - &hotel_ids, + &hotel_ids_json, ], ).map_err(|e| { (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {}", e)) @@ -587,27 +591,35 @@ pub async fn login_refresh_token ( //deserializing the list : //let hotel_ids: Vec = serde_json::from_str(&stored_value)?; let mut stmt = match conn.prepare( - "SELECT user_id, token_hash, hotel_id + "SELECT user_id, token_hash, hotel_id_list FROM refresh_token - WHERE device_id = ?1 AND user_agent = ?2" + WHERE device_id = ?1 AND user_agent = ?2 " ) { Ok(s) => s, Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "DB query error").into_response(), }; - let rows = match stmt.query_map(params![&device_id_str, &user_agent_str], |row| { + let rows = match stmt.query_one(params![&device_id_str, &user_agent_str], |row| { Ok(( row.get::<_, i32>(0)?, // user_id row.get::<_, String>(1)?, // token_hash - row.get::<_, i32>(2)?, // hotel_id + row.get::<_, String>(2)?, // hotel_id //FIXME: this is supposed to be vectore maybe ? )) }) { Ok(r) => r, Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "DB query error").into_response(), }; + //TODO: extraction of the blob + //let json_hotel_ids = rows.2; + let (user_id, saved_hash,json_hotel_ids) = rows; + let hotel_ids: Vec = match serde_json::from_str(&json_hotel_ids) { + Ok(ids) => ids, + Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Hotel ids are not deserializable to Vec").into_response(), + + }; - +/* let mut entries = Vec::new(); for r in rows { match r { @@ -615,27 +627,51 @@ pub async fn login_refresh_token ( Err(_) => continue, // ignore corrupt rows } } + */ - if entries.is_empty() { + if hotel_ids.is_empty() { return (StatusCode::UNAUTHORIZED, "No matching device").into_response(); } + if !verify_password(&payload.refresh_token, &saved_hash) { + // skip rows with wrong hash + return (StatusCode::UNAUTHORIZED, "Invelid credentials").into_response(); + } + + let expiration = match chrono::Utc::now().checked_add_signed(chrono::Duration::hours(15)) { + Some(time) => time.timestamp() as usize, + None => { + // Handle overflow — probably a 500, since this should never happen + return (StatusCode::INTERNAL_SERVER_ERROR, "Time overflow".to_string()).into_response(); + } + }; + let mut tokens = Vec::new(); - //FIXME: swap to "for hotel_id in entries" // interator over vector list + for hotel_id in hotel_ids { + let claims = serde_json::json!({ + "id": user_id, + "hotel_id": hotel_id, + "exp": expiration + }); + + let token = match encode(&Header::default(), &claims, &keys.encoding) { + Ok(token) => token, + Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "JWT creation failed").into_response(), + }; + + tokens.push(token); + } + + /* OLD ITERATION OVER MULTIPLE REFRESH TOKEN + // swap to "for hotel_id in entries" // interator over vector list for (user_id, token_hash, hotel_id) in entries { if !verify_password(&payload.refresh_token, &token_hash) { // skip rows with wrong hash continue; } //FIXME: single expiration - let expiration = match chrono::Utc::now().checked_add_signed(chrono::Duration::hours(15)) { - Some(time) => time.timestamp() as usize, - None => { - // Handle overflow — probably a 500, since this should never happen - return (StatusCode::INTERNAL_SERVER_ERROR, "Time overflow".to_string()).into_response(); - } - }; + let claims = serde_json::json!({ "id": user_id, @@ -650,14 +686,15 @@ pub async fn login_refresh_token ( tokens.push(token); } + */ - -if tokens.is_empty() { - return (StatusCode::UNAUTHORIZED, "Invalid or mismatched token").into_response(); -} + if tokens.is_empty() { + return (StatusCode::UNAUTHORIZED, "Invalid or mismatched token").into_response(); + } //Json(tokens).into_response() Json(MultiLoginResponse { tokens }).into_response() + } pub async fn logout_from_single_device (