use std::time::Duration;
use anyhow::Result;
use cookie::Cookie;
use serde::{Deserialize, Serialize};
use cookie::time::{Duration as DurationCookie, OffsetDateTime};
use crate::session::cookie::utils::parse_encrypted_raw_cookie;
use crate::session::{Session, SessionManager};
use crate::response::Response;
use crate::request::Request;
pub(crate) mod utils;
use crate::utils::{
Values,
encrypt::encrypt,
string::string_fixed_length,
cookie::cookie_parse
};
pub struct SessionCookieManager {
expires: Duration,
cookie_name: String,
encryption_key: String,
}
impl SessionCookieManager {
pub fn new(expires: Duration, cookie_name: &str, encryption_key: &str) -> Self {
return Self {
expires: expires,
cookie_name: cookie_name.to_owned(),
encryption_key: string_fixed_length(encryption_key, 32),
};
}
}
#[derive(Debug, Default)]
pub(crate) struct SessionCookie {
pub(crate) values: Values,
pub(crate) errors: Values,
pub(crate) errors_old: Values,
pub(crate) old: Values,
pub(crate) old_new: Values,
pub(crate) flashes: Values,
pub(crate) flashes_new: Values,
}
impl SessionCookie {
pub(crate) fn new(values: Values, errors: Values, old: Values, flashes: Values) -> Self {
return Self {
values: values,
errors: errors,
errors_old: Values::new(),
old: old,
old_new: Values::new(),
flashes: flashes,
flashes_new: Values::new(),
}
}
}
#[deprecated]
pub fn new_session_manager(expires: Duration, cookie_name: &str, encryption_key: &str) -> impl SessionManager {
return SessionCookieManager {
expires: expires,
cookie_name: String::from(cookie_name),
encryption_key: string_fixed_length(encryption_key, 32),
};
}
#[derive(Serialize, Deserialize)]
pub(crate) struct CookieStorage {
pub values: Values,
pub errors: Values,
pub old: Values,
pub flashes: Values,
}
impl SessionManager for SessionCookieManager {
fn setup<'a>(&mut self, req: &'a mut Request, _res: &'a mut Response) -> Result<()> {
req.session = match cookie_parse(req.header("cookie")).unwrap().get(&self.cookie_name) {
Some(raw) => Some(Box::new(parse_encrypted_raw_cookie(self.encryption_key.to_owned(), raw).unwrap())),
None => Some(Box::new(SessionCookie::default())),
};
return Ok(())
}
fn teardown<'a>(&mut self, req: &'a mut Request, res: &'a mut Response) -> Result<()> {
unsafe {
let ptr = req.session.as_mut().unwrap() as *mut Box<dyn Session + 'static> as usize;
let session = &mut **(ptr as *mut Box<SessionCookie>);
let data = serde_json::to_string(&CookieStorage {
values: session.values.clone(),
errors: res.errors.clone(),
old: res.old.clone(),
flashes: res.flashes.clone(),
});
let payload = encrypt(self.encryption_key.as_str(), data.unwrap().as_str()).unwrap();
let mut cookie = Cookie::new(self.cookie_name.clone(), payload);
cookie.set_expires(OffsetDateTime::now_utc() + DurationCookie::seconds(self.expires.as_secs().try_into().unwrap()));
res.header("Set-Cookie", &cookie.to_string());
return Ok(());
};
}
}
impl Session for SessionCookie {
fn values(&mut self) -> Values {
return self.values.clone();
}
fn set(&mut self, key: &str, value: &str) {
self.values.insert(key.to_owned(), value.to_owned());
}
fn set_values(&mut self, values: Values) {
for (key, value) in values {
self.set(key.as_str(), value.as_str());
}
}
fn get(&mut self, key: &str) -> String {
return self.values.get(key).map(|v| String::from(v)).unwrap_or(String::new());
}
fn remove(&mut self, key: &str) {
self.values.remove(key);
}
fn errors(&mut self) -> Values {
return self.errors.clone();
}
fn set_error(&mut self, key: &str, value: &str) {
self.errors_old.insert(key.to_owned(), value.to_owned());
}
fn set_errors(&mut self, errors: Values) {
for (key, value) in errors {
self.set_error(key.as_str(), value.as_str());
}
}
fn get_error(&mut self, key: &str) -> String {
return self.errors.get(key).map(|e| String::from(e)).unwrap_or(String::new());
}
fn remove_error(&mut self, key: &str) {
self.errors.remove(key);
}
fn set_old(&mut self, values: Values) {
for (key, value) in values {
self.old_new.insert(key, value);
}
}
fn old_values(&mut self) -> Values {
return self.old.clone();
}
fn old(&mut self, key: &str) -> String {
return self.old.get(key).or(Some(&String::new())).unwrap().to_string();
}
fn set_flash(&mut self, key: &str, value: &str) {
self.flashes_new.insert(String::from(key), String::from(value));
}
fn flash(&mut self, key: &str) -> String {
return self.flashes.get(key).map(|v| String::from(v)).unwrap_or(String::new());
}
fn flashes(&mut self) -> Values {
return self.flashes.clone();
}
}