92 lines
2.8 KiB
Rust
92 lines
2.8 KiB
Rust
|
use anyhow::Result;
|
||
|
use async_session::{async_trait, Session, SessionStore};
|
||
|
use diesel::prelude::*;
|
||
|
|
||
|
use crate::{models::BrowserSession, schema};
|
||
|
|
||
|
#[derive(Clone)]
|
||
|
pub struct PgStore {
|
||
|
// TODO: reference instead of clone
|
||
|
pool: deadpool_diesel::postgres::Pool,
|
||
|
}
|
||
|
|
||
|
impl PgStore {
|
||
|
pub fn new(pool: deadpool_diesel::postgres::Pool) -> PgStore {
|
||
|
Self { pool }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl std::fmt::Debug for PgStore {
|
||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||
|
write!(f, "PgStore {{ pool }}")?;
|
||
|
Ok(()).into()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[async_trait]
|
||
|
impl SessionStore for PgStore {
|
||
|
async fn load_session(&self, cookie_value: String) -> Result<Option<Session>> {
|
||
|
let conn = self.pool.get().await?;
|
||
|
let session_id = Session::id_from_cookie_value(&cookie_value)?;
|
||
|
let rows = conn
|
||
|
.interact(move |conn| {
|
||
|
schema::browser_sessions::table
|
||
|
.filter(schema::browser_sessions::id.eq(session_id))
|
||
|
.select(BrowserSession::as_select())
|
||
|
.load(conn)
|
||
|
})
|
||
|
.await
|
||
|
.unwrap()?;
|
||
|
if rows.len() == 0 {
|
||
|
Ok(None)
|
||
|
} else {
|
||
|
Ok(Some(serde_json::from_str::<Session>(
|
||
|
rows[0].serialized.as_str(),
|
||
|
)?))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async fn store_session(&self, session: Session) -> Result<Option<String>> {
|
||
|
let serialized = serde_json::to_string(&session)?;
|
||
|
let conn = self.pool.get().await?;
|
||
|
let session_id = session.id().to_string();
|
||
|
conn.interact(move |conn| {
|
||
|
diesel::insert_into(schema::browser_sessions::table)
|
||
|
.values((
|
||
|
schema::browser_sessions::id.eq(session_id),
|
||
|
schema::browser_sessions::serialized.eq(serialized.clone()),
|
||
|
))
|
||
|
.on_conflict(schema::browser_sessions::id)
|
||
|
.do_update()
|
||
|
.set(schema::browser_sessions::serialized.eq(serialized.clone()))
|
||
|
.execute(conn)
|
||
|
})
|
||
|
.await
|
||
|
.unwrap()?;
|
||
|
session.reset_data_changed();
|
||
|
Ok(session.into_cookie_value())
|
||
|
}
|
||
|
|
||
|
async fn destroy_session(&self, session: Session) -> Result<()> {
|
||
|
let conn = self.pool.get().await?;
|
||
|
conn.interact(move |conn| {
|
||
|
diesel::delete(
|
||
|
schema::browser_sessions::table
|
||
|
.filter(schema::browser_sessions::id.eq(session.id().to_string())),
|
||
|
)
|
||
|
.execute(conn)
|
||
|
})
|
||
|
.await
|
||
|
.unwrap()?;
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
async fn clear_store(&self) -> Result<()> {
|
||
|
let conn = self.pool.get().await?;
|
||
|
conn.interact(move |conn| diesel::delete(schema::browser_sessions::table).execute(conn))
|
||
|
.await
|
||
|
.unwrap()?;
|
||
|
Ok(())
|
||
|
}
|
||
|
}
|