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> { 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::( rows[0].serialized.as_str(), )?)) } } async fn store_session(&self, session: Session) -> Result> { 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(()) } }