gimpey_db_gateway/clients/
account_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::account::{
9 account_service_client::AccountServiceClient, CreateAccountRequest, CreateAccountResponse,
10 GetAccountRequest, GetAccountResponse, GetAccountsRequest, GetAccountsResponse,
11 IncrementNonceRequest, UpdateAccountRequest, UpdateAccountResponse,
12};
13
14#[derive(Debug, Clone)]
15pub struct AccountClient {
16 inner: AccountServiceClient<RustlsChannel>,
17 api_key: String,
18}
19
20impl AccountClient {
21 pub async fn connect(
22 domain: &str,
23 api_key: String,
24 is_secure: bool,
25 ) -> Result<Self, Box<dyn std::error::Error>> {
26 let channel = if is_secure {
27 let provider = default_provider();
28 let _ = provider.install_default();
29
30 let mut roots = RootCertStore::empty();
31 for cert in load_native_certs().expect("Could not load platform certs") {
32 roots.add(cert).unwrap();
33 }
34
35 let config = ClientConfig::builder()
36 .with_root_certificates(roots)
37 .with_no_client_auth();
38
39 let channel = RustlsChannel::from_shared(format!("https://{domain}"))?
40 .tls_config(config)?
41 .connect()
42 .await?;
43
44 channel
45 } else {
46 RustlsChannel::from_shared(format!("http://{domain}"))?
47 .connect()
48 .await?
49 };
50
51 Ok(Self {
52 inner: AccountServiceClient::new(channel),
53 api_key,
54 })
55 }
56
57 fn with_auth<T>(&self, message: T) -> Request<T> {
58 let mut req = Request::new(message);
59 let meta = MetadataValue::from_str(&self.api_key).unwrap();
60 req.metadata_mut().insert("x-api-key", meta);
61 req
62 }
63
64 pub async fn create_account(
65 &mut self,
66 email: String,
67 username: String,
68 password: String,
69 beta_code: Option<String>,
70 referral_code: Option<String>,
71 ) -> Result<CreateAccountResponse, Status> {
72 let request = CreateAccountRequest {
73 email,
74 username,
75 password,
76 beta_code,
77 referral_code,
78 };
79
80 let response = self.inner.create_account(self.with_auth(request)).await?;
81
82 Ok(response.into_inner())
83 }
84
85 pub async fn get_account(&mut self, identifier: String) -> Result<GetAccountResponse, Status> {
87 let request = GetAccountRequest { identifier };
88
89 let response = self.inner.get_account(self.with_auth(request)).await?;
90 Ok(response.into_inner())
91 }
92
93 pub async fn update_account(
94 &mut self,
95 id: String,
96 email: String,
97 username: String,
98 password: String,
99 ) -> Result<UpdateAccountResponse, Status> {
100 let request = UpdateAccountRequest {
101 id,
102 email,
103 username,
104 password,
105 };
106
107 let response = self.inner.update_account(self.with_auth(request)).await?;
108 Ok(response.into_inner())
109 }
110
111 pub async fn get_accounts(
112 &mut self,
113 limit: Option<u32>,
114 cursor: Option<String>,
115 sort_by: Option<i32>,
116 order: Option<String>,
117 search: Option<String>,
118 ) -> Result<GetAccountsResponse, Status> {
119 let request = GetAccountsRequest {
120 limit,
121 cursor,
122 sort_by,
123 order,
124 search,
125 };
126 let response = self.inner.get_accounts(self.with_auth(request)).await?;
127 Ok(response.into_inner())
128 }
129
130 pub async fn increment_avatar_nonce(&mut self, id: String) -> Result<i32, Status> {
131 let request = IncrementNonceRequest { id };
132 let response = self
133 .inner
134 .increment_avatar_nonce(self.with_auth(request))
135 .await?;
136 let nonce = response.into_inner().nonce;
137 Ok(nonce as i32)
138 }
139
140 pub async fn increment_banner_nonce(&mut self, id: String) -> Result<i32, Status> {
141 let request = IncrementNonceRequest { id };
142 let response = self
143 .inner
144 .increment_banner_nonce(self.with_auth(request))
145 .await?;
146 let nonce = response.into_inner().nonce;
147 Ok(nonce as i32)
148 }
149
150 pub async fn increment_totp_nonce(&mut self, id: String) -> Result<i32, Status> {
151 let request = IncrementNonceRequest { id };
152 let response = self
153 .inner
154 .increment_totp_nonce(self.with_auth(request))
155 .await?;
156 let nonce = response.into_inner().nonce;
157 Ok(nonce as i32)
158 }
159}