#![cfg_attr(docsrs, feature(doc_cfg))]
use async_session::{async_trait, serde_json, SessionStore};
use sea_orm::prelude::*;
use sea_orm::{sea_query, ConnectionTrait, DatabaseConnection, StatementBuilder};
use sea_query::OnConflict;
#[cfg(feature = "migration")]
#[cfg_attr(docsrs, doc(cfg(feature = "migration")))]
pub mod migration;
pub mod prelude;
mod sessions;
use sessions::Entity as Session;
#[derive(Clone, Debug)]
pub struct DatabaseSessionStore {
connection: DatabaseConnection,
}
impl DatabaseSessionStore {
pub fn new(connection: DatabaseConnection) -> DatabaseSessionStore {
Self { connection }
}
}
#[async_trait]
impl SessionStore for DatabaseSessionStore {
async fn load_session(
&self,
cookie_value: String,
) -> async_session::Result<Option<async_session::Session>> {
let id = async_session::Session::id_from_cookie_value(&cookie_value)?;
Ok(Session::find_by_id(id)
.one(&self.connection)
.await?
.map(|m| serde_json::from_value(m.session))
.transpose()?)
}
async fn store_session(
&self,
session: async_session::Session,
) -> async_session::Result<Option<String>> {
let stmt = StatementBuilder::build(
sea_query::Query::insert()
.into_table(Session)
.columns(vec![sessions::Column::Id, sessions::Column::Session])
.values(vec![
session.id().into(),
serde_json::to_value(&session)?.into(),
])?
.on_conflict(
OnConflict::column(sessions::Column::Id)
.update_columns([sessions::Column::Session])
.to_owned(),
),
&self.connection.get_database_backend(),
);
self.connection.execute(stmt).await?;
Ok(session.into_cookie_value())
}
async fn destroy_session(&self, session: async_session::Session) -> async_session::Result {
Session::delete_by_id(session.id().to_string())
.exec(&self.connection)
.await?;
Ok(())
}
async fn clear_store(&self) -> async_session::Result {
Session::delete_many().exec(&self.connection).await?;
Ok(())
}
}