calendar_store: Fix deleted objects being returned

This commit is contained in:
Lennart
2025-06-15 16:31:07 +02:00
parent 677e0082fa
commit 0415664ff3
11 changed files with 90 additions and 16 deletions

View File

@@ -1,6 +1,6 @@
{ {
"db_name": "SQLite", "db_name": "SQLite",
"query": "SELECT id, vcf FROM addressobjects WHERE (principal, addressbook_id, id) = (?, ?, ?) AND ((deleted_at IS NULL) or ?)", "query": "SELECT id, vcf FROM addressobjects WHERE (principal, addressbook_id, id) = (?, ?, ?) AND ((deleted_at IS NULL) OR ?)",
"describe": { "describe": {
"columns": [ "columns": [
{ {
@@ -22,5 +22,5 @@
false false
] ]
}, },
"hash": "395e40a7b3333b79bc2ad50a123d99f74bc2712a16257ee2119dd211fdb61f7e" "hash": "246ec675667992c1297c29348d46496a884c59adb8b64b569d36f4ce10f88f47"
} }

View File

@@ -1,6 +1,6 @@
{ {
"db_name": "SQLite", "db_name": "SQLite",
"query": "SELECT id, ics FROM calendarobjects WHERE (principal, cal_id, id) = (?, ?, ?)", "query": "SELECT id, ics FROM calendarobjects WHERE (principal, cal_id, id) = (?, ?, ?) AND ((deleted_at IS NULL) OR ?)",
"describe": { "describe": {
"columns": [ "columns": [
{ {
@@ -15,12 +15,12 @@
} }
], ],
"parameters": { "parameters": {
"Right": 3 "Right": 4
}, },
"nullable": [ "nullable": [
false, false,
false false
] ]
}, },
"hash": "d2f7423e2e8f97607f6664200990dcadb927445880ec6edffba3b5aedf4e199b" "hash": "543838c030550cb09d1af08adfeade8b7ce3575d92fddbc6e9582d141bc9e49d"
} }

68
Cargo.lock generated
View File

@@ -768,7 +768,11 @@ dependencies = [
"base64 0.21.7", "base64 0.21.7",
"byteorder", "byteorder",
"hex", "hex",
"hkdf",
"lazy_static",
"once_cell", "once_cell",
"openssl",
"sha2",
"thiserror 1.0.69", "thiserror 1.0.69",
] ]
@@ -916,6 +920,21 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]] [[package]]
name = "form_urlencoded" name = "form_urlencoded"
version = "1.2.1" version = "1.2.1"
@@ -1834,6 +1853,54 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "openssl"
version = "0.10.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "openssl-src"
version = "300.5.0+3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8ce546f549326b0e6052b649198487d91320875da901e7bd11a06d1ee3f9c2f"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571"
dependencies = [
"cc",
"libc",
"openssl-src",
"pkg-config",
"vcpkg",
]
[[package]] [[package]]
name = "opentelemetry" name = "opentelemetry"
version = "0.30.0" version = "0.30.0"
@@ -2815,6 +2882,7 @@ dependencies = [
"http", "http",
"itertools 0.14.0", "itertools 0.14.0",
"log", "log",
"openssl",
"p256", "p256",
"quick-xml", "quick-xml",
"rand 0.9.1", "rand 0.9.1",

View File

@@ -29,7 +29,7 @@ pub async fn get_objects_calendar_multiget<C: CalendarStore>(
if let Some(filename) = href.strip_prefix(path) { if let Some(filename) = href.strip_prefix(path) {
let filename = filename.trim_start_matches("/"); let filename = filename.trim_start_matches("/");
if let Some(object_id) = filename.strip_suffix(".ics") { if let Some(object_id) = filename.strip_suffix(".ics") {
match store.get_object(principal, cal_id, object_id).await { match store.get_object(principal, cal_id, object_id, false).await {
Ok(object) => result.push(object), Ok(object) => result.push(object),
Err(rustical_store::Error::NotFound) => not_found.push(href.to_owned()), Err(rustical_store::Error::NotFound) => not_found.push(href.to_owned()),
Err(err) => return Err(err.into()), Err(err) => return Err(err.into()),

View File

@@ -33,7 +33,7 @@ pub async fn get_event<C: CalendarStore>(
} }
let event = cal_store let event = cal_store
.get_object(&principal, &calendar_id, &object_id) .get_object(&principal, &calendar_id, &object_id, false)
.await?; .await?;
let mut resp = Response::builder().status(StatusCode::OK); let mut resp = Response::builder().status(StatusCode::OK);

View File

@@ -61,7 +61,7 @@ impl<C: CalendarStore> ResourceService for CalendarObjectResourceService<C> {
) -> Result<Self::Resource, Self::Error> { ) -> Result<Self::Resource, Self::Error> {
let object = self let object = self
.cal_store .cal_store
.get_object(principal, calendar_id, object_id) .get_object(principal, calendar_id, object_id, false)
.await?; .await?;
Ok(CalendarObjectResource { Ok(CalendarObjectResource {
object, object,

View File

@@ -58,6 +58,7 @@ pub trait CalendarStore: Send + Sync + 'static {
principal: &str, principal: &str,
cal_id: &str, cal_id: &str,
object_id: &str, object_id: &str,
show_deleted: bool,
) -> Result<CalendarObject, Error>; ) -> Result<CalendarObject, Error>;
async fn put_object( async fn put_object(
&self, &self,

View File

@@ -96,14 +96,15 @@ impl<CS: CalendarStore, BS: CalendarStore> CalendarStore for CombinedCalendarSto
principal: &str, principal: &str,
cal_id: &str, cal_id: &str,
object_id: &str, object_id: &str,
show_deleted: bool,
) -> Result<CalendarObject, Error> { ) -> Result<CalendarObject, Error> {
if cal_id.starts_with(BIRTHDAYS_PREFIX) { if cal_id.starts_with(BIRTHDAYS_PREFIX) {
self.birthday_store self.birthday_store
.get_object(principal, cal_id, object_id) .get_object(principal, cal_id, object_id, show_deleted)
.await .await
} else { } else {
self.cal_store self.cal_store
.get_object(principal, cal_id, object_id) .get_object(principal, cal_id, object_id, show_deleted)
.await .await
} }
} }

View File

@@ -126,13 +126,14 @@ impl<AS: AddressbookStore> CalendarStore for ContactBirthdayStore<AS> {
principal: &str, principal: &str,
cal_id: &str, cal_id: &str,
object_id: &str, object_id: &str,
show_deleted: bool,
) -> Result<CalendarObject, Error> { ) -> Result<CalendarObject, Error> {
let cal_id = cal_id let cal_id = cal_id
.strip_prefix(BIRTHDAYS_PREFIX) .strip_prefix(BIRTHDAYS_PREFIX)
.ok_or(Error::NotFound)?; .ok_or(Error::NotFound)?;
let (addressobject_id, date_type) = object_id.rsplit_once("-").ok_or(Error::NotFound)?; let (addressobject_id, date_type) = object_id.rsplit_once("-").ok_or(Error::NotFound)?;
self.0 self.0
.get_object(principal, cal_id, addressobject_id, false) .get_object(principal, cal_id, addressobject_id, show_deleted)
.await? .await?
.get_significant_dates()? .get_significant_dates()?
.remove(date_type) .remove(date_type)

View File

@@ -250,7 +250,7 @@ impl SqliteAddressbookStore {
) -> Result<AddressObject, rustical_store::Error> { ) -> Result<AddressObject, rustical_store::Error> {
Ok(sqlx::query_as!( Ok(sqlx::query_as!(
AddressObjectRow, AddressObjectRow,
"SELECT id, vcf FROM addressobjects WHERE (principal, addressbook_id, id) = (?, ?, ?) AND ((deleted_at IS NULL) or ?)", "SELECT id, vcf FROM addressobjects WHERE (principal, addressbook_id, id) = (?, ?, ?) AND ((deleted_at IS NULL) OR ?)",
principal, principal,
addressbook_id, addressbook_id,
object_id, object_id,

View File

@@ -296,13 +296,15 @@ impl SqliteCalendarStore {
principal: &str, principal: &str,
cal_id: &str, cal_id: &str,
object_id: &str, object_id: &str,
show_deleted: bool,
) -> Result<CalendarObject, Error> { ) -> Result<CalendarObject, Error> {
sqlx::query_as!( sqlx::query_as!(
CalendarObjectRow, CalendarObjectRow,
"SELECT id, ics FROM calendarobjects WHERE (principal, cal_id, id) = (?, ?, ?)", "SELECT id, ics FROM calendarobjects WHERE (principal, cal_id, id) = (?, ?, ?) AND ((deleted_at IS NULL) OR ?)",
principal, principal,
cal_id, cal_id,
object_id object_id,
show_deleted
) )
.fetch_one(executor) .fetch_one(executor)
.await .await
@@ -454,7 +456,7 @@ impl SqliteCalendarStore {
.unwrap_or(0); .unwrap_or(0);
for Row { object_id, .. } in changes { for Row { object_id, .. } in changes {
match Self::_get_object(&mut *conn, principal, cal_id, &object_id).await { match Self::_get_object(&mut *conn, principal, cal_id, &object_id, false).await {
Ok(object) => objects.push(object), Ok(object) => objects.push(object),
Err(rustical_store::Error::NotFound) => deleted_objects.push(object_id), Err(rustical_store::Error::NotFound) => deleted_objects.push(object_id),
Err(err) => return Err(err), Err(err) => return Err(err),
@@ -557,8 +559,9 @@ impl CalendarStore for SqliteCalendarStore {
principal: &str, principal: &str,
cal_id: &str, cal_id: &str,
object_id: &str, object_id: &str,
show_deleted: bool,
) -> Result<CalendarObject, Error> { ) -> Result<CalendarObject, Error> {
Self::_get_object(&self.db, principal, cal_id, object_id).await Self::_get_object(&self.db, principal, cal_id, object_id, show_deleted).await
} }
#[instrument] #[instrument]