From 91fd763fe19bb91f7e82113b681caed279b0ef50 Mon Sep 17 00:00:00 2001 From: Pierre Hubert Date: Sat, 2 Apr 2022 17:44:10 +0200 Subject: [PATCH] Redirect anonymous user from authenticated pages --- src/constants.rs | 11 +++++++++- src/data/session_identity.rs | 23 +++++++++++---------- src/middlewares/auth_middleware.rs | 32 ++++++++++++++++++++++++++---- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index e653971..93c7d20 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -18,4 +18,13 @@ pub const MAX_SESSION_DURATION: i64 = 3600 * 6; pub const MIN_PASS_LEN: usize = 4; /// The name of the cookie used to store session information -pub const SESSION_COOKIE_NAME: &str = "auth-cookie"; \ No newline at end of file +pub const SESSION_COOKIE_NAME: &str = "auth-cookie"; + +/// Authenticated routes prefix +pub const AUTHENTICATED_ROUTES: &str = "/settings"; + +/// Admin routes prefix +pub const ADMIN_ROUTES: &str = "/admin"; + +/// Auth route +pub const LOGIN_ROUTE: &str = "/login"; \ No newline at end of file diff --git a/src/data/session_identity.rs b/src/data/session_identity.rs index 0e85656..10877e9 100644 --- a/src/data/session_identity.rs +++ b/src/data/session_identity.rs @@ -19,7 +19,7 @@ impl Default for SessionStatus { #[derive(Debug, Serialize, Deserialize, Default)] -struct SessionIdentityData { +pub struct SessionIdentityData { pub id: UserID, pub is_admin: bool, pub status: SessionStatus, @@ -28,17 +28,12 @@ struct SessionIdentityData { pub struct SessionIdentity<'a>(pub &'a Identity); impl<'a> SessionIdentity<'a> { - pub fn set_user(&self, user: &User) { - self.set_session_data(&SessionIdentityData { - id: user.uid.clone(), - is_admin: user.admin, - status: SessionStatus::SignedIn, - }); + fn get_session_data(&self) -> Option { + Self::deserialize_session_data(self.0.identity()) } - fn get_session_data(&self) -> Option { - let res: Option = self.0.identity() - .as_deref() + pub fn deserialize_session_data(data: Option) -> Option { + let res: Option = data.as_deref() .map(serde_json::from_str) .map(|f| match f { Ok(d) => Some(d), @@ -66,6 +61,14 @@ impl<'a> SessionIdentity<'a> { self.0.remember(s); } + pub fn set_user(&self, user: &User) { + self.set_session_data(&SessionIdentityData { + id: user.uid.clone(), + is_admin: user.admin, + status: SessionStatus::SignedIn, + }); + } + pub fn set_status(&self, status: SessionStatus) { let mut sess = self.get_session_data().unwrap_or_default(); sess.status = status; diff --git a/src/middlewares/auth_middleware.rs b/src/middlewares/auth_middleware.rs index b52d3cb..62aac5b 100644 --- a/src/middlewares/auth_middleware.rs +++ b/src/middlewares/auth_middleware.rs @@ -8,6 +8,10 @@ use actix_identity::RequestIdentity; use actix_web::{dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, Error, HttpResponse}; use actix_web::body::EitherBody; +use crate::constants::{ADMIN_ROUTES, AUTHENTICATED_ROUTES, LOGIN_ROUTE}; +use crate::controllers::base_controller::redirect_user; +use crate::data::session_identity::{SessionIdentity, SessionIdentityData}; + // There are two steps in middleware processing. // 1. Middleware initialization, middleware factory gets called with // next service in chain as parameter. @@ -41,6 +45,16 @@ enum SessionStatus { Admin, } +impl SessionStatus { + pub fn is_auth(&self) -> bool { + !matches!(self, SessionStatus::SignedOut) + } + + pub fn is_admin(&self) -> bool { + matches!(self, SessionStatus::Admin) + } +} + pub struct AuthInnerMiddleware { service: Rc, } @@ -60,8 +74,6 @@ impl Service for AuthInnerMiddleware forward_ready!(service); fn call(&self, req: ServiceRequest) -> Self::Future { - println!("Hi from start. You requested: {}", req.path()); - let service = Rc::clone(&self.service); // Forward request @@ -74,8 +86,20 @@ impl Service for AuthInnerMiddleware )); } - let identity = req.get_identity(); - println!("identity: {:?}", identity); + let identity = match SessionIdentity::deserialize_session_data(req.get_identity()) { + None => SessionStatus::SignedOut, + Some(SessionIdentityData { is_admin: true, .. }) => SessionStatus::Admin, + _ => SessionStatus::RegularUser, + }; + + // Redirect user to login page + if !identity.is_auth() && (req.path().starts_with(ADMIN_ROUTES) || + req.path().starts_with(AUTHENTICATED_ROUTES)) { + return Ok(req.into_response(redirect_user(LOGIN_ROUTE)) + .map_into_right_body()); + } + + // TODO : restrict access to admin pages service .call(req)