use actix_web::http::{ header::{HeaderMap, InvalidHeaderValue, ToStrError}, uri::PathAndQuery, Method, }; use std::{ collections::BTreeMap, error::Error, fmt::{self, Display}, }; mod sign; #[cfg(feature = "digest")] pub mod digest; pub mod verify; pub mod prelude { pub use crate::{verify::Unverified, Config, Sign, Verify, VerifyError}; #[cfg(feature = "digest")] pub use crate::digest::{ middleware::VerifyDigest, DigestClient, DigestCreate, DigestPart, DigestVerify, SignExt, }; pub use actix_web::http::header::{InvalidHeaderValue, ToStrError}; } pub mod create; use self::{create::Unsigned, verify::Unverified}; pub trait Verify { fn begin_verify(&self, config: &Config) -> Result; } pub trait Sign { fn authorization_signature(self, config: &Config, key_id: K, f: F) -> Result where F: FnOnce(&str) -> Result, E>, E: From + From, K: Display, Self: Sized; fn signature(self, config: &Config, key_id: K, f: F) -> Result where F: FnOnce(&str) -> Result, E>, E: From + From, K: Display, Self: Sized; } #[derive(Clone, Default)] pub struct Config { pub config: http_signature_normalization::Config, } #[derive(Debug)] pub enum VerifyError { Sig(http_signature_normalization::VerifyError), Header(ToStrError), } impl Config { pub fn begin_sign( &self, method: &Method, path_and_query: Option<&PathAndQuery>, headers: HeaderMap, ) -> Result { let headers = headers .iter() .map(|(k, v)| v.to_str().map(|v| (k.to_string(), v.to_string()))) .collect::, ToStrError>>()?; let path_and_query = path_and_query .map(|p| p.to_string()) .unwrap_or(String::from("/")); let unsigned = self .config .begin_sign(&method.to_string(), &path_and_query, headers); Ok(Unsigned { unsigned }) } pub fn begin_verify( &self, method: &Method, path_and_query: Option<&PathAndQuery>, headers: HeaderMap, ) -> Result { let headers = headers .iter() .map(|(k, v)| v.to_str().map(|v| (k.to_string(), v.to_string()))) .collect::, ToStrError>>()?; let path_and_query = path_and_query .map(|p| p.to_string()) .unwrap_or(String::from("/")); let unverified = self .config .begin_verify(&method.to_string(), &path_and_query, headers)?; Ok(unverified) } } impl fmt::Display for VerifyError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { VerifyError::Sig(ref e) => write!(f, "Sig error, {}", e), VerifyError::Header(ref e) => write!(f, "Header error, {}", e), } } } impl Error for VerifyError { fn description(&self) -> &str { match *self { VerifyError::Sig(ref e) => e.description(), VerifyError::Header(ref e) => e.description(), } } fn source(&self) -> Option<&(dyn Error + 'static)> { match *self { VerifyError::Sig(ref e) => Some(e), VerifyError::Header(ref e) => Some(e), } } } impl From for VerifyError { fn from(e: http_signature_normalization::VerifyError) -> Self { VerifyError::Sig(e) } } impl From for VerifyError { fn from(e: ToStrError) -> Self { VerifyError::Header(e) } }