mas_data_model/oauth2/
session.rs1use std::net::IpAddr;
8
9use chrono::{DateTime, Utc};
10use oauth2_types::scope::Scope;
11use serde::Serialize;
12use ulid::Ulid;
13
14use crate::{InvalidTransitionError, UserAgent};
15
16#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
17pub enum SessionState {
18 #[default]
19 Valid,
20 Finished {
21 finished_at: DateTime<Utc>,
22 },
23}
24
25impl SessionState {
26 #[must_use]
30 pub fn is_valid(&self) -> bool {
31 matches!(self, Self::Valid)
32 }
33
34 #[must_use]
38 pub fn is_finished(&self) -> bool {
39 matches!(self, Self::Finished { .. })
40 }
41
42 pub fn finish(self, finished_at: DateTime<Utc>) -> Result<Self, InvalidTransitionError> {
54 match self {
55 Self::Valid => Ok(Self::Finished { finished_at }),
56 Self::Finished { .. } => Err(InvalidTransitionError),
57 }
58 }
59
60 #[must_use]
66 pub fn finished_at(&self) -> Option<DateTime<Utc>> {
67 match self {
68 Self::Valid => None,
69 Self::Finished { finished_at } => Some(*finished_at),
70 }
71 }
72}
73
74#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
75pub struct Session {
76 pub id: Ulid,
77 pub state: SessionState,
78 pub created_at: DateTime<Utc>,
79 pub user_id: Option<Ulid>,
80 pub user_session_id: Option<Ulid>,
81 pub client_id: Ulid,
82 pub scope: Scope,
83 pub user_agent: Option<UserAgent>,
84 pub last_active_at: Option<DateTime<Utc>>,
85 pub last_active_ip: Option<IpAddr>,
86}
87
88impl std::ops::Deref for Session {
89 type Target = SessionState;
90
91 fn deref(&self) -> &Self::Target {
92 &self.state
93 }
94}
95
96impl Session {
97 pub fn finish(mut self, finished_at: DateTime<Utc>) -> Result<Self, InvalidTransitionError> {
107 self.state = self.state.finish(finished_at)?;
108 Ok(self)
109 }
110}