Compare commits

...

8 Commits

Author SHA1 Message Date
Lennart
60b45e70ad fix docker builds 2026-01-15 22:31:40 +01:00
Lennart
a0c33c82dd version 0.11.14 2026-01-15 13:32:45 +01:00
Lennart
8ae5e46abf Automatic repair for calendar objects with invalid VERSION:4.0 2026-01-15 13:30:14 +01:00
Lennart
48b2e614a8 Suppress ical invalid version error 2026-01-15 11:15:20 +01:00
Lennart K
f26214abb9 build Docker images for dev branch 2026-01-12 11:15:08 +01:00
Lennart
276e65d41a version 0.11.11 2026-01-10 13:37:24 +01:00
Lennart
7c3e9ecbc1 update ical-rs dev to remove panics 2026-01-10 13:35:14 +01:00
Lennart
53f81a9433 Add a startup test to check whether existing data will be compatible with v0.12 2026-01-10 13:22:49 +01:00
12 changed files with 436 additions and 130 deletions

View File

@@ -2,7 +2,7 @@ name: Docker
on: on:
push: push:
branches: ["main"] branches: ["main", "dev"]
release: release:
types: ["published"] types: ["published"]

View File

@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "DELETE FROM calendarobjectchangelog WHERE (principal, cal_id, object_id) = (?, ?, ?);",
"describe": {
"columns": [],
"parameters": {
"Right": 3
},
"nullable": []
},
"hash": "146e23ae4e0eaae4d65ac7563c67d4f295ccc2534dcc4b3bd710de773ed137f9"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "UPDATE calendarobjects SET ics = ? WHERE (principal, cal_id, id) = (?, ?, ?);",
"describe": {
"columns": [],
"parameters": {
"Right": 4
},
"nullable": []
},
"hash": "354decac84758c88280f60fbf0f93dddc6c7ff92ac7b8ba44049d31df3c680e3"
}

View File

