use super::extract::{
optional_endpoint, optional_request_id, required_str, session_indexes_from_value,
};
use super::identifiers::{MessageId, SessionIndex};
use super::subject::NameId;
use super::EndpointUrl;
use crate::config::EntityId;
use crate::constants::status_code;
use crate::error::SamlError;
use crate::raw::FlowResult;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LogoutSubject {
name_id: NameId,
session_indexes: Vec<SessionIndex>,
}
impl LogoutSubject {
pub fn new(name_id: NameId, session_indexes: Vec<SessionIndex>) -> Self {
Self {
name_id,
session_indexes,
}
}
pub fn from_name_id(name_id: NameId) -> Self {
Self::new(name_id, Vec::new())
}
pub fn with_session_index(name_id: NameId, session_index: SessionIndex) -> Self {
Self::new(name_id, vec![session_index])
}
pub fn name_id(&self) -> &NameId {
&self.name_id
}
pub fn session_index(&self) -> Option<&SessionIndex> {
self.session_indexes.first()
}
pub fn session_indexes(&self) -> &[SessionIndex] {
&self.session_indexes
}
}
#[derive(Debug, Clone)]
pub struct LogoutRequest {
id: MessageId,
issuer: EntityId,
name_id: Option<NameId>,
session_indexes: Vec<SessionIndex>,
destination: Option<EndpointUrl>,
raw_flow: FlowResult,
}
impl LogoutRequest {
pub fn id(&self) -> &MessageId {
&self.id
}
pub fn issuer(&self) -> &EntityId {
&self.issuer
}
pub fn name_id(&self) -> Option<&NameId> {
self.name_id.as_ref()
}
pub fn session_indexes(&self) -> &[SessionIndex] {
&self.session_indexes
}
pub fn destination(&self) -> Option<&EndpointUrl> {
self.destination.as_ref()
}
pub fn raw_flow(&self) -> &FlowResult {
&self.raw_flow
}
}
impl TryFrom<FlowResult> for LogoutRequest {
type Error = SamlError;
fn try_from(raw_flow: FlowResult) -> Result<Self, Self::Error> {
let id = MessageId::try_new(required_str(&raw_flow.extract, "request.id")?)?;
let issuer = EntityId::try_new(required_str(&raw_flow.extract, "issuer")?)?;
let name_id = raw_flow
.extract
.get_str("nameID")
.map(|value| NameId::new(value, None));
let session_indexes = session_indexes_from_value(raw_flow.extract.get("sessionIndex"))?;
let destination = optional_endpoint(&raw_flow.extract, "request.destination")?;
Ok(Self {
id,
issuer,
name_id,
session_indexes,
destination,
raw_flow,
})
}
}
#[derive(Debug, Clone)]
pub struct LogoutResponse {
id: MessageId,
issuer: EntityId,
in_response_to: Option<MessageId>,
destination: Option<EndpointUrl>,
raw_flow: FlowResult,
}
impl LogoutResponse {
pub fn id(&self) -> &MessageId {
&self.id
}
pub fn issuer(&self) -> &EntityId {
&self.issuer
}
pub fn in_response_to(&self) -> Option<&MessageId> {
self.in_response_to.as_ref()
}
pub fn destination(&self) -> Option<&EndpointUrl> {
self.destination.as_ref()
}
pub fn raw_flow(&self) -> &FlowResult {
&self.raw_flow
}
}
impl TryFrom<FlowResult> for LogoutResponse {
type Error = SamlError;
fn try_from(raw_flow: FlowResult) -> Result<Self, Self::Error> {
let id = MessageId::try_new(required_str(&raw_flow.extract, "response.id")?)?;
let issuer = EntityId::try_new(required_str(&raw_flow.extract, "issuer")?)?;
let in_response_to = optional_request_id(&raw_flow.extract, "response.inResponseTo")?;
let destination = optional_endpoint(&raw_flow.extract, "response.destination")?;
Ok(Self {
id,
issuer,
in_response_to,
destination,
raw_flow,
})
}
}
#[derive(Debug, Clone)]
pub struct LogoutCompleted {
peer_entity_id: EntityId,
response: Option<LogoutResponse>,
}
impl PartialEq for LogoutCompleted {
fn eq(&self, other: &Self) -> bool {
self.peer_entity_id == other.peer_entity_id
}
}
impl Eq for LogoutCompleted {}
impl LogoutCompleted {
pub fn new(peer_entity_id: EntityId) -> Self {
Self {
peer_entity_id,
response: None,
}
}
pub fn from_response(peer_entity_id: EntityId, response: LogoutResponse) -> Self {
Self {
peer_entity_id,
response: Some(response),
}
}
pub fn peer_entity_id(&self) -> &EntityId {
&self.peer_entity_id
}
pub fn response(&self) -> Option<&LogoutResponse> {
self.response.as_ref()
}
pub fn status(&self) -> Option<&str> {
self.response.as_ref().map(|_| status_code::SUCCESS)
}
pub fn raw_flow(&self) -> Option<&FlowResult> {
self.response.as_ref().map(LogoutResponse::raw_flow)
}
}