Create middleware.rs
use actix_web::{
dev::Payload, error::ErrorUnauthorized, web, FromRequest, HttpRequest,
};
use jsonwebtoken::{decode, DecodingKey, Validation};
use std::{env, future::Ready, future::ready};
use crate::routes::user::Claims;
pub struct JwtClaims(pub Claims);
impl FromRequest for JwtClaims {
type Error = actix_web::Error;
type Future = Ready<Result<Self, Self::Error>>;
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
let auth_header = req.headers().get("Authorization");
if let Some(header_value) = auth_header {
if let Ok(token) = header_value.to_str() {
let secret = env::var("SECRET_KEY").expect("JWT_SECRET must be set");
let decoding_key = DecodingKey::from_secret(secret.as_bytes());
let validation = Validation::default();
match decode::<Claims>(token, &decoding_key, &validation) {
Ok(token_data) => {
return ready(Ok(JwtClaims(token_data.claims)));
}
Err(e) => {
eprintln!("JWT decoding error: {:?}", e);
return ready(Err(ErrorUnauthorized("Invalid JWT token")));
}
}
}
}
ready(Err(ErrorUnauthorized("Authorization header missing or invalid")))
}
}
#[derive(Serialize, Deserialize)]
pub struct GetUserResponse {
pub username: String,
}
pub async fn get_user(data: web::Data<Store>, claims: JwtClaims) -> Result<web::Json<GetUserResponse>> {
let store = data.into_inner();
let user = store.get_user_by_id(claims.0.sub).await.map_err(|e| actix_web::error::ErrorInternalServerError(e.to_string()))?;
Ok(web::Json(GetUserResponse { username: user.user.username }))
}
pub async fn get_user_by_id(&self, id: String) -> Result<GetUserResponse> {
let user = sqlx::query_as!(User, "SELECT id, username, password FROM users WHERE id = $1", Uuid::parse_str(&id)?)
.fetch_one(&self.pool)
.await?;
Ok(GetUserResponse {
user: user,
})
}
}