use std::convert::TryFrom; use std::future::{ready, Ready}; use std::time::{Duration, SystemTime}; use actix_web::dev::Payload; use actix_web::http::header::LOCATION; use actix_web::http::Uri; use actix_web::{FromRequest, HttpRequest, HttpResponse}; use lettre::Address; use rand::{thread_rng, Fill}; pub struct Session(actix_session::Session); impl FromRequest for Session { type Config = ::Config; type Error = ::Error; type Future = Ready>; fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { ready( actix_session::Session::from_request(req, payload) .into_inner() .map(Self), ) } } impl Session { pub fn init(&self, email: &Address) { self.0.clear(); self.0 .insert("email", email) .expect("email serialization to work"); let mut buf: [u8; 32] = [0; 32]; buf.try_fill(&mut thread_rng()).expect("rng to fill buf"); self.0 .insert( "expires", SystemTime::now() + Duration::from_secs(60 * 60 * 24), ) .expect("setting expiration to work"); } pub fn purge(&self) { self.0.purge(); } pub fn validate_or_redirect(&self, redirect_to: &Uri) -> Result<(), HttpResponse> { if self.expired() { self.0.clear(); self.set_redirect_url(redirect_to); Err(HttpResponse::SeeOther() .insert_header((LOCATION, "/login")) .finish()) } else { Ok(()) } } pub fn expired(&self) -> bool { self.0 .get("expires") .ok() .flatten() .map_or(true, |expires: SystemTime| expires < SystemTime::now()) } pub fn get_redirect_url(&self) -> Option { self.0 .remove("redirect_to") .and_then(|v| Uri::try_from(&v).ok()) } pub fn set_redirect_url(&self, url: &Uri) { self.0 .insert("redirect_to", url.to_string()) .expect("setting a str to work"); } pub fn email(&self) -> Option
{ self.0.get("email").ok().flatten() } }