use std::fmt;
#[derive(Debug, Clone)]
pub enum Auth {
Basic {
username: String,
password: String,
},
Bearer {
token: String,
},
Custom {
scheme: String,
credentials: String,
},
}
impl Auth {
pub fn basic(username: impl Into<String>, password: impl Into<String>) -> Self {
Self::Basic {
username: username.into(),
password: password.into(),
}
}
pub fn bearer(token: impl Into<String>) -> Self {
Self::Bearer {
token: token.into(),
}
}
pub fn custom(scheme: impl Into<String>, credentials: impl Into<String>) -> Self {
Self::Custom {
scheme: scheme.into(),
credentials: credentials.into(),
}
}
pub fn to_header_value(&self) -> String {
match self {
Auth::Basic { username, password } => {
let credentials = format!("{}:{}", username, password);
let encoded = base64::Engine::encode(
&base64::engine::general_purpose::STANDARD,
credentials.as_bytes(),
);
format!("Basic {}", encoded)
}
Auth::Bearer { token } => {
format!("Bearer {}", token)
}
Auth::Custom {
scheme,
credentials,
} => {
format!("{} {}", scheme, credentials)
}
}
}
}
impl fmt::Display for Auth {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Auth::Basic { username, .. } => {
write!(f, "Basic authentication for user: {}", username)
}
Auth::Bearer { .. } => write!(f, "Bearer token authentication"),
Auth::Custom { scheme, .. } => write!(f, "Custom {} authentication", scheme),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic_auth() {
let auth = Auth::basic("user", "pass");
assert_eq!(auth.to_header_value(), "Basic dXNlcjpwYXNz");
}
#[test]
fn test_bearer_auth() {
let auth = Auth::bearer("token123");
assert_eq!(auth.to_header_value(), "Bearer token123");
}
#[test]
fn test_custom_auth() {
let auth = Auth::custom("ApiKey", "secret123");
assert_eq!(auth.to_header_value(), "ApiKey secret123");
}
}