use rustlavel::prelude::*;
use crate::support::settings::Settings;
use crate::support::{page, tokens};
const LAST_SEEN: &str = "last_seen";
const GRANULARITY: i64 = 60;
pub struct IdleTimeout;
impl Middleware for IdleTimeout {
fn handle(&self, request: Request, next: Next) -> BoxFuture<Response> {
Box::pin(async move {
let minutes = timeout_minutes(&request).await;
let now = tokens::unix_now();
if let Some(session) = request.try_session() {
let last_seen = session.get(LAST_SEEN).and_then(|v| v.as_f64()).unwrap_or(0.0) as i64;
if minutes > 0 && last_seen > 0 && now - last_seen > minutes * 60 {
Guard::new(session.clone()).logout();
page::flash(&request, "info", "You were signed out after a period of inactivity.");
return Response::see_other("/login");
}
if now - last_seen >= GRANULARITY {
session.put(LAST_SEEN, Json::from(now as f64));
}
}
next.run(request).await
})
}
}
async fn timeout_minutes(req: &Request) -> i64 {
let raw = match req.state::<Settings>() {
Some(settings) => settings.get("auth.session.timeout").await,
None => req.config().string("auth.session.timeout", "0"),
};
raw.parse::<i64>().unwrap_or(0).max(0)
}