Skip to content
This repository was archived by the owner on Sep 10, 2024. It is now read-only.

Commit e6b91c1

Browse files
committed
data-model: make the access token expiration optional
1 parent 83ca90e commit e6b91c1

File tree

6 files changed

+79
-18
lines changed

6 files changed

+79
-18
lines changed

crates/data-model/src/compat/session.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,33 @@ pub enum CompatSessionState {
2929
}
3030

3131
impl CompatSessionState {
32-
/// Returns `true` if the compta session state is [`Valid`].
32+
/// Returns `true` if the compat session state is [`Valid`].
3333
///
3434
/// [`Valid`]: CompatSessionState::Valid
3535
#[must_use]
3636
pub fn is_valid(&self) -> bool {
3737
matches!(self, Self::Valid)
3838
}
3939

40-
/// Returns `true` if the compta session state is [`Finished`].
40+
/// Returns `true` if the compat session state is [`Finished`].
4141
///
4242
/// [`Finished`]: CompatSessionState::Finished
4343
#[must_use]
4444
pub fn is_finished(&self) -> bool {
4545
matches!(self, Self::Finished { .. })
4646
}
4747

48+
/// Transitions the session state to [`Finished`].
49+
///
50+
/// # Parameters
51+
///
52+
/// * `finished_at` - The time at which the session was finished.
53+
///
54+
/// # Errors
55+
///
56+
/// Returns an error if the session state is already [`Finished`].
57+
///
58+
/// [`Finished`]: CompatSessionState::Finished
4859
pub fn finish(self, finished_at: DateTime<Utc>) -> Result<Self, InvalidTransitionError> {
4960
match self {
5061
Self::Valid => Ok(Self::Finished { finished_at }),
@@ -80,6 +91,15 @@ impl std::ops::Deref for CompatSession {
8091
}
8192

8293
impl CompatSession {
94+
/// Marks the session as finished.
95+
///
96+
/// # Parameters
97+
///
98+
/// * `finished_at` - The time at which the session was finished.
99+
///
100+
/// # Errors
101+
///
102+
/// Returns an error if the session is already finished.
83103
pub fn finish(mut self, finished_at: DateTime<Utc>) -> Result<Self, InvalidTransitionError> {
84104
self.state = self.state.finish(finished_at)?;
85105
Ok(self)

crates/data-model/src/oauth2/session.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,6 @@ use ulid::Ulid;
1919

2020
use crate::InvalidTransitionError;
2121

22-
trait T {
23-
type State;
24-
}
25-
26-
impl T for Session {
27-
type State = SessionState;
28-
}
29-
3022
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
3123
pub enum SessionState {
3224
#[default]
@@ -53,6 +45,17 @@ impl SessionState {
5345
matches!(self, Self::Finished { .. })
5446
}
5547

48+
/// Transitions the session state to [`Finished`].
49+
///
50+
/// # Parameters
51+
///
52+
/// * `finished_at` - The time at which the session was finished.
53+
///
54+
/// # Errors
55+
///
56+
/// Returns an error if the session state is already [`Finished`].
57+
///
58+
/// [`Finished`]: SessionState::Finished
5659
pub fn finish(self, finished_at: DateTime<Utc>) -> Result<Self, InvalidTransitionError> {
5760
match self {
5861
Self::Valid => Ok(Self::Finished { finished_at }),
@@ -81,6 +84,15 @@ impl std::ops::Deref for Session {
8184
}
8285

8386
impl Session {
87+
/// Marks the session as finished.
88+
///
89+
/// # Parameters
90+
///
91+
/// * `finished_at` - The time at which the session was finished.
92+
///
93+
/// # Errors
94+
///
95+
/// Returns an error if the session is already finished.
8496
pub fn finish(mut self, finished_at: DateTime<Utc>) -> Result<Self, InvalidTransitionError> {
8597
self.state = self.state.finish(finished_at)?;
8698
Ok(self)

crates/data-model/src/tokens.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub struct AccessToken {
6262
pub session_id: Ulid,
6363
pub access_token: String,
6464
pub created_at: DateTime<Utc>,
65-
pub expires_at: DateTime<Utc>,
65+
pub expires_at: Option<DateTime<Utc>>,
6666
}
6767

6868
impl AccessToken {
@@ -71,11 +71,40 @@ impl AccessToken {
7171
self.id.to_string()
7272
}
7373

74+
/// Whether the access token is valid, i.e. not revoked and not expired
75+
///
76+
/// # Parameters
77+
///
78+
/// * `now` - The current time
7479
#[must_use]
7580
pub fn is_valid(&self, now: DateTime<Utc>) -> bool {
76-
self.state.is_valid() && self.expires_at > now
81+
self.state.is_valid() && !self.is_expired(now)
7782
}
7883

84+
/// Whether the access token is expired
85+
///
86+
/// Always returns `false` if the access token does not have an expiry time.
87+
///
88+
/// # Parameters
89+
///
90+
/// * `now` - The current time
91+
#[must_use]
92+
pub fn is_expired(&self, now: DateTime<Utc>) -> bool {
93+
match self.expires_at {
94+
Some(expires_at) => expires_at < now,
95+
None => false,
96+
}
97+
}
98+
99+
/// Mark the access token as revoked
100+
///
101+
/// # Parameters
102+
///
103+
/// * `revoked_at` - The time at which the access token was revoked
104+
///
105+
/// # Errors
106+
///
107+
/// Returns an error if the access token is already revoked
79108
pub fn revoke(mut self, revoked_at: DateTime<Utc>) -> Result<Self, InvalidTransitionError> {
80109
self.state = self.state.revoke(revoked_at)?;
81110
Ok(self)

crates/graphql/src/mutations/oauth2_session.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,9 @@ impl OAuth2SessionMutations {
187187
.add(&mut rng, &clock, &session, access_token, ttl)
188188
.await?;
189189

190-
let refresh_token = if !permanent {
190+
let refresh_token = if permanent {
191+
None
192+
} else {
191193
let refresh_token = TokenType::RefreshToken.generate(&mut rng);
192194

193195
let refresh_token = repo
@@ -196,8 +198,6 @@ impl OAuth2SessionMutations {
196198
.await?;
197199

198200
Some(refresh_token)
199-
} else {
200-
None
201201
};
202202

203203
Ok(CreateOAuth2SessionPayload {

crates/handlers/src/oauth2/introspection.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ pub(crate) async fn post(
209209
client_id: Some(session.client_id.to_string()),
210210
username,
211211
token_type: Some(OAuthTokenTypeHint::AccessToken),
212-
exp: Some(token.expires_at),
212+
exp: token.expires_at,
213213
iat: Some(token.created_at),
214214
nbf: Some(token.created_at),
215215
sub,

crates/storage-pg/src/oauth2/access_token.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl From<OAuth2AccessTokenLookup> for AccessToken {
5959
session_id: value.oauth2_session_id.into(),
6060
access_token: value.access_token,
6161
created_at: value.created_at,
62-
expires_at: value.expires_at,
62+
expires_at: Some(value.expires_at),
6363
}
6464
}
6565
}
@@ -177,7 +177,7 @@ impl<'c> OAuth2AccessTokenRepository for PgOAuth2AccessTokenRepository<'c> {
177177
access_token,
178178
session_id: session.id,
179179
created_at,
180-
expires_at,
180+
expires_at: Some(expires_at),
181181
})
182182
}
183183

0 commit comments

Comments
 (0)