diff --git a/src/utils/auth.rs b/src/utils/auth.rs
index 62c349d..dce120f 100644
--- a/src/utils/auth.rs
+++ b/src/utils/auth.rs
@@ -1,75 +1,87 @@
use std::time::Duration;
use axum::{
body::{to_bytes, Body},
- http::{Request as HttpRequest, StatusCode},
+ http::{Request as HttpRequest, StatusCode, },
+ http::request::Parts,
middleware::Next,
response::{Response, IntoResponse},
Json,
- extract::{Path, State, FromRequest}
+ extract::{Path, State, FromRequest, FromRequestParts}
};
+use axum::extract::FromRef;
use axum::extract::Request as ExtractRequest;
-use jsonwebtoken::{decode, DecodingKey, Validation, encode, EncodingKey, Header};
+use jsonwebtoken::{decode, DecodingKey, Validation, encode, EncodingKey, Header, Algorithm};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use chrono::{Utc};
use rusqlite::{params, Connection, OptionalExtension};
+use async_trait::async_trait;
-
+use rand_core::OsRng;
+use argon2::{
+ password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
+ Argon2};
//use crate::utils::db_pool::;
use crate::utils::db_pool::{HotelPool,AppState};
-
-use rand_core::OsRng;
-use argon2::{
- password_hash::{
- PasswordHash, PasswordHasher, PasswordVerifier, SaltString
- },
- Argon2
-};
-
-
-pub async fn auth_middleware(
- mut req: HttpRequest
,
- next: Next,
-) -> Result {
- // buffer body
- let body = std::mem::take(req.body_mut());
-
- // Buffer into bytes
- let bytes = to_bytes(body, 1024 * 1024)
- .await
- .map_err(|_| StatusCode::BAD_REQUEST)?;
-
-
- // parse JSON as generic `Value`
- let value: Value = serde_json::from_slice(&bytes)
- .map_err(|_| StatusCode::BAD_REQUEST)?;
-
- // pull out token
- let token = value
- .get("token")
- .and_then(|t| t.as_str())
- .ok_or(StatusCode::UNAUTHORIZED)?;
-
- // verify token
- let key = DecodingKey::from_secret("your_jwt_secret_key".as_ref());
- let validation = Validation::default();
- let claims = decode::(token, &key, &validation)
- .map_err(|_| StatusCode::UNAUTHORIZED)?
- .claims;
-
- // inject claims for downstream handlers
- req.extensions_mut().insert(claims);
-
- // restore the original body so the handler can parse it into *its own* struct
- req = req.map(|_| Body::from(bytes));
-
-
- Ok(next.run(req).await)
+pub async fn token_tester(
+ State(state): State,
+ AuthClaims { user_id, hotel_id, username }: AuthClaims,
+) -> impl IntoResponse {
+ format!(
+ "Hello {} (user_id: {}) from hotel {}",
+ username, user_id, hotel_id
+ )
}
+pub struct AuthUser(pub Claims); //??
+#[derive(Debug, Clone)]
+pub struct AuthClaims {
+ pub user_id: i32,
+ pub hotel_id: i32,
+ pub username: String,
+}
+
+impl FromRequestParts for AuthClaims
+where
+ S: Send + Sync + 'static,
+ AppState: Clone + Send + Sync + 'static, AppState: FromRef
+ {
+ type Rejection = (StatusCode, String);
+
+ async fn from_request_parts(parts: &mut Parts, state: &S) -> Result {
+ // We assume your state has a `jwt_secret` field
+
+ // 1️⃣ Extract the token from the Authorization header
+ let auth_header = parts
+ .headers
+ .get("Authorization")
+ .ok_or((StatusCode::UNAUTHORIZED, "Missing Authorization header".to_string()))?
+ .to_str()
+ .map_err(|_| (StatusCode::BAD_REQUEST, "Invalid Authorization header".to_string()))?;
+
+ // Bearer token?
+ let token = auth_header
+ .strip_prefix("Bearer ")
+ .ok_or((StatusCode::BAD_REQUEST, "Expected Bearer token".to_string()))?;
+
+ // 2️⃣ Decode the token
+ let token_data = decode::(
+ token,
+ &DecodingKey::from_secret("your_jwt_secret_key s".to_string().as_ref()),
+ &Validation::new(Algorithm::HS256),
+ ).map_err(|_| (StatusCode::UNAUTHORIZED, "Invalid token".to_string()))?;
+
+ Ok(AuthClaims {
+ user_id: token_data.claims.id,
+ hotel_id: token_data.claims.hotel_id,
+ username: token_data.claims.username,
+ })
+
+ }
+}
// Hash a new password
fn hash_password(password: &str) -> anyhow::Result {
@@ -172,63 +184,6 @@ struct LoginResponse {
token: String,
}
-//pub async fn auth_register();
-/*
-pub async fn auth_loggin(
- // State(hotel_pools): State,
- LoginPayload(payload): LoginPayload,
-) -> impl IntoResponse {
-
- let pool = .get_pool(payload.hotel_id);
- let conn = pool.get().unwrap();
- /*
- let conn = match pool.get() {
- Ok(conn) => conn,
- Err(err) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Pool error: {err}")),
- };
-*/
- let mut statement = conn
- .prepare("SELECT id, displayname, hotel_id FROM users WHERE username = ? 1 AND password = ?2 ")
- .unwrap();
-
- let user_row = statement
- .query_row(params![&payload.username, &payload.password], |row| {
- let id: i32 = row.get(0)?;
- let displayname: String = row.get(1)?;
- let hotel_id: i32 = row.get(2)?;
- Ok((id, displayname, hotel_id))
- })
- .optional()
- .unwrap(); // returns Ok(Some(...)) or Ok(None)
-
- if let Some((id, displayname, hotel_id)) = user_row {
- let expiration = chrono::Utc::now()
- .checked_add_signed(chrono::Duration::minutes(15))
- .unwrap()
- .timestamp() as usize;
-
- let claims = Claims {
- id,
- hotel_id,
- username: displayname, // or payload.username if you prefer
- exp: expiration,
- };
-
- let token = encode(
- &Header::default(),
- &claims,
- &EncodingKey::from_secret("TEST".as_bytes()),
- )
- .unwrap();
-
- return (StatusCode::OK, Json(LoginResponse { token }));
- }
- // Fallback if login failed — wrap String in Json or use axum::Json
- return (StatusCode::UNAUTHORIZED, Json(LoginResponse { token: "".to_string() }));
-}
-
-*/
-
pub async fn clean_auth_loging(
State(state): State,
LoginPayload(payload): LoginPayload
diff --git a/src/utils/routes.rs b/src/utils/routes.rs
index 7a55a28..6974982 100644
--- a/src/utils/routes.rs
+++ b/src/utils/routes.rs
@@ -4,7 +4,7 @@ use axum::{
};
use crate::utils::auth::*;
-use crate::utils::db_pool::{HotelPool, AppState};
+use crate::utils::db_pool::{HotelPool, AppState, };
// ROOTS
@@ -13,5 +13,6 @@ pub fn utils_routes() -> Router {
Router::new()
.route("/login", put(clean_auth_loging))
.route("/register", put(register_user))
+ .route("/tokentest", put(token_tester))
//.with_state(state)
}
\ No newline at end of file