use http::header::{HeaderMap, HeaderName, HeaderValue};
use super::component::MessageSignatureComponentTarget;
use super::config::{validate_component_set, validate_label};
use super::headers::{ACCEPT_SIGNATURE, existing_dictionary, reject_duplicate_labels};
use super::params::AcceptSignatureParams;
use super::parsed::parse_accept_signature_member;
use super::{MessageSignatureComponent, MessageSignatureConfig, MessageSignatureError};
use crate::structured_fields;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
#[non_exhaustive]
pub struct AcceptSignature {
entries: Vec<AcceptSignatureEntry>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub struct AcceptSignatureEntry {
label: String,
components: Vec<MessageSignatureComponent>,
params: AcceptSignatureParams,
parsed_value: Option<String>,
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
#[non_exhaustive]
pub struct AcceptSignatureFulfillment {
created: Option<u64>,
expires: Option<u64>,
nonce: Option<String>,
algorithm: Option<String>,
key_id: Option<String>,
tag: Option<String>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum AcceptSignatureTarget {
Request,
Response,
RequestResponse,
}
impl AcceptSignature {
pub fn new() -> Self {
Self::default()
}
pub fn parse(value: &str) -> Result<Self, MessageSignatureError> {
let entries = structured_fields::dictionary(value)
.map_err(|_| MessageSignatureError::MalformedSignatureHeader(ACCEPT_SIGNATURE))?;
Self::from_dictionary_entries(entries)
}
pub fn from_headers(headers: &HeaderMap) -> Result<Self, MessageSignatureError> {
Self::from_dictionary_entries(existing_dictionary(headers, ACCEPT_SIGNATURE)?)
}
pub fn entries(&self) -> &[AcceptSignatureEntry] {
&self.entries
}
pub fn entry(mut self, entry: AcceptSignatureEntry) -> Self {
self.entries.push(entry);
self
}
pub fn header_value(&self) -> Result<HeaderValue, MessageSignatureError> {
let entries = self.dictionary_entries()?;
let value = structured_fields::serialize_dictionary(&entries);
HeaderValue::from_str(&value).map_err(|source| {
MessageSignatureError::InvalidGeneratedHeader {
header: "Accept-Signature",
source,
}
})
}
pub fn insert_into(&self, headers: &mut HeaderMap) -> Result<(), MessageSignatureError> {
headers.insert(
HeaderName::from_static(ACCEPT_SIGNATURE),
self.header_value()?,
);
Ok(())
}
pub fn validate_request_target(&self) -> Result<(), MessageSignatureError> {
self.validate_target(AcceptSignatureTarget::Request)
}
pub fn request_signature_configs(
&self,
fulfillment: &AcceptSignatureFulfillment,
) -> Result<Vec<MessageSignatureConfig>, MessageSignatureError> {
self.entries
.iter()
.map(|entry| entry.request_signature_config(fulfillment))
.collect()
}
pub fn validate_response_target(&self) -> Result<(), MessageSignatureError> {
self.validate_target(AcceptSignatureTarget::Response)
}
pub fn response_signature_configs(
&self,
fulfillment: &AcceptSignatureFulfillment,
) -> Result<Vec<MessageSignatureConfig>, MessageSignatureError> {
self.entries
.iter()
.map(|entry| entry.response_signature_config(fulfillment))
.collect()
}
pub fn validate_request_response_target(&self) -> Result<(), MessageSignatureError> {
self.validate_target(AcceptSignatureTarget::RequestResponse)
}
pub fn request_response_signature_configs(
&self,
fulfillment: &AcceptSignatureFulfillment,
) -> Result<Vec<MessageSignatureConfig>, MessageSignatureError> {
self.entries
.iter()
.map(|entry| entry.request_response_signature_config(fulfillment))
.collect()
}
fn from_dictionary_entries(
dictionary_entries: Vec<(String, String)>,
) -> Result<Self, MessageSignatureError> {
reject_duplicate_labels(ACCEPT_SIGNATURE, &dictionary_entries)?;
let mut entries = Vec::with_capacity(dictionary_entries.len());
for (label, member) in dictionary_entries {
validate_label(&label)?;
let (components, params) = parse_accept_signature_member(&member)?;
validate_component_set(&components, true)?;
entries.push(AcceptSignatureEntry {
label,
components,
params,
parsed_value: Some(member),
});
}
Ok(Self { entries })
}
fn dictionary_entries(&self) -> Result<Vec<(String, String)>, MessageSignatureError> {
let entries = self
.entries
.iter()
.map(|entry| Ok((entry.label.clone(), entry.member_value()?)))
.collect::<Result<Vec<_>, MessageSignatureError>>()?;
reject_duplicate_labels(ACCEPT_SIGNATURE, &entries)?;
Ok(entries)
}
fn validate_target(&self, target: AcceptSignatureTarget) -> Result<(), MessageSignatureError> {
for entry in &self.entries {
entry.validate_target(target)?;
}
Ok(())
}
}
impl AcceptSignatureFulfillment {
pub fn new() -> Self {
Self::default()
}
pub fn created(mut self, created: u64) -> Self {
self.created = Some(created);
self
}
pub fn expires(mut self, expires: u64) -> Self {
self.expires = Some(expires);
self
}
pub fn nonce(mut self, nonce: impl Into<String>) -> Self {
self.nonce = Some(nonce.into());
self
}
pub fn algorithm(mut self, algorithm: impl Into<String>) -> Self {
self.algorithm = Some(algorithm.into());
self
}
pub fn key_id(mut self, key_id: impl Into<String>) -> Self {
self.key_id = Some(key_id.into());
self
}
pub fn tag(mut self, tag: impl Into<String>) -> Self {
self.tag = Some(tag.into());
self
}
}
impl AcceptSignatureEntry {
pub fn new(label: impl Into<String>) -> Result<Self, MessageSignatureError> {
let label = label.into();
validate_label(&label)?;
Ok(Self {
label,
components: Vec::new(),
params: AcceptSignatureParams::default(),
parsed_value: None,
})
}
pub fn label(&self) -> &str {
&self.label
}
pub fn components(&self) -> &[MessageSignatureComponent] {
&self.components
}
pub fn params(&self) -> &AcceptSignatureParams {
&self.params
}
pub fn component(mut self, component: MessageSignatureComponent) -> Self {
self.parsed_value = None;
self.components.push(component);
self
}
pub fn components_iter(
mut self,
components: impl IntoIterator<Item = MessageSignatureComponent>,
) -> Self {
self.parsed_value = None;
self.components.extend(components);
self
}
pub fn created(mut self) -> Self {
self.parsed_value = None;
self.params.created = true;
self
}
pub fn expires(mut self) -> Self {
self.parsed_value = None;
self.params.expires = true;
self
}
pub fn nonce(mut self, nonce: impl Into<String>) -> Self {
self.parsed_value = None;
self.params.nonce = Some(nonce.into());
self
}
pub fn algorithm(mut self, algorithm: impl Into<String>) -> Self {
self.parsed_value = None;
self.params.algorithm = Some(algorithm.into());
self
}
pub fn key_id(mut self, key_id: impl Into<String>) -> Self {
self.parsed_value = None;
self.params.key_id = Some(key_id.into());
self
}
pub fn tag(mut self, tag: impl Into<String>) -> Self {
self.parsed_value = None;
self.params.tag = Some(tag.into());
self
}
pub fn validate_request_target(&self) -> Result<(), MessageSignatureError> {
self.validate_target(AcceptSignatureTarget::Request)
}
pub fn request_signature_config(
&self,
fulfillment: &AcceptSignatureFulfillment,
) -> Result<MessageSignatureConfig, MessageSignatureError> {
self.validate_request_target()?;
self.signature_config(fulfillment)
}
pub fn validate_response_target(&self) -> Result<(), MessageSignatureError> {
self.validate_target(AcceptSignatureTarget::Response)
}
pub fn response_signature_config(
&self,
fulfillment: &AcceptSignatureFulfillment,
) -> Result<MessageSignatureConfig, MessageSignatureError> {
self.validate_response_target()?;
self.signature_config(fulfillment)
}
pub fn validate_request_response_target(&self) -> Result<(), MessageSignatureError> {
self.validate_target(AcceptSignatureTarget::RequestResponse)
}
pub fn request_response_signature_config(
&self,
fulfillment: &AcceptSignatureFulfillment,
) -> Result<MessageSignatureConfig, MessageSignatureError> {
self.validate_request_response_target()?;
self.signature_config(fulfillment)
}
fn signature_config(
&self,
fulfillment: &AcceptSignatureFulfillment,
) -> Result<MessageSignatureConfig, MessageSignatureError> {
let mut config = MessageSignatureConfig::new(self.label.clone())?
.components_iter(self.components.iter().cloned());
if let Some(created) = fulfill_requested_integer(
"created",
self.params.created_requested(),
fulfillment.created,
)? {
config = config.created(created);
}
if let Some(expires) = fulfill_requested_integer(
"expires",
self.params.expires_requested(),
fulfillment.expires,
)? {
config = config.expires(expires);
}
if let Some(nonce) =
fulfill_requested_string("nonce", self.params.nonce(), fulfillment.nonce.as_deref())?
{
config = config.nonce(nonce);
}
if let Some(algorithm) = fulfill_requested_string(
"alg",
self.params.algorithm(),
fulfillment.algorithm.as_deref(),
)? {
config = config.algorithm(algorithm);
}
if let Some(key_id) =
fulfill_requested_string("keyid", self.params.key_id(), fulfillment.key_id.as_deref())?
{
config = config.key_id(key_id);
}
if let Some(tag) =
fulfill_requested_string("tag", self.params.tag(), fulfillment.tag.as_deref())?
{
config = config.tag(tag);
}
Ok(config)
}
fn member_value(&self) -> Result<String, MessageSignatureError> {
validate_component_set(&self.components, true)?;
if let Some(ref value) = self.parsed_value {
return Ok(value.clone());
}
let mut value = String::new();
value.push('(');
for (index, component) in self.components.iter().enumerate() {
if index > 0 {
value.push(' ');
}
value.push_str(&component.identifier()?);
}
value.push(')');
value.push_str(&self.params.serialize()?);
Ok(value)
}
fn validate_target(&self, target: AcceptSignatureTarget) -> Result<(), MessageSignatureError> {
validate_component_set(&self.components, true)?;
for component in &self.components {
validate_component_target(component, target)?;
}
Ok(())
}
}
fn fulfill_requested_integer(
parameter: &'static str,
requested: bool,
fulfilled: Option<u64>,
) -> Result<Option<u64>, MessageSignatureError> {
if requested && fulfilled.is_none() {
return Err(MessageSignatureError::UnfulfillableAcceptSignatureParameter(parameter));
}
Ok(fulfilled)
}
fn fulfill_requested_string(
parameter: &'static str,
requested: Option<&str>,
fulfilled: Option<&str>,
) -> Result<Option<String>, MessageSignatureError> {
match (requested, fulfilled) {
(Some(requested), Some(fulfilled)) if requested != fulfilled => {
Err(MessageSignatureError::UnfulfillableAcceptSignatureParameter(parameter))
}
(Some(requested), _) => Ok(Some(requested.to_owned())),
(None, Some(fulfilled)) => Ok(Some(fulfilled.to_owned())),
(None, None) => Ok(None),
}
}
fn validate_component_target(
component: &MessageSignatureComponent,
target: AcceptSignatureTarget,
) -> Result<(), MessageSignatureError> {
let identifier = component.identifier()?;
if component.related_request_parameter_count() > 1 {
return Err(MessageSignatureError::UnsupportedComponentParameters(
identifier,
));
}
match target {
AcceptSignatureTarget::Request => {
if component.has_related_request_parameter() {
return Err(MessageSignatureError::UnsupportedComponentParameters(
identifier,
));
}
if matches!(
component.target(),
MessageSignatureComponentTarget::Response
) {
return Err(MessageSignatureError::ComponentNotAvailable {
component: identifier,
context: "request",
});
}
}
AcceptSignatureTarget::Response => {
if component.has_related_request_parameter() {
return Err(MessageSignatureError::ComponentNotAvailable {
component: identifier,
context: "response",
});
}
if matches!(component.target(), MessageSignatureComponentTarget::Request) {
return Err(MessageSignatureError::ComponentNotAvailable {
component: identifier,
context: "response",
});
}
}
AcceptSignatureTarget::RequestResponse => {
if component.has_related_request_parameter() {
if matches!(
component.target(),
MessageSignatureComponentTarget::Response
) {
return Err(MessageSignatureError::UnsupportedComponentParameters(
identifier,
));
}
} else if matches!(component.target(), MessageSignatureComponentTarget::Request) {
return Err(MessageSignatureError::ComponentNotAvailable {
component: identifier,
context: "response",
});
}
}
}
Ok(())
}