From 87982fd48068d5cc53a65d8bb3bac33a473d361f Mon Sep 17 00:00:00 2001 From: SquidSpirit Date: Fri, 1 Aug 2025 17:40:13 +0800 Subject: [PATCH 1/5] BLOG-86 fix: redis URL in session configuration to use correct localhost address --- backend/server/src/configuration/session.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/server/src/configuration/session.rs b/backend/server/src/configuration/session.rs index 5eb8ff1..ba4ec8f 100644 --- a/backend/server/src/configuration/session.rs +++ b/backend/server/src/configuration/session.rs @@ -20,7 +20,7 @@ impl SessionConfiguration { let session_key = Key::from(&session_key_bytes); let redis_url = - std::env::var("REDIS_URL").unwrap_or_else(|_| "redis://127.0.1:6379".to_string()); + std::env::var("REDIS_URL").unwrap_or_else(|_| "redis://127.0.0.1:6379".to_string()); Self { session_key, -- 2.47.2 From 0e8eb809a525538fbe1c239a469b63edf617ba16 Mon Sep 17 00:00:00 2001 From: SquidSpirit Date: Fri, 1 Aug 2025 17:40:34 +0800 Subject: [PATCH 2/5] BLOG-86 feat: implement authentication middleware and update routes for user session management --- backend/feature/auth/src/framework/web.rs | 1 + .../auth/src/framework/web/auth_middleware.rs | 49 +++++++++++++++++++ .../auth/src/framework/web/auth_web_routes.rs | 15 ++++-- backend/server/src/main.rs | 7 ++- 4 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 backend/feature/auth/src/framework/web/auth_middleware.rs diff --git a/backend/feature/auth/src/framework/web.rs b/backend/feature/auth/src/framework/web.rs index 8853d00..54b1487 100644 --- a/backend/feature/auth/src/framework/web.rs +++ b/backend/feature/auth/src/framework/web.rs @@ -1,3 +1,4 @@ +pub mod auth_middleware; pub mod auth_web_routes; mod constants; diff --git a/backend/feature/auth/src/framework/web/auth_middleware.rs b/backend/feature/auth/src/framework/web/auth_middleware.rs new file mode 100644 index 0000000..ac183a4 --- /dev/null +++ b/backend/feature/auth/src/framework/web/auth_middleware.rs @@ -0,0 +1,49 @@ +use std::future::{self, Ready}; + +use actix_session::SessionExt; +use actix_web::{ + Error, FromRequest, HttpMessage, HttpRequest, + body::MessageBody, + dev::{Payload, ServiceRequest, ServiceResponse}, + error::ErrorUnauthorized, + middleware::Next, +}; + +use crate::framework::web::constants::SESSION_KEY_USER_ID; + +pub async fn auth_middleware( + req: ServiceRequest, + next: Next, +) -> Result, Error> { + let session = req.get_session(); + let user_id = session.get::(SESSION_KEY_USER_ID); + + if user_id.is_err() { + return next.call(req).await; + } + + let user_id = user_id.unwrap(); + if user_id.is_none() { + return next.call(req).await; + } + + let user_id = user_id.unwrap(); + req.extensions_mut().insert(user_id); + next.call(req).await +} + +pub struct UserId(pub i32); + +impl FromRequest for UserId { + type Error = Error; + type Future = Ready>; + + fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { + let user_id = req.extensions().get::().cloned(); + + match user_id { + Some(id) => future::ready(Ok(UserId(id))), + None => future::ready(Err(ErrorUnauthorized(""))), + } + } +} diff --git a/backend/feature/auth/src/framework/web/auth_web_routes.rs b/backend/feature/auth/src/framework/web/auth_web_routes.rs index f0ab70d..af43672 100644 --- a/backend/feature/auth/src/framework/web/auth_web_routes.rs +++ b/backend/feature/auth/src/framework/web/auth_web_routes.rs @@ -6,8 +6,9 @@ use crate::{ auth_controller::AuthController, oidc_callback_query_dto::OidcCallbackQueryDto, }, application::error::auth_error::AuthError, - framework::web::constants::{ - SESSION_KEY_AUTH_NONCE, SESSION_KEY_AUTH_STATE, SESSION_KEY_USER_ID, + framework::web::{ + auth_middleware::UserId, + constants::{SESSION_KEY_AUTH_NONCE, SESSION_KEY_AUTH_STATE, SESSION_KEY_USER_ID}, }, }; @@ -18,6 +19,8 @@ pub fn configure_auth_routes(cfg: &mut web::ServiceConfig) { .route("/callback", web::get().to(oidc_callback_handler)) .route("/logout", web::get().to(logout_handler)), ); + + cfg.service(web::resource("/me").route(web::get().to(get_logged_in_user_handler))); } async fn oidc_login_handler( @@ -92,10 +95,12 @@ async fn oidc_callback_handler( } async fn logout_handler(session: Session) -> impl Responder { - session.remove(SESSION_KEY_AUTH_STATE); - session.remove(SESSION_KEY_AUTH_NONCE); - session.remove(SESSION_KEY_USER_ID); + session.clear(); HttpResponse::Found() .append_header((header::LOCATION, "/")) .finish() } + +async fn get_logged_in_user_handler(user_id: UserId) -> impl Responder { + HttpResponse::Ok().body(format!("Logged in user ID: {}", user_id.0)) +} diff --git a/backend/server/src/main.rs b/backend/server/src/main.rs index 17fe620..52a36a4 100644 --- a/backend/server/src/main.rs +++ b/backend/server/src/main.rs @@ -5,9 +5,12 @@ use actix_web::{ App, Error, HttpServer, body::MessageBody, dev::{ServiceFactory, ServiceRequest, ServiceResponse}, + middleware::from_fn, web, }; -use auth::framework::web::auth_web_routes::configure_auth_routes; +use auth::framework::web::{ + auth_middleware::auth_middleware, auth_web_routes::configure_auth_routes, +}; use image::framework::web::image_web_routes::configure_image_routes; use openidconnect::reqwest; use post::framework::web::post_web_routes::configure_post_routes; @@ -63,6 +66,8 @@ fn create_app( let container = Container::new(db_pool, http_client, configuration); App::new() + // The middlewares are executed in opposite order as registration. + .wrap(from_fn(auth_middleware)) .wrap(session_middleware_builder.build()) .app_data(web::Data::from(container.auth_controller)) .app_data(web::Data::from(container.image_controller)) -- 2.47.2 From a72a567d6a36aa7eec66edd75aa9e8cedb8e4da3 Mon Sep 17 00:00:00 2001 From: SquidSpirit Date: Fri, 1 Aug 2025 17:46:50 +0800 Subject: [PATCH 3/5] BLOG-86 feat: add auth dependency and integrate UserId in image upload handler --- backend/Cargo.lock | 1 + backend/feature/image/Cargo.toml | 2 ++ backend/feature/image/src/framework/web/image_web_routes.rs | 2 ++ 3 files changed, 5 insertions(+) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index b9586a0..7ffa59d 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1664,6 +1664,7 @@ dependencies = [ "actix-multipart", "actix-web", "async-trait", + "auth", "futures", "log", "serde", diff --git a/backend/feature/image/Cargo.toml b/backend/feature/image/Cargo.toml index 0e6fc35..d7777cf 100644 --- a/backend/feature/image/Cargo.toml +++ b/backend/feature/image/Cargo.toml @@ -11,3 +11,5 @@ futures.workspace = true log.workspace = true serde.workspace = true sqlx.workspace = true + +auth.workspace = true diff --git a/backend/feature/image/src/framework/web/image_web_routes.rs b/backend/feature/image/src/framework/web/image_web_routes.rs index 4d0c206..e8ae4bb 100644 --- a/backend/feature/image/src/framework/web/image_web_routes.rs +++ b/backend/feature/image/src/framework/web/image_web_routes.rs @@ -1,5 +1,6 @@ use actix_multipart::Multipart; use actix_web::{HttpResponse, Responder, web}; +use auth::framework::web::auth_middleware::UserId; use futures::StreamExt; use crate::{ @@ -18,6 +19,7 @@ pub fn configure_image_routes(cfg: &mut web::ServiceConfig) { async fn upload_image_handler( image_controller: web::Data, mut payload: Multipart, + _: UserId, ) -> impl Responder { let mut image_request_dto: Option = None; -- 2.47.2 From eb7a3cf985fbcbbb962cd828df0d4f9b9e4d79ef Mon Sep 17 00:00:00 2001 From: SquidSpirit Date: Fri, 1 Aug 2025 18:05:47 +0800 Subject: [PATCH 4/5] BLOG-86 refactor: update UserId struct to encapsulate user ID and improve access method --- backend/feature/auth/src/framework/web/auth_middleware.rs | 8 +++++++- backend/feature/auth/src/framework/web/auth_web_routes.rs | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/backend/feature/auth/src/framework/web/auth_middleware.rs b/backend/feature/auth/src/framework/web/auth_middleware.rs index ac183a4..d7d720d 100644 --- a/backend/feature/auth/src/framework/web/auth_middleware.rs +++ b/backend/feature/auth/src/framework/web/auth_middleware.rs @@ -32,7 +32,13 @@ pub async fn auth_middleware( next.call(req).await } -pub struct UserId(pub i32); +pub struct UserId(i32); + +impl UserId { + pub fn get(&self) -> i32 { + self.0 + } +} impl FromRequest for UserId { type Error = Error; diff --git a/backend/feature/auth/src/framework/web/auth_web_routes.rs b/backend/feature/auth/src/framework/web/auth_web_routes.rs index af43672..2e06a6a 100644 --- a/backend/feature/auth/src/framework/web/auth_web_routes.rs +++ b/backend/feature/auth/src/framework/web/auth_web_routes.rs @@ -102,5 +102,5 @@ async fn logout_handler(session: Session) -> impl Responder { } async fn get_logged_in_user_handler(user_id: UserId) -> impl Responder { - HttpResponse::Ok().body(format!("Logged in user ID: {}", user_id.0)) + HttpResponse::Ok().body(format!("Logged in user ID: {}", user_id.get())) } -- 2.47.2 From 04c9d4dcf073cca02b4d5c2779a5a2bf576f6ceb Mon Sep 17 00:00:00 2001 From: SquidSpirit Date: Fri, 1 Aug 2025 18:24:02 +0800 Subject: [PATCH 5/5] BLOG-86 refactor: simplify auth middleware by removing unnecessary error handling and integrating user ID retrieval --- .../auth/src/framework/web/auth_middleware.rs | 36 ++++--------------- backend/server/src/main.rs | 6 +--- 2 files changed, 8 insertions(+), 34 deletions(-) diff --git a/backend/feature/auth/src/framework/web/auth_middleware.rs b/backend/feature/auth/src/framework/web/auth_middleware.rs index d7d720d..c1ff8d0 100644 --- a/backend/feature/auth/src/framework/web/auth_middleware.rs +++ b/backend/feature/auth/src/framework/web/auth_middleware.rs @@ -1,37 +1,10 @@ use std::future::{self, Ready}; use actix_session::SessionExt; -use actix_web::{ - Error, FromRequest, HttpMessage, HttpRequest, - body::MessageBody, - dev::{Payload, ServiceRequest, ServiceResponse}, - error::ErrorUnauthorized, - middleware::Next, -}; +use actix_web::{Error, FromRequest, HttpRequest, dev::Payload, error::ErrorUnauthorized}; use crate::framework::web::constants::SESSION_KEY_USER_ID; -pub async fn auth_middleware( - req: ServiceRequest, - next: Next, -) -> Result, Error> { - let session = req.get_session(); - let user_id = session.get::(SESSION_KEY_USER_ID); - - if user_id.is_err() { - return next.call(req).await; - } - - let user_id = user_id.unwrap(); - if user_id.is_none() { - return next.call(req).await; - } - - let user_id = user_id.unwrap(); - req.extensions_mut().insert(user_id); - next.call(req).await -} - pub struct UserId(i32); impl UserId { @@ -45,7 +18,12 @@ impl FromRequest for UserId { type Future = Ready>; fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { - let user_id = req.extensions().get::().cloned(); + let user_id_result = req.get_session().get::(SESSION_KEY_USER_ID); + + let user_id = match user_id_result { + Ok(id) => id, + _ => return future::ready(Err(ErrorUnauthorized(""))), + }; match user_id { Some(id) => future::ready(Ok(UserId(id))), diff --git a/backend/server/src/main.rs b/backend/server/src/main.rs index 52a36a4..adc4724 100644 --- a/backend/server/src/main.rs +++ b/backend/server/src/main.rs @@ -5,12 +5,9 @@ use actix_web::{ App, Error, HttpServer, body::MessageBody, dev::{ServiceFactory, ServiceRequest, ServiceResponse}, - middleware::from_fn, web, }; -use auth::framework::web::{ - auth_middleware::auth_middleware, auth_web_routes::configure_auth_routes, -}; +use auth::framework::web::auth_web_routes::configure_auth_routes; use image::framework::web::image_web_routes::configure_image_routes; use openidconnect::reqwest; use post::framework::web::post_web_routes::configure_post_routes; @@ -67,7 +64,6 @@ fn create_app( App::new() // The middlewares are executed in opposite order as registration. - .wrap(from_fn(auth_middleware)) .wrap(session_middleware_builder.build()) .app_data(web::Data::from(container.auth_controller)) .app_data(web::Data::from(container.image_controller)) -- 2.47.2