108 lines
2.7 KiB
Rust
108 lines
2.7 KiB
Rust
use anyhow::Result;
|
|
use diesel::prelude::*;
|
|
use async_trait::async_trait;
|
|
|
|
pub use std::sync::Arc;
|
|
pub use tokio::sync::Mutex;
|
|
|
|
use crate::repository::Repository;
|
|
use crate::settings::Settings;
|
|
|
|
pub use kordophone::api::TokenStore;
|
|
use kordophone::model::JwtToken;
|
|
|
|
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
|
|
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
|
|
|
|
#[async_trait]
|
|
pub trait DatabaseAccess {
|
|
async fn with_repository<F, R>(&mut self, f: F) -> R
|
|
where
|
|
F: FnOnce(&mut Repository) -> R + Send,
|
|
R: Send;
|
|
|
|
async fn with_settings<F, R>(&mut self, f: F) -> R
|
|
where
|
|
F: FnOnce(&mut Settings) -> R + Send,
|
|
R: Send;
|
|
}
|
|
|
|
pub struct Database {
|
|
pub connection: SqliteConnection,
|
|
}
|
|
|
|
impl Database {
|
|
pub fn new(path: &str) -> Result<Self> {
|
|
let mut connection = SqliteConnection::establish(path)?;
|
|
connection.run_pending_migrations(MIGRATIONS)
|
|
.map_err(|e| anyhow::anyhow!("Error running migrations: {}", e))?;
|
|
|
|
Ok(Self { connection })
|
|
}
|
|
|
|
pub fn new_in_memory() -> Result<Self> {
|
|
Self::new(":memory:")
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl DatabaseAccess for Database {
|
|
async fn with_repository<F, R>(&mut self, f: F) -> R
|
|
where
|
|
F: FnOnce(&mut Repository) -> R + Send,
|
|
R: Send,
|
|
{
|
|
let mut repository = Repository::new(&mut self.connection);
|
|
f(&mut repository)
|
|
}
|
|
|
|
async fn with_settings<F, R>(&mut self, f: F) -> R
|
|
where
|
|
F: FnOnce(&mut Settings) -> R + Send,
|
|
R: Send,
|
|
{
|
|
let mut settings = Settings::new(&mut self.connection);
|
|
f(&mut settings)
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl DatabaseAccess for Arc<Mutex<Database>> {
|
|
async fn with_repository<F, R>(&mut self, f: F) -> R
|
|
where
|
|
F: FnOnce(&mut Repository) -> R + Send,
|
|
R: Send,
|
|
{
|
|
let mut database = self.lock().await;
|
|
database.with_repository(f).await
|
|
}
|
|
|
|
async fn with_settings<F, R>(&mut self, f: F) -> R
|
|
where
|
|
F: FnOnce(&mut Settings) -> R + Send,
|
|
R: Send,
|
|
{
|
|
let mut database = self.lock().await;
|
|
database.with_settings(f).await
|
|
}
|
|
}
|
|
|
|
static TOKEN_KEY: &str = "token";
|
|
|
|
#[async_trait]
|
|
impl TokenStore for Database {
|
|
async fn get_token(&mut self) -> Option<JwtToken> {
|
|
self.with_settings(|settings| {
|
|
let token: Result<Option<JwtToken>> = settings.get(TOKEN_KEY);
|
|
match token {
|
|
Ok(data) => data,
|
|
Err(_) => None,
|
|
}
|
|
}).await
|
|
}
|
|
|
|
async fn set_token(&mut self, token: JwtToken) {
|
|
self.with_settings(|settings| settings.put(TOKEN_KEY, &token).unwrap()).await;
|
|
}
|
|
}
|