mas_data_model/compat/
mod.rs

1// Copyright 2024 New Vector Ltd.
2// Copyright 2022-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 chrono::{DateTime, Utc};
8use ulid::Ulid;
9
10mod device;
11mod session;
12mod sso_login;
13
14pub use self::{
15    device::{Device, ToScopeTokenError},
16    session::{CompatSession, CompatSessionState},
17    sso_login::{CompatSsoLogin, CompatSsoLoginState},
18};
19use crate::InvalidTransitionError;
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct CompatAccessToken {
23    pub id: Ulid,
24    pub session_id: Ulid,
25    pub token: String,
26    pub created_at: DateTime<Utc>,
27    pub expires_at: Option<DateTime<Utc>>,
28}
29
30impl CompatAccessToken {
31    #[must_use]
32    pub fn is_valid(&self, now: DateTime<Utc>) -> bool {
33        if let Some(expires_at) = self.expires_at {
34            expires_at > now
35        } else {
36            true
37        }
38    }
39}
40
41#[derive(Debug, Clone, Default, PartialEq, Eq)]
42pub enum CompatRefreshTokenState {
43    #[default]
44    Valid,
45    Consumed {
46        consumed_at: DateTime<Utc>,
47    },
48}
49
50impl CompatRefreshTokenState {
51    /// Returns `true` if the compat refresh token state is [`Valid`].
52    ///
53    /// [`Valid`]: CompatRefreshTokenState::Valid
54    #[must_use]
55    pub fn is_valid(&self) -> bool {
56        matches!(self, Self::Valid)
57    }
58
59    /// Returns `true` if the compat refresh token state is [`Consumed`].
60    ///
61    /// [`Consumed`]: CompatRefreshTokenState::Consumed
62    #[must_use]
63    pub fn is_consumed(&self) -> bool {
64        matches!(self, Self::Consumed { .. })
65    }
66
67    /// Consume the refresh token, returning a new state.
68    ///
69    /// # Errors
70    ///
71    /// Returns an error if the refresh token is already consumed.
72    pub fn consume(self, consumed_at: DateTime<Utc>) -> Result<Self, InvalidTransitionError> {
73        match self {
74            Self::Valid => Ok(Self::Consumed { consumed_at }),
75            Self::Consumed { .. } => Err(InvalidTransitionError),
76        }
77    }
78}
79
80#[derive(Debug, Clone, PartialEq, Eq)]
81pub struct CompatRefreshToken {
82    pub id: Ulid,
83    pub state: CompatRefreshTokenState,
84    pub session_id: Ulid,
85    pub access_token_id: Ulid,
86    pub token: String,
87    pub created_at: DateTime<Utc>,
88}
89
90impl std::ops::Deref for CompatRefreshToken {
91    type Target = CompatRefreshTokenState;
92
93    fn deref(&self) -> &Self::Target {
94        &self.state
95    }
96}
97
98impl CompatRefreshToken {
99    /// Consume the refresh token and return the consumed token.
100    ///
101    /// # Errors
102    ///
103    /// Returns an error if the refresh token is already consumed.
104    pub fn consume(mut self, consumed_at: DateTime<Utc>) -> Result<Self, InvalidTransitionError> {
105        self.state = self.state.consume(consumed_at)?;
106        Ok(self)
107    }
108}