use std::time::Duration;
use crate::types::{Cookie, Cookies, SameSite};
#[derive(Debug)]
pub struct CookieOptions {
pub name: &'static str,
pub path: &'static str,
pub secure: bool,
pub http_only: bool,
pub max_age: Option<Duration>,
pub domain: Option<&'static str>,
pub same_site: Option<SameSite>,
}
impl CookieOptions {
pub const MAX_AGE: u64 = 3600 * 24;
pub fn new(name: &'static str) -> Self {
Self::default().name(name)
}
pub fn name(mut self, name: &'static str) -> Self {
self.name = name;
self
}
pub fn max_age(mut self, max_age: Duration) -> Self {
self.max_age.replace(max_age);
self
}
pub fn domain(mut self, domain: &'static str) -> Self {
self.domain.replace(domain);
self
}
pub fn path(mut self, path: &'static str) -> Self {
self.path = path;
self
}
pub fn secure(mut self, secure: bool) -> Self {
self.secure = secure;
self
}
pub fn http_only(mut self, http_only: bool) -> Self {
self.http_only = http_only;
self
}
pub fn same_site(mut self, same_site: SameSite) -> Self {
self.same_site.replace(same_site);
self
}
pub fn into_cookie(&self, value: impl Into<String>) -> Cookie<'_> {
let mut cookie = Cookie::new(self.name, value.into());
cookie.set_path(self.path);
cookie.set_secure(self.secure);
cookie.set_http_only(self.http_only);
cookie.set_same_site(self.same_site);
if let Some(domain) = self.domain {
cookie.set_domain(domain);
}
if let Some(max_age) = self.max_age {
cookie.set_max_age(
::cookie::time::Duration::try_from(max_age)
.expect("cant convert std Duration into time::Duration"),
);
}
cookie
}
}
impl Default for CookieOptions {
fn default() -> Self {
Self {
domain: None,
secure: true,
http_only: true,
path: "/",
name: "viz.sid",
same_site: Some(SameSite::Lax),
max_age: Some(Duration::from_secs(Self::MAX_AGE)),
}
}
}
#[cfg(not(any(feature = "cookie-signed", feature = "cookie-private")))]
pub trait Cookieable {
fn options(&self) -> &CookieOptions;
fn get_cookie<'a>(&'a self, cookies: &'a Cookies) -> Option<Cookie<'a>> {
cookies.get(self.options().name)
}
fn remove_cookie<'a>(&'a self, cookies: &'a Cookies) {
cookies.remove(self.options().name)
}
fn set_cookie<'a>(&'a self, cookies: &'a Cookies, value: impl Into<String>) {
cookies.add(self.options().into_cookie(value))
}
}
#[cfg(all(feature = "cookie-signed", not(feature = "cookie-private")))]
pub trait Cookieable {
fn options(&self) -> &CookieOptions;
fn get_cookie<'a>(&'a self, cookies: &'a Cookies) -> Option<Cookie<'a>> {
cookies.signed_get(self.options().name)
}
fn remove_cookie<'a>(&'a self, cookies: &'a Cookies) {
cookies.signed_remove(self.options().name)
}
fn set_cookie<'a>(&'a self, cookies: &'a Cookies, value: impl Into<String>) {
cookies.signed_add(self.options().into_cookie(value))
}
}
#[cfg(all(feature = "cookie-private", not(feature = "cookie-signed")))]
pub trait Cookieable {
fn options(&self) -> &CookieOptions;
fn get_cookie<'a>(&self, cookies: &'a Cookies) -> Option<Cookie<'a>> {
cookies.private_get(self.options().name)
}
fn remove_cookie<'a>(&self, cookies: &'a Cookies) {
cookies.private_remove(self.options().name)
}
fn set_cookie<'a>(&'a self, cookies: &'a Cookies, value: impl Into<String>) {
cookies.private_add(self.options().into_cookie(value))
}
}
#[cfg(all(feature = "cookie-private", feature = "cookie-signed"))]
pub trait Cookieable {
fn options(&self) -> &CookieOptions;
fn get_cookie<'a>(&'a self, _: &'a Cookies) -> Option<Cookie<'a>> {
panic!("Please choose a secure option, `cookie-signed` or `cookie-private`")
}
fn remove_cookie<'a>(&'a self, _: &'a Cookies) {
panic!("Please choose a secure option, `cookie-signed` or `cookie-private`")
}
fn set_cookie<'a>(&'a self, _: &'a Cookies, _: impl Into<String>) {
panic!("Please choose a secure option, `cookie-signed` or `cookie-private`")
}
}