mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-14 01:12:24 +00:00
Initial commit
This commit is contained in:
1748
crates/store/Cargo.lock
generated
Normal file
1748
crates/store/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
15
crates/store/Cargo.toml
Normal file
15
crates/store/Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "rustical_store"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1.0.75", features = ["backtrace"] }
|
||||
async-trait = "0.1.73"
|
||||
serde = { version = "1.0.188", features = ["derive", "rc"] }
|
||||
serde_json = "1.0.105"
|
||||
sha2 = "0.10.7"
|
||||
sqlx = { version = "0.7.1", features = ["sqlx-sqlite", "sqlx-postgres", "uuid", "time", "chrono", "postgres", "sqlite", "runtime-tokio"] }
|
||||
tokio = { version = "1.32.0", features = ["sync", "full"] }
|
||||
108
crates/store/src/calendar.rs
Normal file
108
crates/store/src/calendar.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
use tokio::{fs::File, io::AsyncWriteExt};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct Event {
|
||||
uid: String,
|
||||
ics: String,
|
||||
}
|
||||
|
||||
impl Event {
|
||||
pub fn get_uid(&self) -> &str {
|
||||
&self.uid
|
||||
}
|
||||
pub fn get_etag(&self) -> String {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(&self.uid);
|
||||
hasher.update(self.to_ics());
|
||||
format!("{:x}", hasher.finalize())
|
||||
}
|
||||
|
||||
pub fn to_ics(&self) -> &str {
|
||||
&self.ics
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct Calendar {
|
||||
pub id: String,
|
||||
pub name: Option<String>,
|
||||
pub ics: String,
|
||||
}
|
||||
|
||||
impl Calendar {}
|
||||
|
||||
#[async_trait]
|
||||
pub trait CalendarStore: Send + Sync + 'static {
|
||||
async fn get_calendar(&self, id: &str) -> Result<Calendar>;
|
||||
async fn get_calendars(&self) -> Result<Vec<Calendar>>;
|
||||
|
||||
async fn get_events(&self, cid: &str) -> Result<Vec<Event>>;
|
||||
async fn get_event(&self, uid: &str) -> Result<Event>;
|
||||
async fn upsert_event(&mut self, uid: String, ics: String) -> Result<()>;
|
||||
async fn delete_event(&mut self, uid: &str) -> Result<()>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct JsonCalendarStore {
|
||||
calendars: HashMap<String, Calendar>,
|
||||
events: HashMap<String, Event>,
|
||||
path: String,
|
||||
}
|
||||
|
||||
impl JsonCalendarStore {
|
||||
pub fn new(path: String) -> Self {
|
||||
JsonCalendarStore {
|
||||
calendars: HashMap::new(),
|
||||
events: HashMap::new(),
|
||||
path,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn save(&self) -> Result<()> {
|
||||
let mut file = File::create(&self.path).await?;
|
||||
let json = serde_json::to_string_pretty(&self)?;
|
||||
file.write_all(json.as_bytes()).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl CalendarStore for JsonCalendarStore {
|
||||
async fn get_calendar(&self, id: &str) -> Result<Calendar> {
|
||||
Ok(self.calendars.get(id).ok_or(anyhow!("not found"))?.clone())
|
||||
}
|
||||
|
||||
async fn get_calendars(&self) -> Result<Vec<Calendar>> {
|
||||
Ok(vec![Calendar {
|
||||
id: "test".to_string(),
|
||||
name: Some("test".to_string()),
|
||||
ics: "asd".to_string(),
|
||||
}])
|
||||
}
|
||||
|
||||
async fn get_events(&self, _cid: &str) -> Result<Vec<Event>> {
|
||||
Ok(self.events.values().cloned().collect())
|
||||
}
|
||||
|
||||
async fn get_event(&self, uid: &str) -> Result<Event> {
|
||||
Ok(self.events.get(uid).ok_or(anyhow!("not found"))?.clone())
|
||||
}
|
||||
|
||||
async fn upsert_event(&mut self, uid: String, ics: String) -> Result<()> {
|
||||
self.events.insert(uid.clone(), Event { uid, ics });
|
||||
self.save().await.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete_event(&mut self, uid: &str) -> Result<()> {
|
||||
self.events.remove(uid);
|
||||
self.save().await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
2
crates/store/src/lib.rs
Normal file
2
crates/store/src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod calendar;
|
||||
pub mod users;
|
||||
39
crates/store/src/users.rs
Normal file
39
crates/store/src/users.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct User {
|
||||
pub id: String,
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
impl User {}
|
||||
|
||||
#[async_trait]
|
||||
pub trait UserStore: Send + Sync + 'static {
|
||||
async fn get_user(&self, id: &str) -> Result<User>;
|
||||
async fn get_users(&self) -> Result<Vec<User>>;
|
||||
}
|
||||
|
||||
pub struct TestUserStore {}
|
||||
|
||||
#[async_trait]
|
||||
impl UserStore for TestUserStore {
|
||||
async fn get_user(&self, id: &str) -> Result<User> {
|
||||
if id != "test" {
|
||||
return Err(anyhow!("asd"));
|
||||
}
|
||||
Ok(User {
|
||||
id: "test".to_string(),
|
||||
name: Some("test".to_string()),
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_users(&self) -> Result<Vec<User>> {
|
||||
Ok(vec![User {
|
||||
id: "test".to_string(),
|
||||
name: Some("test".to_string()),
|
||||
}])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user