1use super::{SqlxStore, entities::oauth_client::Model};
2use crate::{
3 model::{self, ActiveRow, SqlxModel},
4 schema::AuthSchema,
5};
6use alibi_core::{
7 AuthResult,
8 store::{CreateOAuthClient, OAuthClient, OAuthClientStore},
9};
10use async_trait::async_trait;
11#[async_trait]
12impl<S: AuthSchema> OAuthClientStore for SqlxStore<S> {
13 async fn claim_oauth_client_assertion(
14 &self,
15 id: &str,
16 expires_at: chrono::DateTime<chrono::Utc>,
17 ) -> AuthResult<bool> {
18 use super::entities::oauth_client_assertion::Model as Assertion;
19 let mut active = ActiveRow::new();
20 active.set("id", id);
21 active.set("expiresAt", expires_at);
22 match model::insert::<Assertion>(self.exec(), &active).await {
23 Ok(_) => Ok(true),
24 Err(error) => {
25 let mut sql = model::select_model::<Assertion>(self.exec());
26 sql.push(" WHERE ");
27 sql.compare(Assertion::TABLE, "id", " = ", id);
28 match self.exec().fetch_optional::<Assertion>(sql).await {
29 Ok(Some(_)) => Ok(false),
30 _ => Err(error),
31 }
32 }
33 }
34 }
35
36 async fn store_oauth_refresh_replay(&self, id: &str, ciphertext: &str) -> AuthResult<()> {
37 let mut sql = crate::sql::Sql::with(self.exec().engine(), "UPDATE ");
38 sql.ident("oauthRefreshToken");
39 sql.push(" SET ");
40 sql.assign("rotationReplayResponse", ciphertext);
41 sql.push(" WHERE ");
42 sql.compare("oauthRefreshToken", "id", " = ", id);
43 _ = self.exec().execute(sql).await?;
44 Ok(())
45 }
46 async fn claim_oauth_refresh_rotation(
47 &self,
48 token: &str,
49 at: chrono::DateTime<chrono::Utc>,
50 replay_expires: Option<chrono::DateTime<chrono::Utc>>,
51 ) -> AuthResult<bool> {
52 let mut sql = crate::sql::Sql::with(self.exec().engine(), "UPDATE ");
53 sql.ident("oauthRefreshToken");
54 sql.push(" SET ");
55 sql.assign("revoked", at);
56 sql.push(", ");
57 sql.assign("rotatedAt", at);
58 if let Some(expires) = replay_expires {
59 sql.push(", ");
60 sql.assign("rotationReplayExpiresAt", expires);
61 }
62 sql.push(" WHERE ");
63 sql.compare("oauthRefreshToken", "token", " = ", token);
64 sql.push(" AND ");
65 sql.ident("revoked");
66 sql.push(" IS NULL");
67 Ok(self.exec().execute(sql).await? > 0)
68 }
69
70 async fn claim_oauth_refresh_rotation_by_id(
71 &self,
72 id: &str,
73 at: chrono::DateTime<chrono::Utc>,
74 replay_expires: Option<chrono::DateTime<chrono::Utc>>,
75 ) -> AuthResult<bool> {
76 let mut sql = crate::sql::Sql::with(self.exec().engine(), "UPDATE ");
77 sql.ident("oauthRefreshToken");
78 sql.push(" SET ");
79 sql.assign("revoked", at);
80 sql.push(", ");
81 sql.assign("rotatedAt", at);
82 if let Some(expires) = replay_expires {
83 sql.push(", ");
84 sql.assign("rotationReplayExpiresAt", expires);
85 }
86 sql.push(" WHERE ");
87 sql.compare("oauthRefreshToken", "id", " = ", id);
88 sql.push(" AND ");
89 sql.ident("revoked");
90 sql.push(" IS NULL");
91 Ok(self.exec().execute(sql).await? > 0)
92 }
93
94 async fn mark_oauth_token_revoked(
95 &self,
96 kind: alibi_core::store::OAuthTokenKind,
97 id: &str,
98 at: chrono::DateTime<chrono::Utc>,
99 ) -> AuthResult<()> {
100 let table = match kind {
101 alibi_core::store::OAuthTokenKind::Access => "oauthAccessToken",
102 alibi_core::store::OAuthTokenKind::Refresh => "oauthRefreshToken",
103 };
104 let mut sql = crate::sql::Sql::with(self.exec().engine(), "UPDATE ");
105 sql.ident(table);
106 sql.push(" SET ");
107 sql.assign("revoked", at);
108 sql.push(" WHERE ");
109 sql.compare(table, "id", " = ", id);
110 _ = self.exec().execute(sql).await?;
111 Ok(())
112 }
113 async fn list_oauth_tokens_for_session(
114 &self,
115 kind: alibi_core::store::OAuthTokenKind,
116 session_id: &str,
117 ) -> AuthResult<Vec<alibi_core::store::OAuthToken>> {
118 match kind {
119 alibi_core::store::OAuthTokenKind::Access => {
120 let mut sql =
121 model::select_model::<super::entities::oauth_access_token::Model>(self.exec());
122 sql.push(" WHERE ");
123 sql.compare(
124 super::entities::oauth_access_token::Model::TABLE,
125 "sessionId",
126 " = ",
127 session_id,
128 );
129 sql.push(" LIMIT ");
130 sql.bind(self.find_many_limit());
131 self.exec()
132 .fetch_all::<super::entities::oauth_access_token::Model>(sql)
133 .await?
134 .into_iter()
135 .map(TryInto::try_into)
136 .collect()
137 }
138 alibi_core::store::OAuthTokenKind::Refresh => {
139 let mut sql =
140 model::select_model::<super::entities::oauth_refresh_token::Model>(self.exec());
141 sql.push(" WHERE ");
142 sql.compare(
143 super::entities::oauth_refresh_token::Model::TABLE,
144 "sessionId",
145 " = ",
146 session_id,
147 );
148 sql.push(" LIMIT ");
149 sql.bind(self.find_many_limit());
150 self.exec()
151 .fetch_all::<super::entities::oauth_refresh_token::Model>(sql)
152 .await?
153 .into_iter()
154 .map(TryInto::try_into)
155 .collect()
156 }
157 }
158 }
159
160 async fn delete_oauth_token(
161 &self,
162 kind: alibi_core::store::OAuthTokenKind,
163 token: &str,
164 ) -> AuthResult<()> {
165 match kind {
166 alibi_core::store::OAuthTokenKind::Access => {
167 let mut sql = crate::sql::Sql::with(self.exec().engine(), "DELETE FROM ");
168 sql.ident(super::entities::oauth_access_token::Model::TABLE);
169 sql.push(" WHERE ");
170 sql.compare(
171 super::entities::oauth_access_token::Model::TABLE,
172 "token",
173 " = ",
174 token,
175 );
176 _ = self.exec().execute(sql).await?;
177 }
178 alibi_core::store::OAuthTokenKind::Refresh => {
179 let mut sql = crate::sql::Sql::with(self.exec().engine(), "DELETE FROM ");
180 sql.ident(super::entities::oauth_refresh_token::Model::TABLE);
181 sql.push(" WHERE ");
182 sql.compare(
183 super::entities::oauth_refresh_token::Model::TABLE,
184 "token",
185 " = ",
186 token,
187 );
188 _ = self.exec().execute(sql).await?;
189 }
190 }
191 Ok(())
192 }
193 async fn revoke_oauth_refresh_token(
194 &self,
195 token: &str,
196 revoked_at: chrono::DateTime<chrono::Utc>,
197 ) -> AuthResult<bool> {
198 let mut lookup =
199 model::select_model::<super::entities::oauth_refresh_token::Model>(self.exec());
200 lookup.push(" WHERE ");
201 lookup.compare("oauthRefreshToken", "token", " = ", token);
202 let Some(row) = self
203 .exec()
204 .fetch_optional::<super::entities::oauth_refresh_token::Model>(lookup)
205 .await?
206 else {
207 return Ok(false);
208 };
209 if row.revoked.is_some() {
210 return Ok(false);
211 }
212 let mut sql = crate::sql::Sql::with(self.exec().engine(), "UPDATE ");
213 sql.ident("oauthRefreshToken");
214 sql.push(" SET ");
215 sql.assign("revoked", revoked_at);
216 sql.push(" WHERE ");
217 sql.compare("oauthRefreshToken", "token", " = ", token);
218 sql.push(" AND ");
219 sql.ident("revoked");
220 sql.push(" IS NULL");
221 Ok(self.exec().execute(sql).await? > 0)
222 }
223 async fn delete_oauth_access_tokens_for_refresh(&self, refresh_id: &str) -> AuthResult<()> {
224 let mut sql = crate::sql::Sql::with(self.exec().engine(), "DELETE FROM ");
225 sql.ident("oauthAccessToken");
226 sql.push(" WHERE ");
227 sql.compare("oauthAccessToken", "refreshId", " = ", refresh_id);
228 _ = self.exec().execute(sql).await?;
229 Ok(())
230 }
231 async fn delete_oauth_refresh_family(&self, client_id: &str, user_id: &str) -> AuthResult<()> {
232 let mut sql = crate::sql::Sql::with(self.exec().engine(), "DELETE FROM ");
233 sql.ident("oauthAccessToken");
234 sql.push(" WHERE ");
235 sql.ident("refreshId");
236 sql.push(" IN (SELECT id FROM ");
237 sql.ident("oauthRefreshToken");
238 sql.push(" WHERE ");
239 sql.compare("oauthRefreshToken", "clientId", " = ", client_id);
240 sql.push(" AND ");
241 sql.compare("oauthRefreshToken", "userId", " = ", user_id);
242 sql.push(" LIMIT ");
243 sql.bind(
244 i64::try_from(self.config().advanced.database.default_find_many_limit)
245 .unwrap_or(i64::MAX),
246 );
247 sql.push(")");
248 _ = self.exec().execute(sql).await?;
249 let mut sql = crate::sql::Sql::with(self.exec().engine(), "DELETE FROM ");
250 sql.ident("oauthRefreshToken");
251 sql.push(" WHERE ");
252 sql.compare("oauthRefreshToken", "clientId", " = ", client_id);
253 sql.push(" AND ");
254 sql.compare("oauthRefreshToken", "userId", " = ", user_id);
255 _ = self.exec().execute(sql).await?;
256 Ok(())
257 }
258 async fn create_oauth_token(
259 &self,
260 kind: alibi_core::store::OAuthTokenKind,
261 data: alibi_core::store::CreateOAuthToken,
262 ) -> AuthResult<alibi_core::store::OAuthToken> {
263 match kind {
264 alibi_core::store::OAuthTokenKind::Access => {
265 let mut active = ActiveRow::new();
266 active.set(
267 "id",
268 self.generated_id(self.exec(), "oauthAccessToken", "oauthAccessToken", "id")
269 .await?
270 .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()),
271 );
272 active.set("token", data.token);
273 active.set("clientId", data.client_id);
274 active.set("userId", data.user_id);
275 active.set("sessionId", data.session_id);
276 active.set("authorizationCodeId", data.authorization_code_id);
277 active.set("createdAt", data.created_at);
278 active.set("expiresAt", data.expires_at);
279 let fields = super::entities::oauth_access_token::Model::columns_from_metadata(
280 data.metadata,
281 )?
282 .into_active();
283 for (column, value) in fields.present() {
284 if ![
285 "id",
286 "token",
287 "clientId",
288 "sessionId",
289 "userId",
290 "authorizationCodeId",
291 "createdAt",
292 "expiresAt",
293 ]
294 .contains(&column)
295 {
296 active.set(column, value.clone());
297 }
298 }
299 model::insert::<super::entities::oauth_access_token::Model>(self.exec(), &active)
300 .await?
301 .try_into()
302 }
303 alibi_core::store::OAuthTokenKind::Refresh => {
304 let mut active = ActiveRow::new();
305 active.set(
306 "id",
307 self.generated_id(self.exec(), "oauthRefreshToken", "oauthRefreshToken", "id")
308 .await?
309 .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()),
310 );
311 active.set("token", data.token);
312 active.set("clientId", data.client_id);
313 active.set("userId", data.user_id);
314 active.set("sessionId", data.session_id);
315 active.set("authorizationCodeId", data.authorization_code_id);
316 active.set("createdAt", data.created_at);
317 active.set("expiresAt", data.expires_at);
318 let fields = super::entities::oauth_refresh_token::Model::columns_from_metadata(
319 data.metadata,
320 )?
321 .into_active();
322 for (column, value) in fields.present() {
323 if ![
324 "id",
325 "token",
326 "clientId",
327 "sessionId",
328 "userId",
329 "authorizationCodeId",
330 "createdAt",
331 "expiresAt",
332 ]
333 .contains(&column)
334 {
335 active.set(column, value.clone());
336 }
337 }
338 model::insert::<super::entities::oauth_refresh_token::Model>(self.exec(), &active)
339 .await?
340 .try_into()
341 }
342 }
343 }
344 async fn get_oauth_token(
345 &self,
346 kind: alibi_core::store::OAuthTokenKind,
347 token: &str,
348 ) -> AuthResult<Option<alibi_core::store::OAuthToken>> {
349 match kind {
350 alibi_core::store::OAuthTokenKind::Access => {
351 let mut sql =
352 model::select_model::<super::entities::oauth_access_token::Model>(self.exec());
353 sql.push(" WHERE ");
354 sql.compare(
355 super::entities::oauth_access_token::Model::TABLE,
356 "token",
357 " = ",
358 token,
359 );
360 self.exec()
361 .fetch_optional::<super::entities::oauth_access_token::Model>(sql)
362 .await?
363 .map(TryInto::try_into)
364 .transpose()
365 }
366 alibi_core::store::OAuthTokenKind::Refresh => {
367 let mut sql =
368 model::select_model::<super::entities::oauth_refresh_token::Model>(self.exec());
369 sql.push(" WHERE ");
370 sql.compare(
371 super::entities::oauth_refresh_token::Model::TABLE,
372 "token",
373 " = ",
374 token,
375 );
376 self.exec()
377 .fetch_optional::<super::entities::oauth_refresh_token::Model>(sql)
378 .await?
379 .map(TryInto::try_into)
380 .transpose()
381 }
382 }
383 }
384 async fn delete_oauth_tokens_for_code(&self, code: &str) -> AuthResult<()> {
385 {
386 let mut sql = crate::sql::Sql::with(self.exec().engine(), "DELETE FROM ");
387 sql.ident(super::entities::oauth_access_token::Model::TABLE);
388 sql.push(" WHERE ");
389 sql.compare(
390 super::entities::oauth_access_token::Model::TABLE,
391 "authorizationCodeId",
392 " = ",
393 code,
394 );
395 _ = self.exec().execute(sql).await?;
396 }
397 {
398 let mut sql = crate::sql::Sql::with(self.exec().engine(), "DELETE FROM ");
399 sql.ident(super::entities::oauth_refresh_token::Model::TABLE);
400 sql.push(" WHERE ");
401 sql.compare(
402 super::entities::oauth_refresh_token::Model::TABLE,
403 "authorizationCodeId",
404 " = ",
405 code,
406 );
407 _ = self.exec().execute(sql).await?;
408 }
409 Ok(())
410 }
411 async fn delete_oauth_client_resource(
412 &self,
413 client_id: &str,
414 resource_id: &str,
415 ) -> AuthResult<()> {
416 let mut sql = crate::sql::Sql::with(self.exec().engine(), "DELETE FROM ");
417 sql.ident(super::entities::oauth_client_resource::Model::TABLE);
418 sql.push(" WHERE ");
419 sql.compare(
420 super::entities::oauth_client_resource::Model::TABLE,
421 "clientId",
422 " = ",
423 client_id,
424 );
425 sql.push(" AND ");
426 sql.compare(
427 super::entities::oauth_client_resource::Model::TABLE,
428 "resourceId",
429 " = ",
430 resource_id,
431 );
432 self.exec().execute(sql).await.map(|_| ())
433 }
434 async fn create_oauth_client_resource(
435 &self,
436 data: alibi_core::store::CreateOAuthClientResource,
437 ) -> AuthResult<alibi_core::store::OAuthClientResource> {
438 let mut active = ActiveRow::new();
439 active.set(
440 "id",
441 self.generated_id(
442 self.exec(),
443 "oauthClientResource",
444 "oauthClientResource",
445 "id",
446 )
447 .await?
448 .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()),
449 );
450 active.set("clientId", data.client_id);
451 active.set("resourceId", data.resource_id);
452 active.set("metadata", Option::<serde_json::Value>::None);
453 active.set("createdAt", Some(data.created_at));
454 model::insert::<super::entities::oauth_client_resource::Model>(self.exec(), &active)
455 .await?
456 .try_into()
457 }
458 async fn delete_oauth_resource(&self, identifier: &str) -> AuthResult<()> {
459 let mut links = crate::sql::Sql::with(self.exec().engine(), "DELETE FROM ");
460 links.ident(super::entities::oauth_client_resource::Model::TABLE);
461 links.push(" WHERE ");
462 links.compare(
463 super::entities::oauth_client_resource::Model::TABLE,
464 "resourceId",
465 " = ",
466 identifier,
467 );
468 _ = self.exec().execute(links).await?;
469 let mut sql = crate::sql::Sql::with(self.exec().engine(), "DELETE FROM ");
470 sql.ident(super::entities::oauth_resource::Model::TABLE);
471 sql.push(" WHERE ");
472 sql.compare(
473 super::entities::oauth_resource::Model::TABLE,
474 "identifier",
475 " = ",
476 identifier,
477 );
478 self.exec().execute(sql).await.map(|_| ())
479 }
480 async fn update_oauth_resource(
481 &self,
482 identifier: &str,
483 metadata: serde_json::Value,
484 updated_at: chrono::DateTime<chrono::Utc>,
485 ) -> AuthResult<Option<alibi_core::store::OAuthResource>> {
486 let Some(row) = self.get_oauth_resource(identifier).await? else {
487 return Ok(None);
488 };
489 let mut active = ActiveRow::new();
490 active.set("id", row.id);
491 let fields =
492 super::entities::oauth_resource::Model::columns_from_metadata(metadata)?.into_active();
493 for (column, value) in fields.present() {
494 if !["id", "identifier", "createdAt", "updatedAt"].contains(&column) {
495 active.set(column, value.clone());
496 }
497 }
498 active.set("updatedAt", updated_at);
499 model::update::<super::entities::oauth_resource::Model>(self.exec(), &active)
500 .await?
501 .map(TryInto::try_into)
502 .transpose()
503 }
504 async fn list_oauth_resources(&self) -> AuthResult<Vec<alibi_core::store::OAuthResource>> {
505 let mut sql = model::select_model::<super::entities::oauth_resource::Model>(self.exec());
506 sql.push(" LIMIT ");
507 sql.bind(self.find_many_limit());
508 self.exec()
509 .fetch_all::<super::entities::oauth_resource::Model>(sql)
510 .await?
511 .into_iter()
512 .map(TryInto::try_into)
513 .collect()
514 }
515 async fn list_oauth_client_resources(
516 &self,
517 client_id: &str,
518 ) -> AuthResult<Vec<alibi_core::store::OAuthClientResource>> {
519 let mut sql =
520 model::select_model::<super::entities::oauth_client_resource::Model>(self.exec());
521 sql.push(" WHERE ");
522 sql.compare(
523 super::entities::oauth_client_resource::Model::TABLE,
524 "clientId",
525 " = ",
526 client_id,
527 );
528 sql.push(" LIMIT ");
529 sql.bind(self.find_many_limit());
530 self.exec()
531 .fetch_all::<super::entities::oauth_client_resource::Model>(sql)
532 .await?
533 .into_iter()
534 .map(TryInto::try_into)
535 .collect()
536 }
537 async fn create_oauth_resource(
538 &self,
539 data: alibi_core::store::CreateOAuthResource,
540 ) -> AuthResult<alibi_core::store::OAuthResource> {
541 let mut active = ActiveRow::new();
542 active.set(
543 "id",
544 self.generated_id(self.exec(), "oauthResource", "oauthResource", "id")
545 .await?
546 .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()),
547 );
548 active.set("identifier", data.identifier);
549 let fields = super::entities::oauth_resource::Model::columns_from_metadata(data.metadata)?
550 .into_active();
551 for (column, value) in fields.present() {
552 if !["id", "identifier", "createdAt", "updatedAt"].contains(&column) {
553 active.set(column, value.clone());
554 }
555 }
556 active.set("createdAt", data.created_at);
557 active.set("updatedAt", data.created_at);
558 model::insert::<super::entities::oauth_resource::Model>(self.exec(), &active)
559 .await?
560 .try_into()
561 }
562 async fn get_oauth_resource(
563 &self,
564 identifier: &str,
565 ) -> AuthResult<Option<alibi_core::store::OAuthResource>> {
566 let mut sql = model::select_model::<super::entities::oauth_resource::Model>(self.exec());
567 sql.push(" WHERE ");
568 sql.compare(
569 super::entities::oauth_resource::Model::TABLE,
570 "identifier",
571 " = ",
572 identifier,
573 );
574 model::limit_one(&mut sql);
575 self.exec()
576 .fetch_optional::<super::entities::oauth_resource::Model>(sql)
577 .await?
578 .map(TryInto::try_into)
579 .transpose()
580 }
581 async fn create_oauth_consent(
582 &self,
583 data: alibi_core::store::CreateOAuthConsent,
584 ) -> AuthResult<alibi_core::store::OAuthConsent> {
585 let mut active = ActiveRow::new();
586 active.set(
587 "id",
588 self.generated_id(self.exec(), "oauthConsent", "oauthConsent", "id")
589 .await?
590 .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()),
591 );
592 active.set("clientId", data.client_id);
593 active.set("userId", data.user_id);
594 let fields = super::entities::oauth_consent::Model::columns_from_metadata(data.metadata)?
595 .into_active();
596 for (column, value) in fields.present() {
597 if !["id", "clientId", "userId", "createdAt", "updatedAt"].contains(&column) {
598 active.set(column, value.clone());
599 }
600 }
601 active.set("createdAt", data.created_at);
602 active.set("updatedAt", data.created_at);
603 model::insert::<super::entities::oauth_consent::Model>(self.exec(), &active)
604 .await?
605 .try_into()
606 }
607 async fn list_oauth_consents_by_user(
608 &self,
609 user_id: &str,
610 ) -> AuthResult<Vec<alibi_core::store::OAuthConsent>> {
611 let mut sql = model::select_model::<super::entities::oauth_consent::Model>(self.exec());
612 sql.push(" WHERE ");
613 sql.compare(
614 super::entities::oauth_consent::Model::TABLE,
615 "userId",
616 " = ",
617 user_id,
618 );
619 sql.push(" LIMIT ");
620 sql.bind(self.find_many_limit());
621 self.exec()
622 .fetch_all::<super::entities::oauth_consent::Model>(sql)
623 .await?
624 .into_iter()
625 .map(TryInto::try_into)
626 .collect()
627 }
628 async fn update_oauth_consent_metadata(
629 &self,
630 id: &str,
631 metadata: serde_json::Value,
632 updated_at: chrono::DateTime<chrono::Utc>,
633 ) -> AuthResult<Option<alibi_core::store::OAuthConsent>> {
634 let mut active = ActiveRow::new();
635 active.set("id", id.to_owned());
636 let fields =
637 super::entities::oauth_consent::Model::columns_from_metadata(metadata)?.into_active();
638 for (column, value) in fields.present() {
639 if !["id", "clientId", "userId", "createdAt", "updatedAt"].contains(&column) {
640 active.set(column, value.clone());
641 }
642 }
643 active.set("updatedAt", updated_at);
644 model::update::<super::entities::oauth_consent::Model>(self.exec(), &active)
645 .await?
646 .map(TryInto::try_into)
647 .transpose()
648 }
649 async fn create_oauth_client(&self, data: CreateOAuthClient) -> AuthResult<OAuthClient> {
650 let mut active = ActiveRow::new();
651 active.set(
652 "id",
653 self.generated_id(self.exec(), "oauthClient", "oauthClient", "id")
654 .await?
655 .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()),
656 );
657 active.set("clientId", data.client_id);
658 active.set("userId", data.user_id);
659 active.set("clientSecret", data.client_secret);
660 let fields = Model::columns_from_metadata(data.metadata)?.into_active();
661 for (column, value) in fields.present() {
662 if ![
663 "id",
664 "clientId",
665 "userId",
666 "clientSecret",
667 "createdAt",
668 "updatedAt",
669 ]
670 .contains(&column)
671 {
672 active.set(column, value.clone());
673 }
674 }
675 active.set("createdAt", data.created_at);
676 active.set("updatedAt", data.created_at);
677 model::insert::<Model>(self.exec(), &active)
678 .await?
679 .try_into()
680 }
681 async fn get_oauth_consent(
682 &self,
683 id: &str,
684 ) -> AuthResult<Option<alibi_core::store::OAuthConsent>> {
685 let mut sql = model::select_model::<super::entities::oauth_consent::Model>(self.exec());
686 sql.push(" WHERE ");
687 sql.compare(
688 super::entities::oauth_consent::Model::TABLE,
689 "id",
690 " = ",
691 id,
692 );
693 model::limit_one(&mut sql);
694 self.exec()
695 .fetch_optional::<super::entities::oauth_consent::Model>(sql)
696 .await?
697 .map(TryInto::try_into)
698 .transpose()
699 }
700 async fn get_oauth_client(&self, client_id: &str) -> AuthResult<Option<OAuthClient>> {
701 let mut sql = model::select_model::<Model>(self.exec());
702 sql.push(" WHERE ");
703 sql.compare(Model::TABLE, "clientId", " = ", client_id);
704 model::limit_one(&mut sql);
705 self.exec()
706 .fetch_optional::<Model>(sql)
707 .await?
708 .map(TryInto::try_into)
709 .transpose()
710 }
711 async fn list_oauth_clients_by_user(&self, user_id: &str) -> AuthResult<Vec<OAuthClient>> {
712 let mut sql = model::select_model::<Model>(self.exec());
713 sql.push(" WHERE ");
714 sql.compare(Model::TABLE, "userId", " = ", user_id);
715 sql.push(" LIMIT ");
716 sql.bind(self.find_many_limit());
717 self.exec()
718 .fetch_all::<Model>(sql)
719 .await?
720 .into_iter()
721 .map(TryInto::try_into)
722 .collect()
723 }
724 async fn delete_oauth_consent(&self, id: &str) -> AuthResult<()> {
725 let mut sql = crate::sql::Sql::with(self.exec().engine(), "DELETE FROM ");
726 sql.ident(super::entities::oauth_consent::Model::TABLE);
727 sql.push(" WHERE ");
728 sql.compare(
729 super::entities::oauth_consent::Model::TABLE,
730 "id",
731 " = ",
732 id,
733 );
734 self.exec().execute(sql).await.map(|_| ())
735 }
736 async fn delete_oauth_client(&self, client_id: &str) -> AuthResult<()> {
737 let mut sql = crate::sql::Sql::with(self.exec().engine(), "DELETE FROM ");
738 sql.ident(Model::TABLE);
739 sql.push(" WHERE ");
740 sql.compare(Model::TABLE, "clientId", " = ", client_id);
741 self.exec().execute(sql).await.map(|_| ())
742 }
743 async fn update_oauth_client_secret(
744 &self,
745 client_id: &str,
746 secret: String,
747 updated_at: chrono::DateTime<chrono::Utc>,
748 ) -> AuthResult<Option<OAuthClient>> {
749 let Some(client) = self.get_oauth_client(client_id).await? else {
750 return Ok(None);
751 };
752 let mut active = ActiveRow::new();
753 active.set("id", client.id);
754 active.set("clientSecret", Some(secret));
755 active.set("updatedAt", updated_at);
756 model::update::<Model>(self.exec(), &active)
757 .await?
758 .map(TryInto::try_into)
759 .transpose()
760 }
761 async fn update_oauth_client_metadata(
762 &self,
763 client_id: &str,
764 metadata: serde_json::Value,
765 updated_at: chrono::DateTime<chrono::Utc>,
766 ) -> AuthResult<Option<OAuthClient>> {
767 let Some(client) = self.get_oauth_client(client_id).await? else {
768 return Ok(None);
769 };
770 let mut active = ActiveRow::new();
771 active.set("id", client.id);
772 let fields = Model::columns_from_metadata(metadata)?.into_active();
773 for (column, value) in fields.present() {
774 if ![
775 "id",
776 "clientId",
777 "userId",
778 "clientSecret",
779 "createdAt",
780 "updatedAt",
781 ]
782 .contains(&column)
783 {
784 active.set(column, value.clone());
785 }
786 }
787 active.set("updatedAt", updated_at);
788 model::update::<Model>(self.exec(), &active)
789 .await?
790 .map(TryInto::try_into)
791 .transpose()
792 }
793}