@@ -0,0 +1,38 @@
{
"db_name": "SQLite",
"query": "SELECT principal, cal_id, id, ics FROM calendarobjects WHERE ics LIKE '%VERSION:4.0%';",
"describe": {
"columns": [
{
"name": "principal",
"ordinal": 0,
"type_info": "Text"
},
{
"name": "cal_id",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "id",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "ics",
"ordinal": 3,
"type_info": "Text"
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false,
false,
false
]
},
"hash": "bdaa4bee8b01d0e3773e34672ed4805d1e71d24888f2227045afd90bf080fc23"
}

304
Cargo.lock generated
View File

@@ -154,7 +154,7 @@ dependencies = [
"rustc-hash", "rustc-hash",
"serde", "serde",
"serde_derive", "serde_derive",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -200,7 +200,7 @@ checksum = "9767c17d33a63daf6da5872ffaf2ab0c289cd73ce7ed4f41d5ddf9149c004873"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -335,7 +335,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -477,9 +477,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]] [[package]]
name = "base64ct" name = "base64ct"
version = "1.8.1" version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" checksum = "7d809780667f4410e7c41b07f52439b94d2bdf8528eeedc287fa38d3b7f95d82"
[[package]] [[package]]
name = "basic-toml" name = "basic-toml"
@@ -573,9 +573,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.51" version = "1.2.52"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"shlex", "shlex",
@@ -623,7 +623,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3" checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"
dependencies = [ dependencies = [
"chrono", "chrono",
"phf", "phf 0.12.1",
] ]
[[package]] [[package]]
@@ -655,9 +655,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.53" version = "4.5.54"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@@ -665,9 +665,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.53" version = "4.5.54"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@@ -684,7 +684,7 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -898,7 +898,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -932,7 +932,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim", "strsim",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -945,7 +945,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim", "strsim",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -956,7 +956,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
dependencies = [ dependencies = [
"darling_core 0.21.3", "darling_core 0.21.3",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -967,7 +967,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
dependencies = [ dependencies = [
"darling_core 0.23.0", "darling_core 0.23.0",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -1010,7 +1010,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"rustc_version", "rustc_version",
"syn 2.0.112", "syn 2.0.114",
"unicode-xid", "unicode-xid",
] ]
@@ -1034,7 +1034,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -1241,9 +1241,9 @@ dependencies = [
[[package]] [[package]]
name = "find-msvc-tools" name = "find-msvc-tools"
version = "0.1.6" version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41"
[[package]] [[package]]
name = "flume" name = "flume"
@@ -1371,7 +1371,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -1484,9 +1484,9 @@ dependencies = [
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.4.12" version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54"
dependencies = [ dependencies = [
"atomic-waker", "atomic-waker",
"bytes", "bytes",
@@ -1494,7 +1494,7 @@ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"http", "http",
"indexmap 2.12.1", "indexmap 2.13.0",
"slab", "slab",
"tokio", "tokio",
"tokio-util", "tokio-util",
@@ -1771,7 +1771,23 @@ dependencies = [
[[package]] [[package]]
name = "ical" name = "ical"
version = "0.11.0" version = "0.11.0"
source = "git+https://github.com/lennart-k/ical-rs#dcd3b106758a054f46a5172103abb17972ad032d" source = "git+https://github.com/lennart-k/ical-rs?branch=dev#b1edcdf2bb7db5a302a5df3650218a9a16aefe0c"
dependencies = [
"chrono",
"chrono-tz",
"derive_more",
"itertools 0.14.0",
"lazy_static",
"phf 0.13.1",
"regex",
"rrule",
"thiserror 2.0.17",
]
[[package]]
name = "ical"
version = "0.11.0"
source = "git+https://github.com/lennart-k/ical-rs?rev=7c2ab1f3#7c2ab1f3abdca768f22d8a36627eebbdd7947e29"
dependencies = [ dependencies = [
"chrono", "chrono",
"chrono-tz", "chrono-tz",
@@ -1904,9 +1920,9 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.12.1" version = "2.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown 0.16.1", "hashbrown 0.16.1",
@@ -1922,9 +1938,9 @@ checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
[[package]] [[package]]
name = "insta" name = "insta"
version = "1.45.1" version = "1.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "983e3b24350c84ab8a65151f537d67afbbf7153bb9f1110e03e9fa9b07f67a5c" checksum = "1b66886d14d18d420ab5052cbff544fc5d34d0b2cdd35eb5976aaa10a4a472e5"
dependencies = [ dependencies = [
"console", "console",
"once_cell", "once_cell",
@@ -2018,9 +2034,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.178" version = "0.2.180"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
[[package]] [[package]]
name = "libm" name = "libm"
@@ -2334,7 +2350,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -2569,7 +2585,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"proc-macro2-diagnostics", "proc-macro2-diagnostics",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -2593,7 +2609,18 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
dependencies = [ dependencies = [
"phf_shared", "phf_shared 0.12.1",
]
[[package]]
name = "phf"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
dependencies = [
"phf_macros",
"phf_shared 0.13.1",
"serde",
] ]
[[package]] [[package]]
@@ -2602,8 +2629,8 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efbdcb6f01d193b17f0b9c3360fa7e0e620991b193ff08702f78b3ce365d7e61" checksum = "efbdcb6f01d193b17f0b9c3360fa7e0e620991b193ff08702f78b3ce365d7e61"
dependencies = [ dependencies = [
"phf_generator", "phf_generator 0.12.1",
"phf_shared", "phf_shared 0.12.1",
] ]
[[package]] [[package]]
@@ -2613,7 +2640,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cbb1126afed61dd6368748dae63b1ee7dc480191c6262a3b4ff1e29d86a6c5b" checksum = "2cbb1126afed61dd6368748dae63b1ee7dc480191c6262a3b4ff1e29d86a6c5b"
dependencies = [ dependencies = [
"fastrand", "fastrand",
"phf_shared", "phf_shared 0.12.1",
]
[[package]]
name = "phf_generator"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
dependencies = [
"fastrand",
"phf_shared 0.13.1",
]
[[package]]
name = "phf_macros"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef"
dependencies = [
"phf_generator 0.13.1",
"phf_shared 0.13.1",
"proc-macro2",
"quote",
"syn 2.0.114",
] ]
[[package]] [[package]]
@@ -2625,6 +2675,15 @@ dependencies = [
"siphasher", "siphasher",
] ]
[[package]]
name = "phf_shared"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
dependencies = [
"siphasher",
]
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.1.10" version = "1.1.10"
@@ -2642,7 +2701,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -2781,9 +2840,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.104" version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@@ -2796,7 +2855,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
"version_check", "version_check",
"yansi", "yansi",
] ]
@@ -2821,7 +2880,7 @@ dependencies = [
"itertools 0.14.0", "itertools 0.14.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -2890,9 +2949,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.42" version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -3017,7 +3076,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -3148,9 +3207,9 @@ dependencies = [
[[package]] [[package]]
name = "rsa" name = "rsa"
version = "0.9.9" version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40a0376c50d0358279d9d643e4bf7b7be212f1f4ff1da9070a7b54d22ef75c88" checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d"
dependencies = [ dependencies = [
"const-oid", "const-oid",
"digest", "digest",
@@ -3191,7 +3250,7 @@ dependencies = [
"regex", "regex",
"relative-path", "relative-path",
"rustc_version", "rustc_version",
"syn 2.0.112", "syn 2.0.114",
"unicode-ident", "unicode-ident",
] ]
@@ -3203,7 +3262,7 @@ checksum = "b3a8fb4672e840a587a66fc577a5491375df51ddb88f2a2c2a792598c326fe14"
dependencies = [ dependencies = [
"quote", "quote",
"rand 0.8.5", "rand 0.8.5",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -3236,7 +3295,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"rust-embed-utils", "rust-embed-utils",
"syn 2.0.112", "syn 2.0.114",
"walkdir", "walkdir",
] ]
@@ -3273,7 +3332,7 @@ dependencies = [
[[package]] [[package]]
name = "rustical" name = "rustical"
version = "0.11.10" version = "0.11.15"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"argon2", "argon2",
@@ -3284,6 +3343,7 @@ dependencies = [
"figment", "figment",
"headers", "headers",
"http", "http",
"ical 0.11.0 (git+https://github.com/lennart-k/ical-rs?branch=dev)",
"insta", "insta",
"opentelemetry", "opentelemetry",
"opentelemetry-otlp", "opentelemetry-otlp",
@@ -3306,7 +3366,7 @@ dependencies = [
"serde", "serde",
"sqlx", "sqlx",
"tokio", "tokio",
"toml 0.9.10+spec-1.1.0", "toml 0.9.11+spec-1.1.0",
"tower", "tower",
"tower-http", "tower-http",
"tower-sessions", "tower-sessions",
@@ -3318,7 +3378,7 @@ dependencies = [
[[package]] [[package]]
name = "rustical_caldav" name = "rustical_caldav"
version = "0.11.10" version = "0.11.15"
dependencies = [ dependencies = [
"async-std", "async-std",
"async-trait", "async-trait",
@@ -3331,7 +3391,7 @@ dependencies = [
"futures-util", "futures-util",
"headers", "headers",
"http", "http",
"ical", "ical 0.11.0 (git+https://github.com/lennart-k/ical-rs?rev=7c2ab1f3)",
"insta", "insta",
"percent-encoding", "percent-encoding",
"quick-xml", "quick-xml",
@@ -3360,7 +3420,7 @@ dependencies = [
[[package]] [[package]]
name = "rustical_carddav" name = "rustical_carddav"
version = "0.11.10" version = "0.11.15"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum", "axum",
@@ -3370,7 +3430,7 @@ dependencies = [
"derive_more", "derive_more",
"futures-util", "futures-util",
"http", "http",
"ical", "ical 0.11.0 (git+https://github.com/lennart-k/ical-rs?rev=7c2ab1f3)",
"insta", "insta",
"percent-encoding", "percent-encoding",
"quick-xml", "quick-xml",
@@ -3394,7 +3454,7 @@ dependencies = [
[[package]] [[package]]
name = "rustical_dav" name = "rustical_dav"
version = "0.11.10" version = "0.11.15"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum", "axum",
@@ -3403,7 +3463,7 @@ dependencies = [
"futures-util", "futures-util",
"headers", "headers",
"http", "http",
"ical", "ical 0.11.0 (git+https://github.com/lennart-k/ical-rs?rev=7c2ab1f3)",
"itertools 0.14.0", "itertools 0.14.0",
"log", "log",
"matchit 0.9.1", "matchit 0.9.1",
@@ -3420,7 +3480,7 @@ dependencies = [
[[package]] [[package]]
name = "rustical_dav_push" name = "rustical_dav_push"
version = "0.11.10" version = "0.11.15"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum", "axum",
@@ -3445,7 +3505,7 @@ dependencies = [
[[package]] [[package]]
name = "rustical_frontend" name = "rustical_frontend"
version = "0.11.10" version = "0.11.15"
dependencies = [ dependencies = [
"askama", "askama",
"askama_web", "askama_web",
@@ -3481,13 +3541,13 @@ dependencies = [
[[package]] [[package]]
name = "rustical_ical" name = "rustical_ical"
version = "0.11.10" version = "0.11.15"
dependencies = [ dependencies = [
"axum", "axum",
"chrono", "chrono",
"chrono-tz", "chrono-tz",
"derive_more", "derive_more",
"ical", "ical 0.11.0 (git+https://github.com/lennart-k/ical-rs?rev=7c2ab1f3)",
"regex", "regex",
"rrule", "rrule",
"rstest", "rstest",
@@ -3500,7 +3560,7 @@ dependencies = [
[[package]] [[package]]
name = "rustical_oidc" name = "rustical_oidc"
version = "0.11.10" version = "0.11.15"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum", "axum",
@@ -3516,7 +3576,7 @@ dependencies = [
[[package]] [[package]]
name = "rustical_store" name = "rustical_store"
version = "0.11.10" version = "0.11.15"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@@ -3528,7 +3588,7 @@ dependencies = [
"futures-core", "futures-core",
"headers", "headers",
"http", "http",
"ical", "ical 0.11.0 (git+https://github.com/lennart-k/ical-rs?rev=7c2ab1f3)",
"regex", "regex",
"rrule", "rrule",
"rstest", "rstest",
@@ -3549,7 +3609,7 @@ dependencies = [
[[package]] [[package]]
name = "rustical_store_sqlite" name = "rustical_store_sqlite"
version = "0.11.10" version = "0.11.15"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"chrono", "chrono",
@@ -3558,6 +3618,7 @@ dependencies = [
"password-auth", "password-auth",
"password-hash", "password-hash",
"pbkdf2", "pbkdf2",
"regex",
"rstest", "rstest",
"rustical_ical", "rustical_ical",
"rustical_store", "rustical_store",
@@ -3572,7 +3633,7 @@ dependencies = [
[[package]] [[package]]
name = "rustical_xml" name = "rustical_xml"
version = "0.11.10" version = "0.11.15"
dependencies = [ dependencies = [
"quick-xml", "quick-xml",
"thiserror 2.0.17", "thiserror 2.0.17",
@@ -3594,9 +3655,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.23.35" version = "0.23.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"ring", "ring",
@@ -3735,14 +3796,14 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.148" version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr", "memchr",
@@ -3811,7 +3872,7 @@ dependencies = [
"chrono", "chrono",
"hex", "hex",
"indexmap 1.9.3", "indexmap 1.9.3",
"indexmap 2.12.1", "indexmap 2.13.0",
"schemars 0.9.0", "schemars 0.9.0",
"schemars 1.2.0", "schemars 1.2.0",
"serde_core", "serde_core",
@@ -3829,7 +3890,7 @@ dependencies = [
"darling 0.21.3", "darling 0.21.3",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -3991,7 +4052,7 @@ dependencies = [
"futures-util", "futures-util",
"hashbrown 0.15.5", "hashbrown 0.15.5",
"hashlink", "hashlink",
"indexmap 2.12.1", "indexmap 2.13.0",
"log", "log",
"memchr", "memchr",
"once_cell", "once_cell",
@@ -4018,7 +4079,7 @@ dependencies = [
"quote", "quote",
"sqlx-core", "sqlx-core",
"sqlx-macros-core", "sqlx-macros-core",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -4041,7 +4102,7 @@ dependencies = [
"sqlx-mysql", "sqlx-mysql",
"sqlx-postgres", "sqlx-postgres",
"sqlx-sqlite", "sqlx-sqlite",
"syn 2.0.112", "syn 2.0.114",
"tokio", "tokio",
"url", "url",
] ]
@@ -4193,7 +4254,7 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -4215,9 +4276,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.112" version = "2.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -4241,7 +4302,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -4283,7 +4344,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -4294,7 +4355,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -4374,9 +4435,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.48.0" version = "1.49.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86"
dependencies = [ dependencies = [
"bytes", "bytes",
"libc", "libc",
@@ -4398,7 +4459,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -4413,9 +4474,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-stream" name = "tokio-stream"
version = "0.1.17" version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"pin-project-lite", "pin-project-lite",
@@ -4424,9 +4485,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.17" version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",
@@ -4449,11 +4510,11 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.9.10+spec-1.1.0" version = "0.9.11+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48" checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46"
dependencies = [ dependencies = [
"indexmap 2.12.1", "indexmap 2.13.0",
"serde_core", "serde_core",
"serde_spanned 1.0.4", "serde_spanned 1.0.4",
"toml_datetime 0.7.5+spec-1.1.0", "toml_datetime 0.7.5+spec-1.1.0",
@@ -4486,7 +4547,7 @@ version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [ dependencies = [
"indexmap 2.12.1", "indexmap 2.13.0",
"serde", "serde",
"serde_spanned 0.6.9", "serde_spanned 0.6.9",
"toml_datetime 0.6.11", "toml_datetime 0.6.11",
@@ -4500,7 +4561,7 @@ version = "0.23.10+spec-1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269"
dependencies = [ dependencies = [
"indexmap 2.12.1", "indexmap 2.13.0",
"toml_datetime 0.7.5+spec-1.1.0", "toml_datetime 0.7.5+spec-1.1.0",
"toml_parser", "toml_parser",
"winnow", "winnow",
@@ -4572,7 +4633,7 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-util", "futures-util",
"indexmap 2.12.1", "indexmap 2.13.0",
"pin-project-lite", "pin-project-lite",
"slab", "slab",
"sync_wrapper", "sync_wrapper",
@@ -4710,7 +4771,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -4794,9 +4855,9 @@ dependencies = [
[[package]] [[package]]
name = "unicase" name = "unicase"
version = "2.8.1" version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
[[package]] [[package]]
name = "unicode-bidi" name = "unicode-bidi"
@@ -4845,14 +4906,15 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]] [[package]]
name = "url" name = "url"
version = "2.5.7" version = "2.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed"
dependencies = [ dependencies = [
"form_urlencoded", "form_urlencoded",
"idna", "idna",
"percent-encoding", "percent-encoding",
"serde", "serde",
"serde_derive",
] ]
[[package]] [[package]]
@@ -4910,7 +4972,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6728de8767c8dea44f41b88115a205ed23adc3302e1b4342be59d922934dae5" checksum = "f6728de8767c8dea44f41b88115a205ed23adc3302e1b4342be59d922934dae5"
dependencies = [ dependencies = [
"glob", "glob",
"phf", "phf 0.12.1",
"phf_codegen", "phf_codegen",
] ]
@@ -4999,7 +5061,7 @@ dependencies = [
"bumpalo", "bumpalo",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@@ -5034,9 +5096,9 @@ dependencies = [
[[package]] [[package]]
name = "webpki-roots" name = "webpki-roots"
version = "1.0.4" version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c"
dependencies = [ dependencies = [
"rustls-pki-types", "rustls-pki-types",
] ]
@@ -5103,7 +5165,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -5114,7 +5176,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -5395,14 +5457,14 @@ checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
[[package]] [[package]]
name = "xml_derive" name = "xml_derive"
version = "0.11.10" version = "0.11.15"
dependencies = [ dependencies = [
"darling 0.23.0", "darling 0.23.0",
"heck", "heck",
"itertools 0.14.0", "itertools 0.14.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -5430,28 +5492,28 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
"synstructure", "synstructure",
] ]
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.8.31" version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd"
dependencies = [ dependencies = [
"zerocopy-derive", "zerocopy-derive",
] ]
[[package]] [[package]]
name = "zerocopy-derive" name = "zerocopy-derive"
version = "0.8.31" version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
@@ -5471,7 +5533,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
"synstructure", "synstructure",
] ]
@@ -5511,11 +5573,11 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.112", "syn 2.0.114",
] ]
[[package]] [[package]]
name = "zmij" name = "zmij"
version = "1.0.5" version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3280a1b827474fcd5dbef4b35a674deb52ba5c312363aef9135317df179d81b" checksum = "2fc5a66a20078bf1251bde995aa2fdcc4b800c70b5d92dd2c62abc5c60f679f8"

View File

@@ -2,7 +2,7 @@
members = ["crates/*"] members = ["crates/*"]
[workspace.package] [workspace.package]
version = "0.11.10" version = "0.11.15"
rust-version = "1.92" rust-version = "1.92"
edition = "2024" edition = "2024"
description = "A CalDAV server" description = "A CalDAV server"
@@ -107,9 +107,7 @@ strum = "0.27"
strum_macros = "0.27" strum_macros = "0.27"
serde_json = { version = "1.0", features = ["raw_value"] } serde_json = { version = "1.0", features = ["raw_value"] }
sqlx-sqlite = { version = "0.8", features = ["bundled"] } sqlx-sqlite = { version = "0.8", features = ["bundled"] }
ical = { git = "https://github.com/lennart-k/ical-rs", features = [ ical = { git = "https://github.com/lennart-k/ical-rs", rev = "7c2ab1f3" }
"chrono-tz",
] }
toml = "0.9" toml = "0.9"
tower = "0.5" tower = "0.5"
tower-http = { version = "0.6", features = [ tower-http = { version = "0.6", features = [
@@ -201,3 +199,7 @@ tower-http.workspace = true
axum-extra.workspace = true axum-extra.workspace = true
headers.workspace = true headers.workspace = true
http.workspace = true http.workspace = true
# TODO: Remove in next major release
ical_dev = { package = "ical", git = "https://github.com/lennart-k/ical-rs", branch = "dev", features = [
"chrono-tz",
] }

View File

@@ -36,3 +36,4 @@ pbkdf2.workspace = true
rustical_ical.workspace = true rustical_ical.workspace = true
rstest = { workspace = true, optional = true } rstest = { workspace = true, optional = true }
sha2.workspace = true sha2.workspace = true
regex.workspace = true

View File

@@ -3,6 +3,7 @@ use crate::BEGIN_IMMEDIATE;
use async_trait::async_trait; use async_trait::async_trait;
use chrono::TimeDelta; use chrono::TimeDelta;
use derive_more::derive::Constructor; use derive_more::derive::Constructor;
use regex::Regex;
use rustical_ical::{CalDateTime, CalendarObject, CalendarObjectType}; use rustical_ical::{CalDateTime, CalendarObject, CalendarObjectType};
use rustical_store::calendar_store::CalendarQuery; use rustical_store::calendar_store::CalendarQuery;
use rustical_store::synctoken::format_synctoken; use rustical_store::synctoken::format_synctoken;
@@ -145,6 +146,83 @@ impl SqliteCalendarStore {
} }
} }
/// In the past exports generated objects with invalid VERSION:4.0
/// This repair sets them to VERSION:2.0
#[allow(clippy::missing_panics_doc)]
pub async fn repair_invalid_version_4_0(&self) -> Result<(), Error> {
struct Row {
principal: String,
cal_id: String,
id: String,
ics: String,
}
let mut tx = self
.db
.begin_with(BEGIN_IMMEDIATE)
.await
.map_err(crate::Error::from)?;
#[allow(clippy::missing_panics_doc)]
let version_pattern = Regex::new(r"(?mi)^VERSION:4.0").unwrap();
let repairs: Vec<Row> = sqlx::query_as!(
Row,
r#"SELECT principal, cal_id, id, ics FROM calendarobjects WHERE ics LIKE '%VERSION:4.0%';"#
)
.fetch_all(&mut *tx)
.await
.map_err(crate::Error::from)?
.into_iter()
.filter_map(|mut row| {
version_pattern.find(&row.ics)?;
let new_ics = version_pattern.replace(&row.ics, "VERSION:2.0");
// Safeguard that we really only changed the version
assert_eq!(row.ics.len(), new_ics.len());
row.ics = new_ics.to_string();
Some(row)
})
.collect();
if repairs.is_empty() {
return Ok(());
}
warn!(
"Found {} calendar objects with invalid VERSION:4.0. Repairing by setting to VERSION:2.0",
repairs.len()
);
for repair in &repairs {
// calendarobjectchangelog is used by sync-collection to fetch changes
// By deleting entries we will later regenerate new entries such that clients will notice
// the objects have changed
warn!(
"Repairing VERSION for {}/{}/{}.ics",
repair.principal, repair.cal_id, repair.id
);
sqlx::query!(
"DELETE FROM calendarobjectchangelog WHERE (principal, cal_id, object_id) = (?, ?, ?);",
repair.principal, repair.cal_id, repair.id
).execute(&mut *tx).await
.map_err(crate::Error::from)?;
sqlx::query!(
"UPDATE calendarobjects SET ics = ? WHERE (principal, cal_id, id) = (?, ?, ?);",
repair.ics,
repair.principal,
repair.cal_id,
repair.id
)
.execute(&mut *tx)
.await
.map_err(crate::Error::from)?;
}
tx.commit().await.map_err(crate::Error::from)?;
Ok(())
}
// Commit "orphaned" objects to the changelog table // Commit "orphaned" objects to the changelog table
pub async fn repair_orphans(&self) -> Result<(), Error> { pub async fn repair_orphans(&self) -> Result<(), Error> {
struct Row { struct Row {

View File

@@ -17,6 +17,7 @@ pub fn cmd_gen_config(_args: GenConfigArgs) -> anyhow::Result<()> {
http: HttpConfig::default(), http: HttpConfig::default(),
data_store: DataStoreConfig::Sqlite(SqliteDataStoreConfig { data_store: DataStoreConfig::Sqlite(SqliteDataStoreConfig {
db_url: "/var/lib/rustical/db.sqlite3".to_owned(), db_url: "/var/lib/rustical/db.sqlite3".to_owned(),
run_repairs: true,
}), }),
tracing: TracingConfig::default(), tracing: TracingConfig::default(),
frontend: FrontendConfig { frontend: FrontendConfig {

View File

@@ -26,6 +26,8 @@ impl Default for HttpConfig {
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct SqliteDataStoreConfig { pub struct SqliteDataStoreConfig {
pub db_url: String, pub db_url: String,
#[serde(default = "default_true")]
pub run_repairs: bool,
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]

View File

@@ -25,7 +25,7 @@ use std::sync::Arc;
use tokio::sync::mpsc::Receiver; use tokio::sync::mpsc::Receiver;
use tower::Layer; use tower::Layer;
use tower_http::normalize_path::NormalizePathLayer; use tower_http::normalize_path::NormalizePathLayer;
use tracing::info; use tracing::{info, warn};
mod app; mod app;
mod commands; mod commands;
@@ -34,6 +34,9 @@ mod config;
pub mod integration_tests; pub mod integration_tests;
mod setup_tracing; mod setup_tracing;
mod migration_0_12;
use migration_0_12::{validate_address_objects_0_12, validate_calendar_objects_0_12};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
struct Args { struct Args {
@@ -67,15 +70,22 @@ async fn get_data_stores(
Receiver<CollectionOperation>, Receiver<CollectionOperation>,
)> { )> {
Ok(match &config { Ok(match &config {
DataStoreConfig::Sqlite(SqliteDataStoreConfig { db_url }) => { DataStoreConfig::Sqlite(SqliteDataStoreConfig {
db_url,
run_repairs,
}) => {
let db = create_db_pool(db_url, migrate).await?; let db = create_db_pool(db_url, migrate).await?;
// Channel to watch for changes (for DAV Push) // Channel to watch for changes (for DAV Push)
let (send, recv) = tokio::sync::mpsc::channel(1000); let (send, recv) = tokio::sync::mpsc::channel(1000);
let addressbook_store = Arc::new(SqliteAddressbookStore::new(db.clone(), send.clone())); let addressbook_store = Arc::new(SqliteAddressbookStore::new(db.clone(), send.clone()));
addressbook_store.repair_orphans().await?;
let cal_store = Arc::new(SqliteCalendarStore::new(db.clone(), send)); let cal_store = Arc::new(SqliteCalendarStore::new(db.clone(), send));
cal_store.repair_orphans().await?; if *run_repairs {
info!("Running repair tasks");
addressbook_store.repair_orphans().await?;
cal_store.repair_invalid_version_4_0().await?;
cal_store.repair_orphans().await?;
}
let subscription_store = Arc::new(SqliteStore::new(db.clone())); let subscription_store = Arc::new(SqliteStore::new(db.clone()));
let principal_store = Arc::new(SqlitePrincipalStore::new(db)); let principal_store = Arc::new(SqlitePrincipalStore::new(db));
( (
@@ -115,6 +125,14 @@ async fn main() -> Result<()> {
let (addr_store, cal_store, subscription_store, principal_store, update_recv) = let (addr_store, cal_store, subscription_store, principal_store, update_recv) =
get_data_stores(!args.no_migrations, &config.data_store).await?; get_data_stores(!args.no_migrations, &config.data_store).await?;
warn!(
"Validating calendar data against the next-version ical parser.
In the next major release these will be rejected and cause errors.
If any errors occur, please open an issue so they can be fixed before the next major release."
);
validate_calendar_objects_0_12(principal_store.as_ref(), cal_store.as_ref()).await?;
validate_address_objects_0_12(principal_store.as_ref(), addr_store.as_ref()).await?;
let mut tasks = vec![]; let mut tasks = vec![];
if config.dav_push.enabled { if config.dav_push.enabled {

80
src/migration_0_12.rs Normal file
View File

@@ -0,0 +1,80 @@
use rustical_store::{AddressbookStore, CalendarStore, auth::AuthenticationProvider};
use tracing::{error, info};
pub async fn validate_calendar_objects_0_12(
principal_store: &impl AuthenticationProvider,
cal_store: &impl CalendarStore,
) -> Result<(), rustical_store::Error> {
let mut success = true;
for principal in principal_store.get_principals().await? {
for calendar in cal_store.get_calendars(&principal.id).await? {
for object in cal_store
.get_objects(&calendar.principal, &calendar.id)
.await?
{
if let Err(err) =
ical_dev::parser::ical::IcalObjectParser::new(object.get_ics().as_bytes())
.expect_one()
{
success = false;
error!(
"An error occured parsing a calendar object: principal={principal}, calendar={calendar}, object_id={object_id}: {err}",
principal = principal.id,
calendar = calendar.id,
object_id = object.get_id()
);
println!("{}", object.get_ics());
}
}
}
}
if success {
info!("Your calendar data seems to be valid in the next major version.");
} else {
error!(
"Not all calendar objects will be successfully parsed in the next major version (v0.12).
This will not cause issues in this version, but please comment under the tracking issue on GitHub:
https://github.com/lennart-k/rustical/issues/165"
);
}
Ok(())
}
pub async fn validate_address_objects_0_12(
principal_store: &impl AuthenticationProvider,
addr_store: &impl AddressbookStore,
) -> Result<(), rustical_store::Error> {
let mut success = true;
for principal in principal_store.get_principals().await? {
for addressbook in addr_store.get_addressbooks(&principal.id).await? {
for object in addr_store
.get_objects(&addressbook.principal, &addressbook.id)
.await?
{
if let Err(err) =
ical_dev::parser::vcard::VcardParser::new(object.get_vcf().as_bytes())
.expect_one()
{
success = false;
error!(
"An error occured parsing an address object: principal={principal}, addressbook={addressbook}, object_id={object_id}: {err}",
principal = principal.id,
addressbook = addressbook.id,
object_id = object.get_id()
);
println!("{}", object.get_vcf());
}
}
}
}
if success {
info!("Your addressbook data seems to be valid in the next major version.");
} else {
error!(
"Not all address objects will be successfully parsed in the next major version (v0.12).
This will not cause issues in this version, but please comment under the tracking issue on GitHub:
https://github.com/lennart-k/rustical/issues/165"
);
}
Ok(())
}