Something went wrong. Try again.
Learn how to use Rust to build ATProto powered applications
Something went wrong. Try again.
4.6 kB · 145 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146/// Storage impls to persis OAuth sessions if you are not using the memory stores/// https://github.com/bluesky-social/statusphere-example-app/blob/main/src/auth/storage.tsuse crate::db::{AuthSession, AuthState};use async_sqlite::Pool;use atrium_api::types::string::Did;use atrium_common::store::Store;use atrium_oauth::store::session::SessionStore;use atrium_oauth::store::state::StateStore;use serde::Serialize;use serde::de::DeserializeOwned;use std::fmt::Debug;use std::hash::Hash;use thiserror::Error;
#[derive(Error, Debug)]pub enum SqliteStoreError { #[error("Invalid session")] InvalidSession, #[error("No session found")] NoSessionFound, #[error("Database error: {0}")] DatabaseError(async_sqlite::Error),}
///Persistent session store in sqliteimpl SessionStore for SqliteSessionStore {}
pub struct SqliteSessionStore { db_pool: Pool,}
impl SqliteSessionStore { pub fn new(db: Pool) -> Self { Self { db_pool: db } }}
impl<K, V> Store<K, V> for SqliteSessionStorewhere K: Debug + Eq + Hash + Send + Sync + 'static + From<Did> + AsRef<str>, V: Debug + Clone + Send + Sync + 'static + Serialize + DeserializeOwned,{ type Error = SqliteStoreError; async fn get(&self, key: &K) -> Result<Option<V>, Self::Error> { let did = key.as_ref().to_string(); match AuthSession::get_by_did(&self.db_pool, did).await { Ok(Some(auth_session)) => { let deserialized_session: V = serde_json::from_str(&auth_session.session) .map_err(|_| SqliteStoreError::InvalidSession)?; Ok(Some(deserialized_session)) } Ok(None) => Err(SqliteStoreError::NoSessionFound), Err(db_error) => { log::error!("Database error: {db_error}"); Err(SqliteStoreError::DatabaseError(db_error)) } } }
async fn set(&self, key: K, value: V) -> Result<(), Self::Error> { let did = key.as_ref().to_string(); let auth_session = AuthSession::new(did, value); auth_session .save_or_update(&self.db_pool) .await .map_err(SqliteStoreError::DatabaseError)?; Ok(()) }
async fn del(&self, _key: &K) -> Result<(), Self::Error> { let did = _key.as_ref().to_string(); AuthSession::delete_by_did(&self.db_pool, did) .await .map_err(SqliteStoreError::DatabaseError)?; Ok(()) }
async fn clear(&self) -> Result<(), Self::Error> { AuthSession::delete_all(&self.db_pool) .await .map_err(SqliteStoreError::DatabaseError)?; Ok(()) }}
///Persistent session state in sqliteimpl StateStore for SqliteStateStore {}
pub struct SqliteStateStore { db_pool: Pool,}
impl SqliteStateStore { pub fn new(db: Pool) -> Self { Self { db_pool: db } }}
impl<K, V> Store<K, V> for SqliteStateStorewhere K: Debug + Eq + Hash + Send + Sync + 'static + From<Did> + AsRef<str>, V: Debug + Clone + Send + Sync + 'static + Serialize + DeserializeOwned,{ type Error = SqliteStoreError; async fn get(&self, key: &K) -> Result<Option<V>, Self::Error> { let key = key.as_ref().to_string(); match AuthState::get_by_key(&self.db_pool, key).await { Ok(Some(auth_state)) => { let deserialized_state: V = serde_json::from_str(&auth_state.state) .map_err(|_| SqliteStoreError::InvalidSession)?; Ok(Some(deserialized_state)) } Ok(None) => Err(SqliteStoreError::NoSessionFound), Err(db_error) => { log::error!("Database error: {db_error}"); Err(SqliteStoreError::DatabaseError(db_error)) } } }
async fn set(&self, key: K, value: V) -> Result<(), Self::Error> { let did = key.as_ref().to_string(); let auth_state = AuthState::new(did, value); auth_state .save_or_update(&self.db_pool) .await .map_err(SqliteStoreError::DatabaseError)?; Ok(()) }
async fn del(&self, _key: &K) -> Result<(), Self::Error> { let key = _key.as_ref().to_string(); AuthState::delete_by_key(&self.db_pool, key) .await .map_err(SqliteStoreError::DatabaseError)?; Ok(()) }
async fn clear(&self) -> Result<(), Self::Error> { AuthState::delete_all(&self.db_pool) .await .map_err(SqliteStoreError::DatabaseError)?; Ok(()) }}