use base64::Engine;
use base64::prelude::BASE64_STANDARD;
use deno_npmrc::RegistryConfig;
#[derive(Debug, thiserror::Error, deno_error::JsError)]
pub enum AuthHeaderForNpmRegistryError {
#[class(type)]
#[error(
"Both the username / email and password must be provided for basic auth"
)]
Both,
#[class(type)]
#[error("The password in npmrc is an invalid base64 string: {0}")]
Base64(base64::DecodeError),
}
pub fn maybe_auth_header_value_for_npm_registry(
registry_config: &RegistryConfig,
) -> Result<Option<String>, AuthHeaderForNpmRegistryError> {
if let Some(token) = registry_config.auth_token.as_ref() {
return Ok(Some(format!("Bearer {}", token)));
}
if let Some(auth) = registry_config.auth.as_ref() {
return Ok(Some(format!("Basic {}", auth)));
}
let username_or_email = registry_config
.username
.as_ref()
.or(registry_config.email.as_ref());
let password = registry_config.password.as_ref();
if username_or_email.is_some() != password.is_some() {
return Err(AuthHeaderForNpmRegistryError::Both);
}
if let Some(username) = username_or_email
&& let Some(password) = password
{
let pw_base64 = BASE64_STANDARD
.decode(password)
.map_err(AuthHeaderForNpmRegistryError::Base64)?;
let bearer = BASE64_STANDARD.encode(format!(
"{}:{}",
username,
String::from_utf8_lossy(&pw_base64)
));
return Ok(Some(format!("Basic {}", bearer)));
}
Ok(None)
}