use super::{Site, answer};
use crate::door::{
config::SignInBounds,
http::Request,
packed::Packed,
signin::{Door, Issuer, SignedIn, Started},
};
use lys_pass::Error;
use std::collections::BTreeMap;
use std::num::NonZeroU64;
use std::path::PathBuf;
type TestResult = Result<(), Box<dyn std::error::Error>>;
struct ShortSession;
impl Issuer for ShortSession {
fn bounds(&self) -> SignInBounds {
SignInBounds {
session_seconds: NonZeroU64::MIN.saturating_add(1),
..SignInBounds::default()
}
}
fn start(&self) -> Result<Started, Error> {
Ok(Started {
url: "https://lys.example".into(),
state: "state".into(),
browser: "browser".into(),
verifier: "verifier".into(),
})
}
fn finish(
&self,
_code: &str,
_state: &str,
browser: &str,
started: &Started,
) -> Result<SignedIn, Error> {
if browser != started.browser {
return Err(Error::Invalid("fixture browser mismatch"));
}
Ok(SignedIn {
token: "fixture".into(),
holder: "fixture".into(),
expires_at: 1600,
refresh: Some("refresh".into()),
})
}
fn refresh(&self, _refresh: &str) -> Result<SignedIn, Error> {
Err(Error::CannotAsk("fixture"))
}
}
#[test]
fn session_cookie_uses_the_configured_session_lifetime() -> TestResult {
let door = Door::new(ShortSession);
door.begin(1000)?;
let request = Request {
method: "GET".into(),
path: "/callback".into(),
query: "code=code&state=state".into(),
headers: vec![("cookie".into(), "haem_state=browser".into())],
body: Vec::new(),
};
let site = Site {
origin: "https://studio.example".into(),
files: PathBuf::from("/unused"),
stores: BTreeMap::new(),
timeout: std::time::Duration::from_secs(1),
packed: Packed::default(),
store_children: BTreeMap::new(),
};
let mut bytes = Vec::new();
answer(&door, &site, &request, 1000).write(&mut bytes)?;
let response = String::from_utf8(bytes)?;
let cookie = response
.lines()
.find(|line| line.starts_with("Set-Cookie: haem_session="))
.ok_or("session cookie missing")?;
let lifetime = cookie
.rsplit_once("Max-Age=")
.ok_or("cookie lifetime missing")?
.1;
assert_eq!(lifetime, "2", "cookie outlived configured session");
Ok(())
}