mas_storage/oauth2/
access_token.rs

1// Copyright 2024 New Vector Ltd.
2// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
3//
4// SPDX-License-Identifier: AGPL-3.0-only
5// Please see LICENSE in the repository root for full details.
6
7use async_trait::async_trait;
8use chrono::Duration;
9use mas_data_model::{AccessToken, Session};
10use rand_core::RngCore;
11use ulid::Ulid;
12
13use crate::{Clock, repository_impl};
14
15/// An [`OAuth2AccessTokenRepository`] helps interacting with [`AccessToken`]
16/// saved in the storage backend
17#[async_trait]
18pub trait OAuth2AccessTokenRepository: Send + Sync {
19    /// The error type returned by the repository
20    type Error;
21
22    /// Lookup an access token by its ID
23    ///
24    /// Returns the access token if it exists, `None` otherwise
25    ///
26    /// # Parameters
27    ///
28    /// * `id`: The ID of the access token to lookup
29    ///
30    /// # Errors
31    ///
32    /// Returns [`Self::Error`] if the underlying repository fails
33    async fn lookup(&mut self, id: Ulid) -> Result<Option<AccessToken>, Self::Error>;
34
35    /// Find an access token by its token
36    ///
37    /// Returns the access token if it exists, `None` otherwise
38    ///
39    /// # Parameters
40    ///
41    /// * `access_token`: The token of the access token to lookup
42    ///
43    /// # Errors
44    ///
45    /// Returns [`Self::Error`] if the underlying repository fails
46    async fn find_by_token(
47        &mut self,
48        access_token: &str,
49    ) -> Result<Option<AccessToken>, Self::Error>;
50
51    /// Add a new access token to the database
52    ///
53    /// Returns the newly created access token
54    ///
55    /// # Parameters
56    ///
57    /// * `rng`: A random number generator
58    /// * `clock`: The clock used to generate timestamps
59    /// * `session`: The session the access token is associated with
60    /// * `access_token`: The access token to add
61    /// * `expires_after`: The duration after which the access token expires. If
62    ///   [`None`] the access token never expires
63    ///
64    /// # Errors
65    ///
66    /// Returns [`Self::Error`] if the underlying repository fails
67    async fn add(
68        &mut self,
69        rng: &mut (dyn RngCore + Send),
70        clock: &dyn Clock,
71        session: &Session,
72        access_token: String,
73        expires_after: Option<Duration>,
74    ) -> Result<AccessToken, Self::Error>;
75
76    /// Revoke an access token
77    ///
78    /// Returns the revoked access token
79    ///
80    /// # Parameters
81    ///
82    /// * `clock`: The clock used to generate timestamps
83    /// * `access_token`: The access token to revoke
84    ///
85    /// # Errors
86    ///
87    /// Returns [`Self::Error`] if the underlying repository fails
88    async fn revoke(
89        &mut self,
90        clock: &dyn Clock,
91        access_token: AccessToken,
92    ) -> Result<AccessToken, Self::Error>;
93
94    /// Mark the access token as used, to track when it was first used
95    ///
96    /// # Parameters
97    ///
98    /// * `clock`: The clock used to generate timestamps
99    /// * `access_token`: The access token to mark as used
100    ///
101    /// # Errors
102    ///
103    /// Returns [`Self::Error`] if the underlying repository fails
104    async fn mark_used(
105        &mut self,
106        clock: &dyn Clock,
107        access_token: AccessToken,
108    ) -> Result<AccessToken, Self::Error>;
109
110    /// Cleanup revoked access tokens
111    ///
112    /// Returns the number of access tokens that were cleaned up
113    ///
114    /// # Parameters
115    ///
116    /// * `clock`: The clock used to get the current time
117    ///
118    /// # Errors
119    ///
120    /// Returns [`Self::Error`] if the underlying repository fails
121    async fn cleanup_revoked(&mut self, clock: &dyn Clock) -> Result<usize, Self::Error>;
122}
123
124repository_impl!(OAuth2AccessTokenRepository:
125    async fn lookup(&mut self, id: Ulid) -> Result<Option<AccessToken>, Self::Error>;
126
127    async fn find_by_token(
128        &mut self,
129        access_token: &str,
130    ) -> Result<Option<AccessToken>, Self::Error>;
131
132    async fn add(
133        &mut self,
134        rng: &mut (dyn RngCore + Send),
135        clock: &dyn Clock,
136        session: &Session,
137        access_token: String,
138        expires_after: Option<Duration>,
139    ) -> Result<AccessToken, Self::Error>;
140
141    async fn revoke(
142        &mut self,
143        clock: &dyn Clock,
144        access_token: AccessToken,
145    ) -> Result<AccessToken, Self::Error>;
146
147    async fn mark_used(
148        &mut self,
149        clock: &dyn Clock,
150        access_token: AccessToken,
151    ) -> Result<AccessToken, Self::Error>;
152
153    async fn cleanup_revoked(&mut self, clock: &dyn Clock) -> Result<usize, Self::Error>;
154);