better-auth-api 1.0.0-alpha.5

Plugin implementations for better-auth
use super::*;
use base64::{Engine, engine::general_purpose::STANDARD};
use better_auth_core::Headers;
use hmac::{Hmac, Mac};
use sha2::Sha256;

pub(super) fn observe(headers: Option<&Headers>, state: &State) -> Value {
    let Some(headers) = headers else {
        return Value::Null;
    };
    let cookies: Vec<_> = headers.get_all("set-cookie").cloned().collect();
    let mut session_pair = None;
    for cookie in &cookies {
        let pair = cookie.split(';').next().unwrap();
        if !pair.starts_with("better-auth.session_token=") {
            assert!(
                pair.ends_with('='),
                "Only empty state cookies may accompany the Session cookie: {pair}"
            );
            continue;
        }
        let token = state
            .tracking
            .lock()
            .unwrap()
            .session_token
            .clone()
            .unwrap();
        let encoded = pair.strip_prefix("better-auth.session_token=").unwrap();
        let decoded = urlencoding::decode(encoded).unwrap();
        let (signed_token, signature) = decoded.rsplit_once('.').unwrap();
        assert_eq!(signed_token, token);
        let mut verifier = Hmac::<Sha256>::new_from_slice(SECRET.as_bytes()).unwrap();
        verifier.update(token.as_bytes());
        verifier
            .verify_slice(&STANDARD.decode(signature).unwrap())
            .unwrap();
        assert_eq!(encoded, urlencoding::encode(&decoded));
        session_pair = Some(pair.to_owned());
        state.tracking.lock().unwrap().replacements.insert(
            cookie.clone(),
            format!(
                "better-auth.session_token=<verified-session-token>{}",
                &cookie[pair.len()..]
            ),
        );
    }
    let mut entries: Vec<_> = headers
        .into_iter()
        .map(|(name, value)| {
            let name = name.to_ascii_lowercase();
            let value = if name == "set-cookie" {
                session_pair.as_ref().map_or_else(
                    || value.clone(),
                    |pair| {
                        value.replace(pair, "better-auth.session_token=<verified-session-token>")
                    },
                )
            } else {
                value.clone()
            };
            (name, value)
        })
        .collect();
    entries.sort_by(|left, right| left.0.cmp(&right.0));
    json!({"entries": entries, "cookies": cookies})
}