use chrono::{DateTime, Utc};
use crate::core::assertion::issuer::{Issuer, IssuerRef};
use crate::core::assertion::name_id::{NameIdOrEncryptedId, NameIdOrEncryptedIdRef};
use crate::core::identifiers::SamlVersion;
use super::status::{Status, StatusRef};
#[derive(Debug, Clone, PartialEq)]
pub enum NewIdOrTerminateRef<'a> {
NewId(&'a str),
NewEncryptedId(&'a [u8]),
Terminate,
}
impl<'a> NewIdOrTerminateRef<'a> {
pub fn to_owned(&self) -> NewIdOrTerminate {
match self {
NewIdOrTerminateRef::NewId(s) => NewIdOrTerminate::NewId(s.to_string()),
NewIdOrTerminateRef::NewEncryptedId(b) => NewIdOrTerminate::NewEncryptedId(b.to_vec()),
NewIdOrTerminateRef::Terminate => NewIdOrTerminate::Terminate,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum NewIdOrTerminate {
NewId(String),
NewEncryptedId(Vec<u8>),
Terminate,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ManageNameIdRequestRef<'a> {
pub id: &'a str,
pub version: SamlVersion,
pub issue_instant: DateTime<Utc>,
pub destination: Option<&'a str>,
pub consent: Option<&'a str>,
pub issuer: Option<IssuerRef<'a>>,
pub has_signature: bool,
pub name_id: NameIdOrEncryptedIdRef<'a>,
pub new_id_or_terminate: NewIdOrTerminateRef<'a>,
}
impl<'a> ManageNameIdRequestRef<'a> {
pub fn to_owned(&self) -> ManageNameIdRequest {
ManageNameIdRequest {
id: self.id.to_string(),
version: self.version,
issue_instant: self.issue_instant,
destination: self.destination.map(str::to_string),
consent: self.consent.map(str::to_string),
issuer: self.issuer.as_ref().map(|i| i.to_owned()),
has_signature: self.has_signature,
name_id: self.name_id.to_owned(),
new_id_or_terminate: self.new_id_or_terminate.to_owned(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ManageNameIdRequest {
pub id: String,
pub version: SamlVersion,
pub issue_instant: DateTime<Utc>,
pub destination: Option<String>,
pub consent: Option<String>,
pub issuer: Option<Issuer>,
pub has_signature: bool,
pub name_id: NameIdOrEncryptedId,
pub new_id_or_terminate: NewIdOrTerminate,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ManageNameIdResponseRef<'a> {
pub id: &'a str,
pub version: SamlVersion,
pub issue_instant: DateTime<Utc>,
pub destination: Option<&'a str>,
pub consent: Option<&'a str>,
pub issuer: Option<IssuerRef<'a>>,
pub has_signature: bool,
pub in_response_to: Option<&'a str>,
pub status: StatusRef<'a>,
}
impl<'a> ManageNameIdResponseRef<'a> {
pub fn to_owned(&self) -> ManageNameIdResponse {
ManageNameIdResponse {
id: self.id.to_string(),
version: self.version,
issue_instant: self.issue_instant,
destination: self.destination.map(str::to_string),
consent: self.consent.map(str::to_string),
issuer: self.issuer.as_ref().map(|i| i.to_owned()),
has_signature: self.has_signature,
in_response_to: self.in_response_to.map(str::to_string),
status: self.status.to_owned(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ManageNameIdResponse {
pub id: String,
pub version: SamlVersion,
pub issue_instant: DateTime<Utc>,
pub destination: Option<String>,
pub consent: Option<String>,
pub issuer: Option<Issuer>,
pub has_signature: bool,
pub in_response_to: Option<String>,
pub status: Status,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::assertion::name_id::NameIdRef;
use crate::core::constants::*;
use crate::core::protocol::status::StatusCodeRef;
#[test]
fn test_manage_name_id_request_with_new_id() {
let now = chrono::Utc::now();
let req = ManageNameIdRequestRef {
id: "_mni_req_1",
version: SamlVersion::V2_0,
issue_instant: now,
destination: Some("https://idp.example.com/mni"),
consent: None,
issuer: Some(IssuerRef {
value: "https://sp.example.com",
format: None,
name_qualifier: None,
sp_name_qualifier: None,
}),
has_signature: true,
name_id: NameIdOrEncryptedIdRef::NameId(NameIdRef {
value: "old-user-id",
format: Some(NAMEID_PERSISTENT),
name_qualifier: None,
sp_name_qualifier: None,
sp_provided_id: None,
}),
new_id_or_terminate: NewIdOrTerminateRef::NewId("new-user-id"),
};
let owned = req.to_owned();
assert_eq!(owned.id, "_mni_req_1");
match &owned.new_id_or_terminate {
NewIdOrTerminate::NewId(s) => assert_eq!(s, "new-user-id"),
_ => panic!("Expected NewId"),
}
}
#[test]
fn test_manage_name_id_request_terminate() {
let now = chrono::Utc::now();
let req = ManageNameIdRequestRef {
id: "_mni_req_2",
version: SamlVersion::V2_0,
issue_instant: now,
destination: None,
consent: None,
issuer: None,
has_signature: false,
name_id: NameIdOrEncryptedIdRef::NameId(NameIdRef {
value: "user@example.com",
format: Some(NAMEID_EMAIL),
name_qualifier: None,
sp_name_qualifier: None,
sp_provided_id: None,
}),
new_id_or_terminate: NewIdOrTerminateRef::Terminate,
};
let owned = req.to_owned();
assert_eq!(owned.new_id_or_terminate, NewIdOrTerminate::Terminate);
}
#[test]
fn test_manage_name_id_response_ref_to_owned() {
let now = chrono::Utc::now();
let resp = ManageNameIdResponseRef {
id: "_mni_resp_1",
version: SamlVersion::V2_0,
issue_instant: now,
destination: None,
consent: None,
issuer: Some(IssuerRef {
value: "https://idp.example.com",
format: None,
name_qualifier: None,
sp_name_qualifier: None,
}),
has_signature: true,
in_response_to: Some("_mni_req_1"),
status: StatusRef {
status_code: StatusCodeRef {
value: STATUS_SUCCESS,
sub_status: None,
},
status_message: None,
status_detail: None,
},
};
let owned = resp.to_owned();
assert_eq!(owned.id, "_mni_resp_1");
assert!(owned.status.is_success());
assert_eq!(owned.in_response_to.as_deref(), Some("_mni_req_1"));
}
}