Skip to main content

native/kameleoon_elixir_bridge/src/cookies_ex.rs

use std::collections::HashMap;

use kameleoon_core::cookies::accessor::CoreCookieAccessor;

pub(crate) struct MapCookieAccessor {
    cookies: HashMap<String, String>,
    response_cookies: Vec<CookieResponseItemEx>,
}

impl MapCookieAccessor {
    pub(crate) fn new(cookies: HashMap<String, String>) -> Self {
        Self {
            cookies,
            response_cookies: Vec::new(),
        }
    }

    pub(crate) fn into_ex(self) -> CookieEx {
        CookieEx {
            cookies: self.cookies,
            response_cookies: self.response_cookies,
        }
    }
}

impl CoreCookieAccessor for MapCookieAccessor {
    fn set(&mut self, key: &str, value: &str, max_age: u32, top_level_domain: Option<&str>) {
        self.cookies.insert(key.to_owned(), value.to_owned());
        self.response_cookies.push(CookieResponseItemEx {
            key: key.to_owned(),
            value: value.to_owned(),
            max_age,
            top_level_domain: top_level_domain.map(str::to_owned),
        });
    }

    fn get(&self, key: &str) -> Option<String> {
        self.cookies.get(key).cloned()
    }
}

#[derive(Debug, rustler::NifStruct)]
#[module = "Kameleoon.Internal.GetVisitorCodeResult"]
#[rustler(encode)]
pub(crate) struct GetVisitorCodeResultEx {
    pub(crate) visitor_code: String,
    pub(crate) cookies: CookieEx,
}

#[derive(Debug, rustler::NifStruct)]
#[module = "Kameleoon.Internal.Cookie"]
#[rustler(encode)]
pub(crate) struct CookieEx {
    cookies: HashMap<String, String>,
    response_cookies: Vec<CookieResponseItemEx>,
}

#[derive(Debug, rustler::NifStruct)]
#[module = "Kameleoon.Internal.CookieResponseItem"]
#[rustler(encode)]
struct CookieResponseItemEx {
    key: String,
    value: String,
    max_age: u32,
    top_level_domain: Option<String>,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn map_cookie_accessor_tracks_cookie_reponses() {
        let mut accessor = MapCookieAccessor::new(HashMap::from([("existing".to_owned(), "1".to_owned())]));

        assert_eq!(accessor.get("existing"), Some("1".to_owned()));
        accessor.set("new_cookie", "value", 60, Some("example.com"));

        let payload = accessor.into_ex();
        assert_eq!(payload.cookies.get("existing"), Some(&"1".to_owned()));
        assert_eq!(payload.cookies.get("new_cookie"), Some(&"value".to_owned()));
        assert_eq!(payload.response_cookies.len(), 1);
        assert_eq!(payload.response_cookies[0].key, "new_cookie");
        assert_eq!(payload.response_cookies[0].top_level_domain.as_deref(), Some("example.com"));
    }
}