axum_rh/router/utils/
session_manager.rs1use axum::{
2 extract::FromRequestParts,
3 http::{request::Parts, StatusCode},
4};
5use serde::{Deserialize, Serialize};
6use time::OffsetDateTime;
7use tower_sessions::Session;
8
9pub trait SessionTrait: Send + Sync + Serialize + for<'de> Deserialize<'de> + Default {
10 fn key(&self) -> Option<String>;
11 fn set_key(&mut self, key: String);
12 fn has_key(&self) -> bool {
13 self.key().is_some()
14 }
15}
16
17#[derive(Serialize, Deserialize, Debug, Clone)]
18pub struct SessionData {
19 pub user_id: Option<String>,
20 pub created_at: OffsetDateTime,
21 pub end_at: OffsetDateTime,
22}
23
24impl SessionTrait for SessionData {
25 fn key(&self) -> Option<String> {
26 self.user_id.clone()
27 }
28
29 fn set_key(&mut self, key: String) {
30 self.user_id = Some(key);
31 }
32}
33
34impl Default for SessionData {
35 fn default() -> Self {
36 Self {
37 user_id: None,
38 created_at: OffsetDateTime::now_utc(),
39 end_at: OffsetDateTime::now_utc(),
40 }
41 }
42}
43pub struct SessionObject<T>
44where
45 T: SessionTrait,
46{
47 pub session: Session,
48 pub data: T,
49}
50
51impl<T> SessionObject<T>
52where
53 T: SessionTrait,
54{
55 const DATA_KEY: &'static str = "data";
56
57 pub async fn update(&mut self) {
58 Self::update_session(&self.session, &self.data).await;
59 }
60
61 pub async fn update_key(&mut self, key: String) {
62 self.data.set_key(key);
63 self.update().await;
64 }
65
66 async fn update_session(session: &Session, session_data: &T) {
67 match session.insert(Self::DATA_KEY, session_data).await {
68 Ok(_) => {}
69 Err(e) => {
70 log::error!("Error updating session: {:?}", e);
71 }
72 };
73 match session.save().await {
74 Ok(_) => {}
75 Err(e) => {
76 log::error!("Error saving session: {:?}", e);
77 }
78 };
79 }
80
81 pub async fn clear(&mut self) {
82 self.data = T::default();
83 self.session.clear().await;
84 }
85}
86
87impl<S, T> FromRequestParts<S> for SessionObject<T>
88where
89 S: Send + Sync,
90 T: SessionTrait,
91{
92 type Rejection = (StatusCode, &'static str);
93
94 async fn from_request_parts(req: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
95 let session = Session::from_request_parts(req, state).await?;
96
97 let data: T = session
98 .get(Self::DATA_KEY)
99 .await
100 .expect("session data not found")
101 .unwrap_or_default();
102
103 Self::update_session(&session, &data).await;
104 Ok(Self { session, data })
105 }
106}