Redirect anonymous user from authenticated pages

This commit is contained in:
Pierre HUBERT 2022-04-02 17:44:10 +02:00
parent 9e72e6a044
commit 91fd763fe1
3 changed files with 51 additions and 15 deletions

View File

@ -18,4 +18,13 @@ pub const MAX_SESSION_DURATION: i64 = 3600 * 6;
pub const MIN_PASS_LEN: usize = 4; pub const MIN_PASS_LEN: usize = 4;
/// The name of the cookie used to store session information /// The name of the cookie used to store session information
pub const SESSION_COOKIE_NAME: &str = "auth-cookie"; 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";

View File

@ -19,7 +19,7 @@ impl Default for SessionStatus {
#[derive(Debug, Serialize, Deserialize, Default)] #[derive(Debug, Serialize, Deserialize, Default)]
struct SessionIdentityData { pub struct SessionIdentityData {
pub id: UserID, pub id: UserID,
pub is_admin: bool, pub is_admin: bool,
pub status: SessionStatus, pub status: SessionStatus,
@ -28,17 +28,12 @@ struct SessionIdentityData {
pub struct SessionIdentity<'a>(pub &'a Identity); pub struct SessionIdentity<'a>(pub &'a Identity);
impl<'a> SessionIdentity<'a> { impl<'a> SessionIdentity<'a> {
pub fn set_user(&self, user: &User) { fn get_session_data(&self) -> Option<SessionIdentityData> {
self.set_session_data(&SessionIdentityData { Self::deserialize_session_data(self.0.identity())
id: user.uid.clone(),
is_admin: user.admin,
status: SessionStatus::SignedIn,
});
} }
fn get_session_data(&self) -> Option<SessionIdentityData> { pub fn deserialize_session_data(data: Option<String>) -> Option<SessionIdentityData> {
let res: Option<SessionIdentityData> = self.0.identity() let res: Option<SessionIdentityData> = data.as_deref()
.as_deref()
.map(serde_json::from_str) .map(serde_json::from_str)
.map(|f| match f { .map(|f| match f {
Ok(d) => Some(d), Ok(d) => Some(d),
@ -66,6 +61,14 @@ impl<'a> SessionIdentity<'a> {
self.0.remember(s); 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) { pub fn set_status(&self, status: SessionStatus) {
let mut sess = self.get_session_data().unwrap_or_default(); let mut sess = self.get_session_data().unwrap_or_default();
sess.status = status; sess.status = status;

View File

@ -8,6 +8,10 @@ use actix_identity::RequestIdentity;
use actix_web::{dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, Error, HttpResponse}; use actix_web::{dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, Error, HttpResponse};
use actix_web::body::EitherBody; 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. // There are two steps in middleware processing.
// 1. Middleware initialization, middleware factory gets called with // 1. Middleware initialization, middleware factory gets called with
// next service in chain as parameter. // next service in chain as parameter.
@ -41,6 +45,16 @@ enum SessionStatus {
Admin, 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<S> { pub struct AuthInnerMiddleware<S> {
service: Rc<S>, service: Rc<S>,
} }
@ -60,8 +74,6 @@ impl<S, B> Service<ServiceRequest> for AuthInnerMiddleware<S>
forward_ready!(service); forward_ready!(service);
fn call(&self, req: ServiceRequest) -> Self::Future { fn call(&self, req: ServiceRequest) -> Self::Future {
println!("Hi from start. You requested: {}", req.path());
let service = Rc::clone(&self.service); let service = Rc::clone(&self.service);
// Forward request // Forward request
@ -74,8 +86,20 @@ impl<S, B> Service<ServiceRequest> for AuthInnerMiddleware<S>
)); ));
} }
let identity = req.get_identity(); let identity = match SessionIdentity::deserialize_session_data(req.get_identity()) {
println!("identity: {:?}", 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 service
.call(req) .call(req)