use monoloop_contracts::{ConnectorError, ConnectorErrorKind};
use secrecy::{ExposeSecret, SecretString};
use std::collections::HashMap;
use std::fmt;
use std::sync::Arc;
pub struct ResolvedCredential {
authorization: Option<SecretString>,
}
impl ResolvedCredential {
pub fn none() -> Self {
Self {
authorization: None,
}
}
pub fn authorization(value: impl Into<String>) -> Self {
Self {
authorization: Some(SecretString::from(value.into())),
}
}
pub fn bearer(token: impl Into<String>) -> Self {
Self::authorization(format!("Bearer {}", token.into()))
}
pub fn expose_authorization(&self) -> Option<&str> {
self.authorization.as_ref().map(|s| s.expose_secret())
}
}
impl fmt::Debug for ResolvedCredential {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ResolvedCredential")
.field(
"authorization",
&self.authorization.as_ref().map(|_| "<redacted>"),
)
.finish()
}
}
pub trait CredentialResolver: Send + Sync {
fn resolve(&self, credential_ref: &str) -> Result<ResolvedCredential, ConnectorError>;
}
#[derive(Clone, Default)]
pub struct MapCredentialResolver {
map: Arc<HashMap<String, SecretString>>,
}
impl MapCredentialResolver {
pub fn new(entries: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>) -> Self {
let mut map = HashMap::new();
for (k, v) in entries {
map.insert(k.into(), SecretString::from(v.into()));
}
Self { map: Arc::new(map) }
}
pub fn empty() -> Self {
Self::default()
}
}
impl fmt::Debug for MapCredentialResolver {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MapCredentialResolver")
.field("entries", &self.map.len())
.finish()
}
}
impl CredentialResolver for MapCredentialResolver {
fn resolve(&self, credential_ref: &str) -> Result<ResolvedCredential, ConnectorError> {
if credential_ref.is_empty() {
return Err(ConnectorError::new(
ConnectorErrorKind::CredentialUnavailable,
"empty credential reference",
));
}
match self.map.get(credential_ref) {
Some(secret) => Ok(ResolvedCredential::authorization(secret.expose_secret())),
None => Err(ConnectorError::new(
ConnectorErrorKind::CredentialUnavailable,
"credential reference not found",
)),
}
}
}
#[derive(Clone, Debug, Default)]
pub struct AnonymousCredentialResolver;
impl CredentialResolver for AnonymousCredentialResolver {
fn resolve(&self, _credential_ref: &str) -> Result<ResolvedCredential, ConnectorError> {
Ok(ResolvedCredential::none())
}
}