1use serde::{de::DeserializeOwned, Serialize};
2
3use crate::{
4 apis::{
5 Authenticate, CurrentUser, Jwks, Login, MagicLink, OpenId, Otp, Register, Tokens, Users,
6 },
7 config::Config,
8 error::ApiError,
9 PassageError,
10};
11
12#[derive(Debug, Clone)]
13pub struct Passage {
14 http_client: reqwest::Client,
15 config: Config,
16}
17
18impl Default for Passage {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23
24impl Passage {
25 pub fn new() -> Self {
27 Self {
28 http_client: reqwest::Client::new(),
29 config: Config::default(),
30 }
31 }
32}
33
34impl Passage {
35 pub fn build(http_client: reqwest::Client, config: Config) -> Self {
37 Self {
38 http_client,
39 config,
40 }
41 }
42
43 pub fn with_config(config: Config) -> Self {
44 Self {
45 http_client: reqwest::Client::new(),
46 config,
47 }
48 }
49
50 pub fn set_pub_jwk(mut self, pub_jwk: String) -> Self {
51 self.config = self.config.with_pub_jwk(pub_jwk);
52 self
53 }
54
55 pub fn with_http_client(mut self, http_client: reqwest::Client) -> Self {
59 self.http_client = http_client;
60 self
61 }
62
63 pub fn tokens(&self) -> Tokens {
67 Tokens::new(self)
68 }
69
70 pub fn register(&self) -> Register {
72 Register::new(self)
73 }
74
75 pub fn otp(&self) -> Otp {
77 Otp::new(self)
78 }
79
80 pub fn open_id(&self) -> OpenId {
82 OpenId::new(self)
83 }
84
85 pub fn magic_link(&self) -> MagicLink {
87 MagicLink::new(self)
88 }
89
90 pub fn login(&self) -> Login {
92 Login::new(self)
93 }
94
95 pub fn jwks(&self) -> Jwks {
97 Jwks::new(self)
98 }
99
100 pub fn authenticate(&self) -> Authenticate {
102 Authenticate::new(self)
103 }
104
105 pub fn current_user(&self) -> CurrentUser {
107 CurrentUser::new(self)
108 }
109
110 pub fn users(&self) -> Users {
112 Users::new(self)
113 }
114
115 pub fn app_auth_origin(&self) -> &str {
116 self.config.app_auth_origin()
117 }
118
119 pub fn app_id(&self) -> &str {
120 self.config.app_id()
121 }
122
123 pub fn config(&self) -> &Config {
124 &self.config
125 }
126
127 pub fn pub_jwk(&self) -> Option<&String> {
128 self.config.pub_jwk()
129 }
130
131 pub(crate) async fn get<O>(&self, path: &str) -> Result<O, PassageError>
133 where
134 O: DeserializeOwned,
135 {
136 let response = self
137 .http_client
138 .get(self.config.url(path))
139 .query(&self.config.query())
140 .headers(self.config.bearer_auth())
141 .send()
142 .await?;
143
144 self.deserialize_response(response).await
145 }
146
147 pub(crate) async fn get_with_query<Q, O>(
150 &self,
151 path: &str,
152 query: &Q,
153 ) -> Result<O, PassageError>
154 where
155 O: DeserializeOwned,
156 Q: Serialize + ?Sized,
157 {
158 let response = self
159 .http_client
160 .get(self.config.url(path))
161 .query(&self.config.query())
162 .query(query)
163 .headers(self.config.bearer_auth())
164 .send()
165 .await?;
166
167 self.deserialize_response(response).await
168 }
169
170 pub(crate) async fn get_from_management_api<O>(&self, path: &str) -> Result<O, PassageError>
175 where
176 O: DeserializeOwned,
177 {
178 let response = self
179 .http_client
180 .get(format!("https://api.passage.id/v1{}", path))
181 .query(&self.config.query())
182 .headers(self.config.api_key_auth())
183 .send()
184 .await?;
185
186 dbg!(&response);
187
188 self.deserialize_response(response).await
189 }
190
191 pub(crate) async fn post<I, O>(&self, path: &str, request: I) -> Result<O, PassageError>
193 where
194 I: Serialize,
195 O: DeserializeOwned,
196 {
197 let response = self
198 .http_client
199 .post(self.config.url(path))
200 .query(&self.config.query())
201 .headers(self.config.bearer_auth())
202 .json(&request)
203 .send()
204 .await?;
205
206 self.deserialize_response(response).await
207 }
208
209 pub(crate) async fn patch<I, O>(&self, path: &str, request: I) -> Result<O, PassageError>
211 where
212 I: Serialize,
213 O: DeserializeOwned,
214 {
215 let response = self
216 .http_client
217 .patch(self.config.url(path))
218 .query(&self.config.query())
219 .headers(self.config.bearer_auth())
220 .json(&request)
221 .send()
222 .await?;
223
224 self.deserialize_response(response).await
225 }
226
227 pub(crate) async fn delete<O>(&self, path: &str) -> Result<O, PassageError>
229 where
230 O: DeserializeOwned,
231 {
232 let response = self
233 .http_client
234 .delete(self.config.url(path))
235 .query(&self.config.query())
236 .headers(self.config.bearer_auth())
237 .send()
238 .await?;
239
240 self.deserialize_response(response).await
241 }
242
243 pub(crate) async fn delete_with_query<Q, O>(
246 &self,
247 path: &str,
248 query: &Q,
249 ) -> Result<O, PassageError>
250 where
251 O: DeserializeOwned,
252 Q: Serialize + ?Sized,
253 {
254 let response = self
255 .http_client
256 .delete(self.config.url(path))
257 .query(&self.config.query())
258 .query(query)
259 .headers(self.config.bearer_auth())
260 .send()
261 .await?;
262
263 self.deserialize_response(response).await
264 }
265
266 async fn deserialize_response<O>(&self, response: reqwest::Response) -> Result<O, PassageError>
268 where
269 O: DeserializeOwned,
270 {
271 if response.status().is_success() {
272 response.json::<O>().await.map_err(PassageError::from)
273 } else {
274 Err(response
275 .json::<ApiError>()
276 .await
277 .map_err(PassageError::from)?
278 .into())
279 }
280 }
281}