use async_trait::async_trait;
use tokio::sync::watch;
pub mod mock;
pub mod refresh;
pub mod static_token;
pub type TokenSourceError = Box<dyn std::error::Error + Sync + Send>;
pub type TokenSourceWatch = watch::Receiver<Option<Result<String, TokenSourceError>>>;
#[async_trait]
pub trait TokenSource: Send + Sync + 'static {
fn watch(&self) -> TokenSourceWatch;
async fn get_token(&self) -> Result<String, TokenSourceError> {
let mut watch = self.watch();
match watch.borrow_and_update().as_ref() {
Some(Ok(token)) => return Ok(token.clone()),
Some(Err(e)) => return Err(e.to_string().into()),
None => {}
}
watch.changed().await.map_err(|_| {
Box::<dyn std::error::Error + Sync + Send>::from("token source watch channel closed")
})?;
match watch.borrow().as_ref() {
Some(Ok(token)) => Ok(token.clone()),
Some(Err(e)) => Err(e.to_string().into()),
None => {
Err(Box::<dyn std::error::Error + Sync + Send>::from(
"token source watch channel has no value",
))
}
}
}
fn format_header(&self, token: String) -> String {
format!("Bearer {token}")
}
}