use std::collections::HashMap;
use super::oidc::SsoUserInfo;
pub struct SsoSessionBridge<'a> {
user_info: &'a SsoUserInfo,
}
impl<'a> SsoSessionBridge<'a> {
pub fn new(user_info: &'a SsoUserInfo) -> Self {
Self { user_info }
}
pub fn to_session_attributes(&self) -> HashMap<String, String> {
let mut attrs = HashMap::new();
attrs.insert("sso_subject".to_string(), self.user_info.subject.clone());
if let Some(email) = &self.user_info.email {
attrs.insert("sso_email".to_string(), email.clone());
}
if let Some(name) = &self.user_info.name {
attrs.insert("sso_name".to_string(), name.clone());
}
if !self.user_info.groups.is_empty() {
attrs.insert("sso_groups".to_string(), self.user_info.groups.join(","));
}
attrs
}
pub fn has_group(&self, group: &str) -> bool {
self.user_info.groups.iter().any(|g| g == group)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_user(groups: Vec<&str>) -> SsoUserInfo {
SsoUserInfo {
subject: "sub-999".to_string(),
email: Some("carol@example.com".to_string()),
name: Some("Carol".to_string()),
groups: groups.into_iter().map(|s| s.to_string()).collect(),
raw_claims: HashMap::new(),
}
}
#[test]
fn test_session_bridge_to_attributes() {
let user = make_user(vec!["admins", "users"]);
let bridge = SsoSessionBridge::new(&user);
let attrs = bridge.to_session_attributes();
assert_eq!(
attrs.get("sso_subject").map(|s| s.as_str()),
Some("sub-999")
);
assert_eq!(
attrs.get("sso_email").map(|s| s.as_str()),
Some("carol@example.com")
);
assert_eq!(attrs.get("sso_name").map(|s| s.as_str()), Some("Carol"));
let groups_str = attrs.get("sso_groups").expect("sso_groups must be present");
assert!(groups_str.contains("admins"), "missing admins");
assert!(groups_str.contains("users"), "missing users");
}
#[test]
fn test_session_bridge_has_group() {
let user = make_user(vec!["engineers", "rdf-users"]);
let bridge = SsoSessionBridge::new(&user);
assert!(bridge.has_group("engineers"), "should be in engineers");
assert!(bridge.has_group("rdf-users"), "should be in rdf-users");
assert!(!bridge.has_group("admins"), "should NOT be in admins");
assert!(
!bridge.has_group("Engineers"),
"comparison is case-sensitive"
);
}
#[test]
fn test_session_bridge_no_email() {
let user = SsoUserInfo {
subject: "anon-sub".to_string(),
email: None,
name: None,
groups: vec![],
raw_claims: HashMap::new(),
};
let bridge = SsoSessionBridge::new(&user);
let attrs = bridge.to_session_attributes();
assert!(attrs.contains_key("sso_subject"));
assert!(!attrs.contains_key("sso_email"), "email should be absent");
assert!(!attrs.contains_key("sso_name"), "name should be absent");
assert!(!attrs.contains_key("sso_groups"), "groups should be absent");
}
}