use rustlavel::prelude::*;
use crate::models::user::User;
use crate::support::page;
pub const EPOCH_KEY: &str = "_epoch";
pub struct SessionEpoch;
impl Middleware for SessionEpoch {
fn handle(&self, request: Request, next: Next) -> BoxFuture<Response> {
Box::pin(async move {
if stale(&request).await {
if let Some(session) = request.try_session() {
Guard::new(session.clone()).logout();
}
page::flash(
&request,
"info",
"You were signed out because the password on this account was changed.",
);
return Response::see_other("/login");
}
next.run(request).await
})
}
}
async fn stale(request: &Request) -> bool {
let Some(identity) = request.identity() else { return false };
let Some(user_id) = identity.id_as::<i64>() else { return false };
let Some(db) = request.state::<Database>() else { return false };
let Ok(Some(user)) = User::find(db, user_id).await else { return false };
let Some(current) = user.session_epoch else { return false };
let held = request
.try_session()
.and_then(|session| session.get_string(EPOCH_KEY));
held.as_deref() != Some(current.as_str())
}