gimpey_db_gateway/clients/
refresh_token_client.rs1use rustls::crypto::ring::default_provider;
2use rustls::{ClientConfig, RootCertStore};
3use rustls_native_certs::load_native_certs;
4use std::str::FromStr;
5use tonic::{metadata::MetadataValue, Request, Status};
6use tonic_rustls::channel::Channel as RustlsChannel;
7
8use crate::generated::refresh_token::{
9 refresh_token_service_client::RefreshTokenServiceClient, CreateRefreshTokenRequest,
10 CreateRefreshTokenResponse, GetRefreshTokenRequest, GetRefreshTokenResponse, Meta,
11};
12
13#[derive(Debug, Clone)]
14pub struct RefreshTokenClient {
15 inner: RefreshTokenServiceClient<RustlsChannel>,
16 api_key: String,
17}
18
19impl RefreshTokenClient {
20 pub async fn connect(
21 domain: &str,
22 api_key: String,
23 is_secure: bool,
24 ) -> Result<Self, Box<dyn std::error::Error>> {
25 let channel = if is_secure {
26 let provider = default_provider();
27 let _ = provider.install_default();
28
29 let mut roots = RootCertStore::empty();
30 for cert in load_native_certs().expect("Could not load platform certs") {
31 roots.add(cert).unwrap();
32 }
33
34 let config = ClientConfig::builder()
35 .with_root_certificates(roots)
36 .with_no_client_auth();
37
38 let channel = RustlsChannel::from_shared(format!("https://{domain}"))?
39 .tls_config(config)?
40 .connect()
41 .await?;
42
43 channel
44 } else {
45 RustlsChannel::from_shared(format!("http://{domain}"))?
46 .connect()
47 .await?
48 };
49
50 Ok(Self {
51 inner: RefreshTokenServiceClient::new(channel),
52 api_key,
53 })
54 }
55
56 fn with_auth<T>(&self, message: T) -> Request<T> {
57 let mut req = Request::new(message);
58 let meta = MetadataValue::from_str(&self.api_key).unwrap();
59 req.metadata_mut().insert("x-api-key", meta);
60 req
61 }
62
63 pub async fn create_refresh_token(
64 &mut self,
65 session_id: String,
66 account_id: String,
67 token_hash: String,
68 fingerprint_hash: String,
69 user_agent: String,
70 issued_at: u64,
71 expires_at: u64,
72 meta: Option<Meta>,
73 ) -> Result<CreateRefreshTokenResponse, Status> {
74 let request = CreateRefreshTokenRequest {
75 session_id,
76 account_id,
77 token_hash,
78 fingerprint_hash,
79 user_agent,
80 issued_at,
81 expires_at,
82 meta,
83 };
84
85 let response = self
86 .inner
87 .create_refresh_token(self.with_auth(request))
88 .await?;
89 Ok(response.into_inner())
90 }
91
92 pub async fn get_refresh_token(
93 &mut self,
94 token_hash: String,
95 ) -> Result<GetRefreshTokenResponse, Status> {
96 let request = GetRefreshTokenRequest { token_hash };
97 let response = self
98 .inner
99 .get_refresh_token(self.with_auth(request))
100 .await?;
101 Ok(response.into_inner())
102 }
103}