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