1use super::*;
2use anyhow::Context as _;
3use sea_orm::sea_query::Query;
4
5impl Database {
6 /// Creates a new access token for the given user.
7 pub async fn create_access_token(
8 &self,
9 user_id: UserId,
10 impersonated_user_id: Option<UserId>,
11 access_token_hash: &str,
12 max_access_token_count: usize,
13 ) -> Result<AccessTokenId> {
14 self.transaction(|tx| async {
15 let tx = tx;
16
17 let token = access_token::ActiveModel {
18 user_id: ActiveValue::set(user_id),
19 impersonated_user_id: ActiveValue::set(impersonated_user_id),
20 hash: ActiveValue::set(access_token_hash.into()),
21 ..Default::default()
22 }
23 .insert(&*tx)
24 .await?;
25
26 access_token::Entity::delete_many()
27 .filter(
28 access_token::Column::Id.in_subquery(
29 Query::select()
30 .column(access_token::Column::Id)
31 .from(access_token::Entity)
32 .and_where(access_token::Column::UserId.eq(user_id))
33 .order_by(access_token::Column::Id, sea_orm::Order::Desc)
34 .limit(10000)
35 .offset(max_access_token_count as u64)
36 .to_owned(),
37 ),
38 )
39 .exec(&*tx)
40 .await?;
41 Ok(token.id)
42 })
43 .await
44 }
45
46 /// Retrieves the access token with the given ID.
47 pub async fn get_access_token(
48 &self,
49 access_token_id: AccessTokenId,
50 ) -> Result<access_token::Model> {
51 self.transaction(|tx| async move {
52 Ok(access_token::Entity::find_by_id(access_token_id)
53 .one(&*tx)
54 .await?
55 .context("no such access token")?)
56 })
57 .await
58 }
59
60 /// Retrieves the access token with the given ID.
61 pub async fn update_access_token_hash(
62 &self,
63 id: AccessTokenId,
64 new_hash: &str,
65 ) -> Result<access_token::Model> {
66 self.transaction(|tx| async move {
67 Ok(access_token::Entity::update(access_token::ActiveModel {
68 id: ActiveValue::unchanged(id),
69 hash: ActiveValue::set(new_hash.into()),
70 ..Default::default()
71 })
72 .exec(&*tx)
73 .await?)
74 })
75 .await
76 }
77}