spiral-auth 0.1.12

Spiral credentials: bearer tokens and the providers that obtain them
Documentation
//! Failures of credential sources.

use std::error::Error as StdError;
use std::fmt::Display;

use reqwest::{StatusCode, Url};

/// A credential source could not supply a usable credential.
#[derive(Debug, thiserror::Error)]
pub enum CredentialError {
    /// The source is misconfigured or supplied an unusable credential.
    #[error("{0}")]
    Invalid(String),
    /// The authorization server or a platform identity endpoint rejected a request.
    #[error("{url} returned {status}: {body}")]
    Rejected {
        url: Url,
        status: StatusCode,
        body: String,
    },
    /// A URL for a credential request is malformed.
    #[error(transparent)]
    Url(#[from] url::ParseError),
    /// A credential request could not be sent or its response read.
    #[error(transparent)]
    Http(#[from] reqwest::Error),
    /// A credential response or saved session was not the expected JSON.
    #[error(transparent)]
    Json(#[from] serde_json::Error),
    /// A saved session could not be read or written.
    #[error(transparent)]
    Io(#[from] std::io::Error),
    /// A credential source supplied by the host application failed.
    #[error(transparent)]
    External(Box<dyn StdError + Send + Sync>),
}

/// The result of consulting a credential source.
pub type CredentialResult<T> = Result<T, CredentialError>;

impl CredentialError {
    /// A source is misconfigured or supplied an unusable credential.
    pub fn invalid(message: impl Display) -> Self {
        Self::Invalid(message.to_string())
    }

    /// Wrap the failure of a credential source implemented outside this crate.
    pub fn external(error: impl Into<Box<dyn StdError + Send + Sync>>) -> Self {
        Self::External(error.into())
    }
}

impl From<reqwest_middleware::Error> for CredentialError {
    fn from(error: reqwest_middleware::Error) -> Self {
        match error {
            reqwest_middleware::Error::Reqwest(error) => Self::Http(error),
            reqwest_middleware::Error::Middleware(error) => Self::External(error.into()),
        }
    }
}