1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-21 23:00:50 +03:00

data-model: have more structs use a state machine

This commit is contained in:
Quentin Gliech
2023-01-09 18:02:32 +01:00
parent 39cd9a2578
commit 35787aa072
21 changed files with 1148 additions and 621 deletions

View File

@@ -1,4 +1,4 @@
// Copyright 2021, 2022 The Matrix.org Foundation C.I.C.
// Copyright 2021-2023 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,5 +19,5 @@ pub(self) mod session;
pub use self::{
authorization_grant::{AuthorizationCode, AuthorizationGrant, AuthorizationGrantStage, Pkce},
client::{Client, InvalidRedirectUriError, JwksOrJwksUri},
session::Session,
session::{Session, SessionState},
};

View File

@@ -1,4 +1,4 @@
// Copyright 2021 The Matrix.org Foundation C.I.C.
// Copyright 2021-2023 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,22 +19,69 @@ use ulid::Ulid;
use crate::InvalidTransitionError;
trait T {
type State;
}
impl T for Session {
type State = SessionState;
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
pub enum SessionState {
#[default]
Valid,
Finished {
finished_at: DateTime<Utc>,
},
}
impl SessionState {
/// Returns `true` if the session state is [`Valid`].
///
/// [`Valid`]: SessionState::Valid
#[must_use]
pub fn is_valid(&self) -> bool {
matches!(self, Self::Valid)
}
/// Returns `true` if the session state is [`Finished`].
///
/// [`Finished`]: SessionState::Finished
#[must_use]
pub fn is_finished(&self) -> bool {
matches!(self, Self::Finished { .. })
}
pub fn finish(self, finished_at: DateTime<Utc>) -> Result<Self, InvalidTransitionError> {
match self {
Self::Valid => Ok(Self::Finished { finished_at }),
Self::Finished { .. } => Err(InvalidTransitionError),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Session {
pub id: Ulid,
pub state: SessionState,
pub created_at: DateTime<Utc>,
pub user_session_id: Ulid,
pub client_id: Ulid,
pub scope: Scope,
pub finished_at: Option<DateTime<Utc>>,
}
impl std::ops::Deref for Session {
type Target = SessionState;
fn deref(&self) -> &Self::Target {
&self.state
}
}
impl Session {
pub fn finish(mut self, finished_at: DateTime<Utc>) -> Result<Self, InvalidTransitionError> {
if self.finished_at.is_some() {
return Err(InvalidTransitionError);
}
self.finished_at = Some(finished_at);
self.state = self.state.finish(finished_at)?;
Ok(self)
}
}