1use std::{sync::{Arc, Mutex, RwLock}, time::Duration};
2
3use tonic::{metadata::{Ascii, MetadataValue}, service::Interceptor, transport::Channel, Request};
4
5use crate::proto::auth::{auth_service_client::AuthServiceClient, AuthRequest};
6
7pub const TOKEN_UPDATE_PERIOD: Duration = Duration::from_secs(14*60); pub type Token = MetadataValue<Ascii>;
10
11#[derive(Debug, Clone)]
12pub struct TokenInterceptor {
13 token: Arc<Mutex<Token>>,
14}
15
16impl TokenInterceptor {
17 pub async fn with_duration(channel: Channel, secret: impl ToString, update_period: Duration) -> Result<Self, tonic::Status> {
18 let secret = secret.to_string();
19 let token = Arc::new(Mutex::new(get_token(channel.clone(), secret.clone()).await?));
20 log::info!("JWT received");
21 let weak = Arc::downgrade(&token);
22 tokio::spawn(async move {
23 tokio::time::sleep(update_period).await;
24 while let Some(token) = weak.upgrade() {
25 match get_token(channel.clone(), secret.clone()).await {
26 Ok(updated) => {
27 *token.lock().unwrap() = updated;
28 drop(token);
29 log::info!("JWT updated");
30 tokio::time::sleep(update_period).await;
31 },
32 Err(e) => {
33 log::error!("Cannot update token: {e}");
34 tokio::time::sleep(crate::RETRY_DELAY).await;
35 }
36 }
37 }
38 log::info!("token updating stopped");
39 });
40 Ok(Self { token })
41 }
42 pub async fn new(channel: Channel, secret: impl ToString) -> Result<Self, tonic::Status> {
43 Self::with_duration(channel, secret, TOKEN_UPDATE_PERIOD).await
44 }
45 pub fn get_token(&self) -> Arc<Mutex<Token>> {
46 self.token.clone()
47 }
48}
49
50impl Interceptor for TokenInterceptor {
51 fn call(&mut self, mut req: Request<()>) -> Result<Request<()>, tonic::Status> {
52 let token = self.token.lock().unwrap().clone();
53 req.metadata_mut().append(
54 "authorization",
55 token,
56 );
57 Ok(req)
58 }
59}
60
61async fn get_token(channel: Channel, secret: String) -> Result<MetadataValue<Ascii>, tonic::Status> {
62 let mut serv = AuthServiceClient::new(channel);
63 let crate::proto::auth::AuthResponse {token} = serv.auth(AuthRequest { secret }).await?.into_inner();
64 Ok(token.parse().unwrap())
65}