diff --git a/Cargo.lock b/Cargo.lock index 7b7290d..b5bed9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1644,6 +1644,7 @@ version = "0.1.0" dependencies = [ "actix-web", "anyhow", + "async-trait", "clap", "env_logger", "rustical_api", @@ -1651,6 +1652,7 @@ dependencies = [ "rustical_caldav", "rustical_store", "serde", + "sqlx", "tokio", "toml", "tracing", diff --git a/Cargo.toml b/Cargo.toml index 5be8ee6..e0d4e0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,3 +22,15 @@ actix-web = "4.4.0" anyhow = { version = "1.0.75", features = ["backtrace"] } toml = "0.7.6" clap = { version = "4.4.2", features = ["derive", "env"] } +sqlx = { version = "0.7.1", features = [ + "sqlx-sqlite", + "sqlx-postgres", + "uuid", + "time", + "chrono", + "postgres", + "sqlite", + "runtime-tokio", + "migrate", +] } +async-trait = "0.1.73" diff --git a/crates/store/Cargo.toml b/crates/store/Cargo.toml index 0fb9e6a..3c03bf6 100644 --- a/crates/store/Cargo.toml +++ b/crates/store/Cargo.toml @@ -19,6 +19,7 @@ sqlx = { version = "0.7.1", features = [ "postgres", "sqlite", "runtime-tokio", + "migrate", ] } tokio = { version = "1.32.0", features = ["sync", "full"] } toml = "0.7.6" diff --git a/crates/store/src/lib.rs b/crates/store/src/lib.rs index 81bc558..938ac8c 100644 --- a/crates/store/src/lib.rs +++ b/crates/store/src/lib.rs @@ -1,4 +1,5 @@ pub mod calendar; pub mod event; +pub mod sqlite_store; pub mod timestamps; pub mod toml_store; diff --git a/crates/store/src/sqlite_store.rs b/crates/store/src/sqlite_store.rs new file mode 100644 index 0000000..0f49a99 --- /dev/null +++ b/crates/store/src/sqlite_store.rs @@ -0,0 +1,54 @@ +use std::sync::Arc; + +use anyhow::{anyhow, Result}; +use async_trait::async_trait; +use sqlx::SqlitePool; + +use crate::calendar::{Calendar, CalendarStore}; + +#[derive(Debug)] +pub struct SqliteCalendarStore { + db: Arc, +} + +impl SqliteCalendarStore { + pub fn new(db: Arc) -> Self { + Self { db } + } +} + +#[async_trait] +impl CalendarStore for SqliteCalendarStore { + async fn get_calendar(&self, id: &str) -> Result { + let a = sqlx::query_as!( + Calendar, + "SELECT id, name, owner, description, color, timezone FROM calendars WHERE id = ?", + id + ); + Err(anyhow!("ok wow")) + } + + async fn get_calendars(&self, _owner: &str) -> Result> { + Err(anyhow!("ok wow")) + } + + async fn insert_calendar(&mut self, _cid: String, _calendar: Calendar) -> Result<()> { + Err(anyhow!("ok wow")) + } + + async fn get_events(&self, _cid: &str) -> Result> { + Err(anyhow!("ok wow")) + } + + async fn get_event(&self, _cid: &str, _uid: &str) -> Result { + Err(anyhow!("ok wow")) + } + + async fn upsert_event(&mut self, _cid: String, _uid: String, _ics: String) -> Result<()> { + Err(anyhow!("ok wow")) + } + + async fn delete_event(&mut self, _cid: &str, _uid: &str) -> Result<()> { + Err(anyhow!("ok wow")) + } +} diff --git a/src/config.rs b/src/config.rs index 4be5f85..f41b201 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,10 +6,16 @@ pub struct TomlCalendarStoreConfig { pub db_path: String, } +#[derive(Debug, Deserialize, Serialize)] +pub struct SqliteCalendarStoreConfig { + pub db_url: String, +} + #[derive(Debug, Deserialize, Serialize)] #[serde(tag = "backend", rename_all = "snake_case")] pub enum CalendarStoreConfig { Toml(TomlCalendarStoreConfig), + Sqlite(SqliteCalendarStoreConfig), } #[derive(Debug, Deserialize, Serialize)] diff --git a/src/main.rs b/src/main.rs index c21a9be..43a28a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,11 +3,14 @@ use actix_web::middleware::{Logger, NormalizePath}; use actix_web::{web, App, HttpServer}; use anyhow::Result; use clap::Parser; -use config::{CalendarStoreConfig, TomlCalendarStoreConfig}; +use config::{CalendarStoreConfig, SqliteCalendarStoreConfig, TomlCalendarStoreConfig}; use rustical_api::configure_api; use rustical_auth::AuthProvider; use rustical_caldav::{configure_dav, configure_well_known}; +use rustical_store::calendar::CalendarStore; +use rustical_store::sqlite_store::SqliteCalendarStore; use rustical_store::toml_store::TomlCalendarStore; +use sqlx::SqlitePool; use std::fs; use std::sync::Arc; use tokio::sync::RwLock; @@ -28,14 +31,18 @@ async fn main() -> Result<()> { let args = Args::parse(); let config: Config = toml::from_str(&fs::read_to_string(&args.config_file)?)?; - let cal_store = Arc::new(RwLock::new(match &config.calendar_store { + let cal_store: Arc> = match &config.calendar_store { CalendarStoreConfig::Toml(TomlCalendarStoreConfig { db_path }) => { - match fs::read_to_string(db_path) { + Arc::new(RwLock::new(match fs::read_to_string(db_path) { Ok(content) => toml::from_str::(&content).unwrap(), Err(_) => TomlCalendarStore::new(db_path.to_string()), - } + })) } - })); + CalendarStoreConfig::Sqlite(SqliteCalendarStoreConfig { db_url }) => { + let db = SqlitePool::connect(db_url).await?; + Arc::new(RwLock::new(SqliteCalendarStore::new(Arc::new(db)))) + } + }; let auth: Arc = Arc::new(config.auth.into());