diff --git a/.sqlx/query-6d08d3a014743da9b445ab012437ec11f81fd86d3b02fc1df07a036c6b47ace2.json b/.sqlx/query-6d08d3a014743da9b445ab012437ec11f81fd86d3b02fc1df07a036c6b47ace2.json new file mode 100644 index 0000000..b46345f --- /dev/null +++ b/.sqlx/query-6d08d3a014743da9b445ab012437ec11f81fd86d3b02fc1df07a036c6b47ace2.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "INSERT OR REPLACE INTO davpush_subscriptions (id, topic, expiration, push_resource, public_key, public_key_type, auth_secret) VALUES (?, ?, ?, ?, ?, ?, ?)", + "describe": { + "columns": [], + "parameters": { + "Right": 7 + }, + "nullable": [] + }, + "hash": "6d08d3a014743da9b445ab012437ec11f81fd86d3b02fc1df07a036c6b47ace2" +} diff --git a/.sqlx/query-809600b79c012e77c5efabe5d355a8b188f23826a723030807dedc96fd24fdcc.json b/.sqlx/query-809600b79c012e77c5efabe5d355a8b188f23826a723030807dedc96fd24fdcc.json new file mode 100644 index 0000000..c1571c9 --- /dev/null +++ b/.sqlx/query-809600b79c012e77c5efabe5d355a8b188f23826a723030807dedc96fd24fdcc.json @@ -0,0 +1,56 @@ +{ + "db_name": "SQLite", + "query": "SELECT id, topic, expiration, push_resource, public_key, public_key_type, auth_secret\n FROM davpush_subscriptions\n WHERE (topic) = (?)", + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "topic", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "expiration", + "ordinal": 2, + "type_info": "Datetime" + }, + { + "name": "push_resource", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "public_key", + "ordinal": 4, + "type_info": "Text" + }, + { + "name": "public_key_type", + "ordinal": 5, + "type_info": "Text" + }, + { + "name": "auth_secret", + "ordinal": 6, + "type_info": "Text" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false + ] + }, + "hash": "809600b79c012e77c5efabe5d355a8b188f23826a723030807dedc96fd24fdcc" +} diff --git a/.sqlx/query-8159ceb84de9016e738e5fdc9a5203a4c4cbc583483241e3cdee542232c1bc35.json b/.sqlx/query-8159ceb84de9016e738e5fdc9a5203a4c4cbc583483241e3cdee542232c1bc35.json deleted file mode 100644 index 75aab9f..0000000 --- a/.sqlx/query-8159ceb84de9016e738e5fdc9a5203a4c4cbc583483241e3cdee542232c1bc35.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT id, topic, expiration, push_resource\n FROM davpush_subscriptions\n WHERE (id) = (?)", - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "topic", - "ordinal": 1, - "type_info": "Text" - }, - { - "name": "expiration", - "ordinal": 2, - "type_info": "Datetime" - }, - { - "name": "push_resource", - "ordinal": 3, - "type_info": "Text" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false, - false, - false, - false - ] - }, - "hash": "8159ceb84de9016e738e5fdc9a5203a4c4cbc583483241e3cdee542232c1bc35" -} diff --git a/.sqlx/query-84772106cd7461119dfaf0e60908f6523860b35c06010bb0a85a531ceeeadede.json b/.sqlx/query-84772106cd7461119dfaf0e60908f6523860b35c06010bb0a85a531ceeeadede.json deleted file mode 100644 index d9f4677..0000000 --- a/.sqlx/query-84772106cd7461119dfaf0e60908f6523860b35c06010bb0a85a531ceeeadede.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "INSERT OR REPLACE INTO davpush_subscriptions (id, topic, expiration, push_resource) VALUES (?, ?, ?, ?)", - "describe": { - "columns": [], - "parameters": { - "Right": 4 - }, - "nullable": [] - }, - "hash": "84772106cd7461119dfaf0e60908f6523860b35c06010bb0a85a531ceeeadede" -} diff --git a/.sqlx/query-851fdb63dfffde80b8793c08fa6c81ecae1d70b33dd63c8bd5b296eae330b522.json b/.sqlx/query-851fdb63dfffde80b8793c08fa6c81ecae1d70b33dd63c8bd5b296eae330b522.json deleted file mode 100644 index fc82668..0000000 --- a/.sqlx/query-851fdb63dfffde80b8793c08fa6c81ecae1d70b33dd63c8bd5b296eae330b522.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT id, topic, expiration, push_resource\n FROM davpush_subscriptions\n WHERE (topic) = (?)", - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "topic", - "ordinal": 1, - "type_info": "Text" - }, - { - "name": "expiration", - "ordinal": 2, - "type_info": "Datetime" - }, - { - "name": "push_resource", - "ordinal": 3, - "type_info": "Text" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false, - false, - false, - false - ] - }, - "hash": "851fdb63dfffde80b8793c08fa6c81ecae1d70b33dd63c8bd5b296eae330b522" -} diff --git a/.sqlx/query-ef6cf801df2237b82b55754f1b0a5da51089810fe7a0feb0d68ea801b4e2721c.json b/.sqlx/query-ef6cf801df2237b82b55754f1b0a5da51089810fe7a0feb0d68ea801b4e2721c.json new file mode 100644 index 0000000..0f8cd5d --- /dev/null +++ b/.sqlx/query-ef6cf801df2237b82b55754f1b0a5da51089810fe7a0feb0d68ea801b4e2721c.json @@ -0,0 +1,56 @@ +{ + "db_name": "SQLite", + "query": "SELECT id, topic, expiration, push_resource, public_key, public_key_type, auth_secret\n FROM davpush_subscriptions\n WHERE (id) = (?)", + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "topic", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "expiration", + "ordinal": 2, + "type_info": "Datetime" + }, + { + "name": "push_resource", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "public_key", + "ordinal": 4, + "type_info": "Text" + }, + { + "name": "public_key_type", + "ordinal": 5, + "type_info": "Text" + }, + { + "name": "auth_secret", + "ordinal": 6, + "type_info": "Text" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false + ] + }, + "hash": "ef6cf801df2237b82b55754f1b0a5da51089810fe7a0feb0d68ea801b4e2721c" +} diff --git a/Cargo.lock b/Cargo.lock index 1642435..9b14cfd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -199,7 +199,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -383,6 +383,18 @@ dependencies = [ "password-hash", ] +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "askama" version = "0.13.1" @@ -410,7 +422,7 @@ dependencies = [ "rustc-hash", "serde", "serde_derive", - "syn", + "syn 2.0.100", ] [[package]] @@ -444,7 +456,7 @@ checksum = "34921de3d57974069bad483fdfe0ec65d88c4ff892edd1ab4d8b03be0dda1b9b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -455,7 +467,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -509,6 +521,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.20.0" @@ -542,6 +560,12 @@ dependencies = [ "serde", ] +[[package]] +name = "binstring" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a3c2603413428303761fae99d4b6d936404208221a44eba47d7c1e6dd03a3" + [[package]] name = "bitflags" version = "2.9.0" @@ -560,6 +584,17 @@ dependencies = [ "digest", ] +[[package]] +name = "blake2b_simd" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e903a20b159e944f91ec8499fe1e55651480c541ea0a584f5d967c49ad9d99" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -732,7 +767,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -741,6 +776,17 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +[[package]] +name = "coarsetime" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91849686042de1b41cd81490edc83afbcb0abe5a9b6f2c4114f23ce8cca1bcf4" +dependencies = [ + "libc", + "wasix", + "wasm-bindgen", +] + [[package]] name = "colorchoice" version = "1.0.3" @@ -756,12 +802,24 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "const-oid" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" + [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + [[package]] name = "cookie" version = "0.16.2" @@ -857,6 +915,12 @@ dependencies = [ "typenum", ] +[[package]] +name = "ct-codecs" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e994091bae428316ad612b1d563e7bd917141ba942963f65251bb07c0f31cc55" + [[package]] name = "ctr" version = "0.9.2" @@ -890,7 +954,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -914,7 +978,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.100", ] [[package]] @@ -925,7 +989,17 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.100", +] + +[[package]] +name = "der" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" +dependencies = [ + "const-oid 0.6.2", + "der_derive", ] [[package]] @@ -934,11 +1008,23 @@ version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "const-oid", + "const-oid 0.9.6", "pem-rfc7468", "zeroize", ] +[[package]] +name = "der_derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8aed3b3c608dc56cf36c45fe979d04eda51242e6703d8d0bb03426ef7c41db6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure 0.12.6", +] + [[package]] name = "deranged" version = "0.4.0" @@ -975,7 +1061,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", "unicode-xid", ] @@ -987,7 +1073,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", "unicode-xid", ] @@ -998,7 +1084,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", - "const-oid", + "const-oid 0.9.6", "crypto-common", "subtle", ] @@ -1011,7 +1097,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -1032,7 +1118,7 @@ version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der", + "der 0.7.10", "digest", "elliptic-curve", "rfc6979", @@ -1040,6 +1126,24 @@ dependencies = [ "spki", ] +[[package]] +name = "ece" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ea1d2f2cc974957a4e2575d8e5bb494549bab66338d6320c2789abcfff5746" +dependencies = [ + "base64 0.21.7", + "byteorder", + "hex", + "hkdf", + "lazy_static", + "once_cell", + "openssl", + "serde", + "sha2", + "thiserror 1.0.69", +] + [[package]] name = "ed25519" version = "2.2.3" @@ -1050,6 +1154,16 @@ dependencies = [ "signature", ] +[[package]] +name = "ed25519-compact" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9b3460f44bea8cd47f45a0c70892f1eff856d97cd55358b2f73f663789f6190" +dependencies = [ + "ct-codecs", + "getrandom 0.2.15", +] + [[package]] name = "ed25519-dalek" version = "2.1.1" @@ -1210,6 +1324,21 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "form_urlencoded" version = "1.2.1" @@ -1271,7 +1400,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -1477,6 +1606,30 @@ dependencies = [ "digest", ] +[[package]] +name = "hmac-sha1-compact" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18492c9f6f9a560e0d346369b665ad2bdbc89fa9bceca75796584e79042694c3" + +[[package]] +name = "hmac-sha256" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a8575493d277c9092b988c780c94737fb9fd8651a1001e16bee3eccfc1baedb" +dependencies = [ + "digest", +] + +[[package]] +name = "hmac-sha512" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b3a0f572aa8389d325f5852b9e0a333a15b0f86ecccbb3fdb6e97cd86dc67c" +dependencies = [ + "digest", +] + [[package]] name = "home" version = "0.5.11" @@ -1763,7 +1916,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -1892,6 +2045,46 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jwt-simple" +version = "0.12.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "731011e9647a71ff4f8474176ff6ce6e0d2de87a0173f15613af3a84c3e3401a" +dependencies = [ + "anyhow", + "binstring", + "blake2b_simd", + "coarsetime", + "ct-codecs", + "ed25519-compact", + "hmac-sha1-compact", + "hmac-sha256", + "hmac-sha512", + "k256", + "p256", + "p384", + "rand 0.8.5", + "serde", + "serde_json", + "superboring", + "thiserror 2.0.12", + "zeroize", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + [[package]] name = "language-tags" version = "0.3.2" @@ -2178,6 +2371,44 @@ dependencies = [ "url", ] +[[package]] +name = "openssl" +version = "0.10.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +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 2.0.100", +] + +[[package]] +name = "openssl-sys" +version = "0.9.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "opentelemetry" version = "0.29.1" @@ -2397,7 +2628,28 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn", + "syn 2.0.100", +] + +[[package]] +name = "pem" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" +dependencies = [ + "base64 0.13.1", + "once_cell", + "regex", +] + +[[package]] +name = "pem" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +dependencies = [ + "base64 0.22.1", + "serde", ] [[package]] @@ -2470,7 +2722,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -2491,7 +2743,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ - "der", + "der 0.7.10", "pkcs8", "spki", ] @@ -2502,7 +2754,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der", + "der 0.7.10", "spki", ] @@ -2574,7 +2826,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", "version_check", "yansi", ] @@ -2599,7 +2851,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -2891,7 +3143,7 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" dependencies = [ - "const-oid", + "const-oid 0.9.6", "digest", "num-bigint-dig", "num-integer", @@ -2899,6 +3151,7 @@ dependencies = [ "pkcs1", "pkcs8", "rand_core 0.6.4", + "sha2", "signature", "spki", "subtle", @@ -2931,7 +3184,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn", + "syn 2.0.100", "unicode-ident", ] @@ -2943,7 +3196,7 @@ checksum = "b3a8fb4672e840a587a66fc577a5491375df51ddb88f2a2c2a792598c326fe14" dependencies = [ "quote", "rand 0.8.5", - "syn", + "syn 2.0.100", ] [[package]] @@ -2976,7 +3229,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn", + "syn 2.0.100", "walkdir", ] @@ -3141,6 +3394,7 @@ dependencies = [ "tokio", "tracing", "tracing-actix-web", + "web-push", ] [[package]] @@ -3333,13 +3587,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", - "der", + "der 0.7.10", "generic-array", "pkcs8", "subtle", "zeroize", ] +[[package]] +name = "sec1_decode" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6326ddc956378a0739200b2c30892dccaf198992dfd7323274690b9e188af23" +dependencies = [ + "der 0.4.5", + "pem 0.8.3", + "thiserror 1.0.69", +] + [[package]] name = "semver" version = "1.0.26" @@ -3373,7 +3638,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -3455,7 +3720,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -3564,7 +3829,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der", + "der 0.7.10", ] [[package]] @@ -3626,7 +3891,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn", + "syn 2.0.100", ] [[package]] @@ -3649,7 +3914,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn", + "syn 2.0.100", "tempfile", "tokio", "url", @@ -3803,7 +4068,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn", + "syn 2.0.100", ] [[package]] @@ -3812,6 +4077,30 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "superboring" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "515cce34a781d7250b8a65706e0f2a5b99236ea605cb235d4baed6685820478f" +dependencies = [ + "getrandom 0.2.15", + "hmac-sha256", + "hmac-sha512", + "rand 0.8.5", + "rsa", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.100" @@ -3832,6 +4121,18 @@ dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + [[package]] name = "synstructure" version = "0.13.1" @@ -3840,7 +4141,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -3882,7 +4183,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -3893,7 +4194,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -3989,7 +4290,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -4166,7 +4467,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -4400,6 +4701,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" +[[package]] +name = "wasix" +version = "0.12.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fbb4ef9bbca0c1170e0b00dd28abc9e3b68669821600cad1caaed606583c6d" +dependencies = [ + "wasi 0.11.0+wasi-snapshot-preview1", +] + [[package]] name = "wasm-bindgen" version = "0.2.100" @@ -4422,7 +4732,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 2.0.100", "wasm-bindgen-shared", ] @@ -4457,7 +4767,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4471,6 +4781,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "web-push" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5c305b9ee2993ab68b7744b13ef32231d83600dd879ac8183b4c76ae31d28ac" +dependencies = [ + "async-trait", + "chrono", + "ct-codecs", + "ece", + "http 0.2.12", + "jwt-simple", + "log", + "pem 3.0.5", + "sec1_decode", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "web-sys" version = "0.3.77" @@ -4562,7 +4892,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -4573,7 +4903,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -4870,7 +5200,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -4899,8 +5229,8 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn", - "synstructure", + "syn 2.0.100", + "synstructure 0.13.1", ] [[package]] @@ -4920,7 +5250,7 @@ checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] @@ -4940,8 +5270,8 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", - "synstructure", + "syn 2.0.100", + "synstructure 0.13.1", ] [[package]] @@ -4969,7 +5299,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.100", ] [[package]] diff --git a/crates/caldav/src/calendar/methods/post.rs b/crates/caldav/src/calendar/methods/post.rs index 1e52180..fabc0a8 100644 --- a/crates/caldav/src/calendar/methods/post.rs +++ b/crates/caldav/src/calendar/methods/post.rs @@ -58,6 +58,17 @@ pub async fn route_post( .to_owned(), topic: calendar_resource.cal.push_topic, expiration: expires.naive_local(), + public_key: request + .subscription + .web_push_subscription + .subscription_public_key + .key, + public_key_type: request + .subscription + .web_push_subscription + .subscription_public_key + .ty, + auth_secret: request.subscription.web_push_subscription.auth_secret, }; subscription_store.upsert_subscription(subscription).await?; diff --git a/crates/carddav/src/addressbook/methods/post.rs b/crates/carddav/src/addressbook/methods/post.rs index 94dc176..2ec898d 100644 --- a/crates/carddav/src/addressbook/methods/post.rs +++ b/crates/carddav/src/addressbook/methods/post.rs @@ -45,6 +45,17 @@ pub async fn route_post( .to_owned(), topic: addressbook.push_topic, expiration: expires.naive_local(), + public_key: request + .subscription + .web_push_subscription + .subscription_public_key + .key, + public_key_type: request + .subscription + .web_push_subscription + .subscription_public_key + .ty, + auth_secret: request.subscription.web_push_subscription.auth_secret, }; subscription_store.upsert_subscription(subscription).await?; diff --git a/crates/dav_push/Cargo.toml b/crates/dav_push/Cargo.toml index 9752236..944be1a 100644 --- a/crates/dav_push/Cargo.toml +++ b/crates/dav_push/Cargo.toml @@ -23,3 +23,4 @@ reqwest.workspace = true tokio.workspace = true rustical_dav.workspace = true rustical_store.workspace = true +web-push = { version = "0.11", default-features = false } diff --git a/crates/dav_push/src/extension.rs b/crates/dav_push/src/extension.rs index 102a2f6..4ddd0fe 100644 --- a/crates/dav_push/src/extension.rs +++ b/crates/dav_push/src/extension.rs @@ -1,6 +1,6 @@ use crate::{ContentUpdate, PropertyUpdate, SupportedTriggers, Transports, Trigger}; use rustical_dav::header::Depth; -use rustical_xml::{EnumUnitVariants, EnumVariants, Unparsed, XmlDeserialize, XmlSerialize}; +use rustical_xml::{EnumUnitVariants, EnumVariants, XmlDeserialize, XmlSerialize}; #[derive(XmlDeserialize, XmlSerialize, PartialEq, Clone, EnumUnitVariants, EnumVariants)] #[xml(unit_variants_ident = "DavPushExtensionPropName")] diff --git a/crates/dav_push/src/notifier.rs b/crates/dav_push/src/notifier.rs index b9ccd14..e19e85d 100644 --- a/crates/dav_push/src/notifier.rs +++ b/crates/dav_push/src/notifier.rs @@ -1,10 +1,15 @@ use actix_web::http::StatusCode; +use reqwest::{ + Method, Request, + header::{self, HeaderName, HeaderValue}, +}; use rustical_dav::xml::multistatus::PropstatElement; use rustical_store::{CollectionOperation, CollectionOperationType, SubscriptionStore}; use rustical_xml::{XmlRootTag, XmlSerialize, XmlSerializeRoot}; -use std::sync::Arc; +use std::{str::FromStr, sync::Arc}; use tokio::sync::mpsc::Receiver; use tracing::{error, info, warn}; +use web_push::{SubscriptionInfo, WebPushMessage, WebPushMessageBuilder}; #[derive(XmlSerialize, Debug)] struct PushMessageProp { @@ -25,6 +30,40 @@ struct PushMessage { propstat: PropstatElement, } +pub fn build_request(message: WebPushMessage) -> Request { + // A little janky :) + let url = reqwest::Url::from_str(&message.endpoint.to_string()).unwrap(); + let mut builder = Request::new(Method::POST, url); + + if let Some(topic) = message.topic { + builder + .headers_mut() + .insert("Topic", HeaderValue::from_str(topic.as_str()).unwrap()); + } + + if let Some(payload) = message.payload { + builder.headers_mut().insert( + header::CONTENT_ENCODING, + HeaderValue::from_static(payload.content_encoding.to_str()), + ); + builder.headers_mut().insert( + header::CONTENT_TYPE, + HeaderValue::from_static("application/octet-stream"), + ); + + for (k, v) in payload.crypto_headers.into_iter() { + let v: &str = v.as_ref(); + builder.headers_mut().insert( + HeaderName::from_static(k), + HeaderValue::from_str(&v).unwrap(), + ); + } + + *builder.body_mut() = Some(reqwest::Body::from(payload.content)); + } + builder +} + pub async fn push_notifier( allowed_push_servers: Option>, mut recv: Receiver, @@ -65,6 +104,19 @@ pub async fn push_notifier( let payload = String::from_utf8(output).unwrap(); for subscriber in subscribers { let push_resource = subscriber.push_resource; + + let sub_info = SubscriptionInfo { + endpoint: push_resource.to_owned(), + keys: web_push::SubscriptionKeys { + p256dh: subscriber.public_key, + auth: subscriber.auth_secret, + }, + }; + let mut builder = WebPushMessageBuilder::new(&sub_info); + builder.set_payload(web_push::ContentEncoding::Aes128Gcm, payload.as_bytes()); + let push_message = builder.build().unwrap(); + let request = build_request(push_message); + let allowed = if let Some(allowed_push_servers) = &allowed_push_servers { if let Ok(resource_url) = reqwest::Url::parse(&push_resource) { let origin = resource_url.origin().ascii_serialization(); @@ -81,12 +133,7 @@ pub async fn push_notifier( if allowed { info!("Sending a push message to {}: {}", push_resource, payload); - if let Err(err) = client - .post(push_resource) - .body(payload.to_owned()) - .send() - .await - { + if let Err(err) = client.execute(request).await { error!("{err}"); } } else { diff --git a/crates/dav_push/src/register.rs b/crates/dav_push/src/register.rs index 4fb7c57..5a3d05b 100644 --- a/crates/dav_push/src/register.rs +++ b/crates/dav_push/src/register.rs @@ -18,9 +18,9 @@ pub struct WebPushSubscription { #[derive(XmlDeserialize, Clone, Debug, PartialEq)] pub struct SubscriptionPublicKey { #[xml(ty = "attr", rename = b"type")] - ty: String, + pub ty: String, #[xml(ty = "text")] - key: String, + pub key: String, } #[derive(XmlDeserialize, Clone, Debug, PartialEq)] diff --git a/crates/store/src/subscription_store.rs b/crates/store/src/subscription_store.rs index 1272b19..23c8f49 100644 --- a/crates/store/src/subscription_store.rs +++ b/crates/store/src/subscription_store.rs @@ -7,6 +7,9 @@ pub struct Subscription { pub topic: String, pub expiration: NaiveDateTime, pub push_resource: String, + pub public_key: String, + pub public_key_type: String, + pub auth_secret: String, } #[async_trait] diff --git a/crates/store_sqlite/migrations/20250503120840_davpush_encryption.down.sql b/crates/store_sqlite/migrations/20250503120840_davpush_encryption.down.sql new file mode 100644 index 0000000..c7cbef4 --- /dev/null +++ b/crates/store_sqlite/migrations/20250503120840_davpush_encryption.down.sql @@ -0,0 +1,4 @@ +ALTER TABLE davpush_subscriptions +DROP public_key, +DROP public_key_type, +DROP auth_secret; diff --git a/crates/store_sqlite/migrations/20250503120840_davpush_encryption.up.sql b/crates/store_sqlite/migrations/20250503120840_davpush_encryption.up.sql new file mode 100644 index 0000000..bbbce5f --- /dev/null +++ b/crates/store_sqlite/migrations/20250503120840_davpush_encryption.up.sql @@ -0,0 +1,7 @@ +-- Old subscriptions are useless anyway +DELETE FROM davpush_subscriptions; + +-- Now the new columns can also be set NOT NULL +ALTER TABLE davpush_subscriptions ADD public_key TEXT NOT NULL; +ALTER TABLE davpush_subscriptions ADD public_key_type TEXT NOT NULL; +ALTER TABLE davpush_subscriptions ADD auth_secret TEXT NOT NULL; diff --git a/crates/store_sqlite/src/subscription_store.rs b/crates/store_sqlite/src/subscription_store.rs index 8c989be..7ab59cc 100644 --- a/crates/store_sqlite/src/subscription_store.rs +++ b/crates/store_sqlite/src/subscription_store.rs @@ -7,7 +7,7 @@ impl SubscriptionStore for SqliteStore { async fn get_subscriptions(&self, topic: &str) -> Result, Error> { Ok(sqlx::query_as!( Subscription, - r#"SELECT id, topic, expiration, push_resource + r#"SELECT id, topic, expiration, push_resource, public_key, public_key_type, auth_secret FROM davpush_subscriptions WHERE (topic) = (?)"#, topic @@ -20,7 +20,7 @@ impl SubscriptionStore for SqliteStore { async fn get_subscription(&self, id: &str) -> Result { Ok(sqlx::query_as!( Subscription, - r#"SELECT id, topic, expiration, push_resource + r#"SELECT id, topic, expiration, push_resource, public_key, public_key_type, auth_secret FROM davpush_subscriptions WHERE (id) = (?)"#, id @@ -32,11 +32,14 @@ impl SubscriptionStore for SqliteStore { async fn upsert_subscription(&self, sub: Subscription) -> Result { sqlx::query!( - r#"INSERT OR REPLACE INTO davpush_subscriptions (id, topic, expiration, push_resource) VALUES (?, ?, ?, ?)"#, + r#"INSERT OR REPLACE INTO davpush_subscriptions (id, topic, expiration, push_resource, public_key, public_key_type, auth_secret) VALUES (?, ?, ?, ?, ?, ?, ?)"#, sub.id, sub.topic, sub.expiration, - sub.push_resource + sub.push_resource, + sub.public_key, + sub.public_key_type, + sub.auth_secret ).execute(&self.db).await.map_err(crate::Error::from)?; // TODO: Correctly return whether a subscription already existed Ok(false)