use snafu::Snafu;
use tonic::metadata::errors::InvalidMetadataValue;
pub const DEFAULT_ENV_VAR_NAME: &str = "DNA_TOKEN";
#[derive(Snafu, Debug)]
pub enum BearerTokenError {
#[snafu(display("Invalid bearer token format"))]
InvalidBearerTokenFormat { source: InvalidMetadataValue },
#[snafu(display("{message}"))]
External {
message: String,
source: Box<dyn std::error::Error + Send + Sync>,
},
}
pub trait BearerTokenProvider: Send + Sync {
fn get_token(&self) -> Result<String, BearerTokenError>;
}
#[derive(Debug, Clone)]
pub struct StaticBearerToken {
token: String,
}
#[derive(Debug, Clone)]
pub struct BearerTokenFromEnv {
env_var_name: String,
}
impl StaticBearerToken {
pub fn new(token: String) -> Self {
StaticBearerToken { token }
}
}
impl BearerTokenProvider for StaticBearerToken {
fn get_token(&self) -> Result<String, BearerTokenError> {
Ok(self.token.clone())
}
}
impl Default for StaticBearerToken {
fn default() -> Self {
StaticBearerToken::new(DEFAULT_ENV_VAR_NAME.to_string())
}
}
impl BearerTokenProvider for BearerTokenFromEnv {
fn get_token(&self) -> Result<String, BearerTokenError> {
let token =
std::env::var(&self.env_var_name).map_err(|err| BearerTokenError::External {
message: format!(
"Failed to get bearer token from '{}' env variable",
&self.env_var_name
),
source: Box::new(err),
})?;
Ok(token)
}
}
impl Default for BearerTokenFromEnv {
fn default() -> Self {
BearerTokenFromEnv::new_with_var_name(DEFAULT_ENV_VAR_NAME.to_string())
}
}
impl BearerTokenFromEnv {
pub fn new() -> Self {
Self::default()
}
pub fn new_with_var_name(env_var_name: String) -> Self {
BearerTokenFromEnv { env_var_name }
}
}
impl From<InvalidMetadataValue> for BearerTokenError {
fn from(source: InvalidMetadataValue) -> Self {
BearerTokenError::InvalidBearerTokenFormat { source }
}
}