pub trait TokenApi: Send + Sync {
// Required methods
fn auth<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
secret: &'life1 str,
source_app_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<String, FinamError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn token_details<'life0, 'life1, 'async_trait>(
&'life0 self,
token: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<TokenInfo, FinamError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
}Expand description
Auth transport, abstracted so refresh logic is testable without a network.
GrpcTokenApi is the real implementation. Implement the trait yourself to test code that depends
on a TokenManager without a server.
§Examples
use std::sync::Arc;
use async_trait::async_trait;
use brokapi_finam_protocol::{FinamError, TokenApi, TokenInfo, TokenManager};
/// Gives numbered tokens and no details.
struct Fake(std::sync::atomic::AtomicU32);
#[async_trait]
impl TokenApi for Fake {
async fn auth(&self, _secret: &str, _app: &str) -> Result<String, FinamError> {
let n = self.0.fetch_add(1, std::sync::atomic::Ordering::SeqCst) + 1;
Ok(format!("token-{n}"))
}
async fn token_details(&self, _token: &str) -> Result<TokenInfo, FinamError> {
Ok(TokenInfo { account_ids: vec!["A1".into()], ..TokenInfo::default() })
}
}
let tokens = TokenManager::start(Arc::new(Fake(Default::default())), "secret", "").await?;
assert_eq!(&*tokens.current(), "token-1");
assert_eq!(tokens.account_ids(), vec!["A1"]);Required Methods§
Sourcefn auth<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
secret: &'life1 str,
source_app_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<String, FinamError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn auth<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
secret: &'life1 str,
source_app_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<String, FinamError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Exchanges the API secret for a JWT (AuthService.Auth).
source_app_id is the application id the broker shows in its records. It may be empty.
§Errors
FinamError::Status when the server refuses the secret or cannot be reached.
Sourcefn token_details<'life0, 'life1, 'async_trait>(
&'life0 self,
token: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<TokenInfo, FinamError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn token_details<'life0, 'life1, 'async_trait>(
&'life0 self,
token: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<TokenInfo, FinamError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Reads the lifetime and the account list of token (AuthService.TokenDetails).
The manager does not fail when this call fails: it falls back to the JWT claims for the lifetime and to an empty account list.
§Errors
FinamError::Status when the server refuses the token or cannot be reached.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".