Skip to main content

paas_client/
auth.rs

1use async_trait::async_trait;
2use paas_api::status::SystemId;
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::error::Error;
6use std::sync::Arc;
7
8#[derive(Debug, thiserror::Error)]
9pub enum AuthError {
10    #[error("Failed to get token: {0}")]
11    TokenError(String),
12    #[error("Failed to set header: {0}")]
13    HeaderError(#[from] reqwest::header::InvalidHeaderValue),
14}
15
16#[async_trait]
17pub trait Auth: Send + Sync + 'static {
18    fn token_type(&self) -> &str;
19    async fn token(&self) -> Result<String, Box<dyn Error>>;
20
21    async fn authenticate(
22        &self,
23        headers: &mut reqwest::header::HeaderMap,
24    ) -> Result<(), Box<dyn Error>> {
25        let auth_value = format!("{} {}", self.token_type(), self.token().await?);
26        headers.insert(
27            reqwest::header::AUTHORIZATION,
28            reqwest::header::HeaderValue::from_str(&auth_value)?,
29        );
30        Ok(())
31    }
32}
33
34#[async_trait]
35pub(crate) trait RequestBuilderExt {
36    async fn with_auth(self, auth: &Arc<dyn Auth>) -> Result<reqwest::RequestBuilder, AuthError>;
37}
38
39#[async_trait]
40impl RequestBuilderExt for reqwest::RequestBuilder {
41    async fn with_auth(self, auth: &Arc<dyn Auth>) -> Result<reqwest::RequestBuilder, AuthError> {
42        let auth_value = format!(
43            "{} {}",
44            auth.token_type(),
45            auth.token()
46                .await
47                .map_err(|e| AuthError::TokenError(e.to_string()))?
48        );
49        Ok(self.header(reqwest::header::AUTHORIZATION, auth_value))
50    }
51}
52
53#[derive(Clone, Serialize, Deserialize)]
54pub struct BearerTokenAuth {
55    token: String,
56}
57
58impl BearerTokenAuth {
59    pub fn new(token: String) -> BearerTokenAuth {
60        BearerTokenAuth { token }
61    }
62}
63
64#[async_trait]
65impl Auth for BearerTokenAuth {
66    fn token_type(&self) -> &str {
67        "Bearer"
68    }
69
70    async fn token(&self) -> Result<String, Box<dyn Error>> {
71        Ok(self.token.clone())
72    }
73}
74
75pub struct SystemAuths(pub HashMap<SystemId, Arc<dyn Auth>>);
76
77impl SystemAuths {
78    pub fn new(auths: HashMap<SystemId, Arc<dyn Auth>>) -> Self {
79        Self(auths)
80    }
81
82    pub fn from_auths<A: Auth>(auths: HashMap<SystemId, A>) -> Self {
83        Self::new(
84            auths
85                .into_iter()
86                .map(|(id, auth)| (id, Arc::new(auth) as Arc<dyn Auth>))
87                .collect(),
88        )
89    }
90
91    pub fn get(&self, system_id: &SystemId) -> Option<Arc<dyn Auth>> {
92        self.0.get(system_id).map(Arc::clone)
93    }
94}