clean up and mainenence, bump dependencies
This commit is contained in:
parent
7d1fb9d991
commit
1236c427c1
31 changed files with 446 additions and 372 deletions
280
Cargo.lock
generated
280
Cargo.lock
generated
|
@ -52,9 +52,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.0.2"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
|
||||
checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -121,9 +121,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
|
||||
checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
|
@ -135,12 +135,6 @@ version = "1.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
|
||||
|
||||
[[package]]
|
||||
name = "ascii_table"
|
||||
version = "4.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75054ce561491263d7b80dc2f6f6c6f8cdfd0c7a7c17c5cf3b8117829fa72ae1"
|
||||
|
||||
[[package]]
|
||||
name = "async-recursion"
|
||||
version = "1.0.4"
|
||||
|
@ -149,18 +143,18 @@ checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.72"
|
||||
version = "0.1.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09"
|
||||
checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -186,9 +180,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.6.19"
|
||||
version = "0.6.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6a1de45611fdb535bfde7b7de4fd54f4fd2b17b1737c0a59b69bf9b92074b8c"
|
||||
checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core",
|
||||
|
@ -247,7 +241,7 @@ dependencies = [
|
|||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -297,9 +291,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.3.3"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
|
||||
[[package]]
|
||||
name = "bitpacking"
|
||||
|
@ -375,11 +369,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -429,9 +424,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.3.19"
|
||||
version = "4.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d"
|
||||
checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
@ -440,9 +435,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.3.19"
|
||||
version = "4.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1"
|
||||
checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
@ -459,7 +454,7 @@ dependencies = [
|
|||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -472,14 +467,11 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
|
|||
name = "cli"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ascii_table",
|
||||
"base64 0.21.2",
|
||||
"bytes",
|
||||
"clap",
|
||||
"colored",
|
||||
"ctrlc",
|
||||
"dirs",
|
||||
"ed25519-dalek",
|
||||
"fuser",
|
||||
"humantime",
|
||||
"json-canon",
|
||||
|
@ -668,6 +660,15 @@ version = "2.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.9.0"
|
||||
|
@ -783,9 +784,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
|||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
||||
checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
|
@ -872,9 +873,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.26"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
|
||||
checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
|
@ -990,7 +991,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1269,9 +1270,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
|
|||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
|
@ -1296,7 +1297,7 @@ dependencies = [
|
|||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"socket2 0.4.9",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
|
@ -1312,7 +1313,7 @@ dependencies = [
|
|||
"futures-util",
|
||||
"http",
|
||||
"hyper",
|
||||
"rustls 0.21.5",
|
||||
"rustls 0.21.6",
|
||||
"tokio",
|
||||
"tokio-rustls 0.24.1",
|
||||
]
|
||||
|
@ -1352,9 +1353,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.24.6"
|
||||
version = "0.24.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a"
|
||||
checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder",
|
||||
|
@ -1538,9 +1539,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
|||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.3"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
|
||||
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
|
@ -1554,9 +1555,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.19"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "loom"
|
||||
|
@ -1646,9 +1647,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.7.0"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40"
|
||||
checksum = "ed1202b2a6f884ae56f04cff409ab315c5ce26b5e58d7412e484f01fd52f52ef"
|
||||
|
||||
[[package]]
|
||||
name = "md5"
|
||||
|
@ -1993,7 +1994,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"proc-macro2-diagnostics",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2042,29 +2043,29 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.2"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842"
|
||||
checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.1.2"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
|
||||
checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.10"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57"
|
||||
checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
|
@ -2120,7 +2121,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
"version_check",
|
||||
"yansi",
|
||||
]
|
||||
|
@ -2267,13 +2268,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.9.1"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
|
||||
checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata 0.3.3",
|
||||
"regex-automata 0.3.6",
|
||||
"regex-syntax 0.7.4",
|
||||
]
|
||||
|
||||
|
@ -2288,9 +2289,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.3.3"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
|
||||
checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -2332,7 +2333,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls 0.21.5",
|
||||
"rustls 0.21.6",
|
||||
"rustls-pemfile",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -2387,11 +2388,11 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.4"
|
||||
version = "0.38.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5"
|
||||
checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
|
||||
dependencies = [
|
||||
"bitflags 2.3.3",
|
||||
"bitflags 2.4.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
|
@ -2412,9 +2413,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.21.5"
|
||||
version = "0.21.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79ea77c539259495ce8ca47f53e66ae0330a8819f67e23ac96ca02f50e7b7d36"
|
||||
checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring",
|
||||
|
@ -2433,9 +2434,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.101.2"
|
||||
version = "0.101.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "513722fd73ad80a71f72b61009ea1b584bcfa1483ca93949c8f290298837fa59"
|
||||
checksum = "261e9e0888cba427c3316e6322805653c9425240b6fd96cee7cb671ab70ab8d0"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
|
@ -2483,9 +2484,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.177"
|
||||
version = "1.0.183"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63ba2516aa6bf82e0b19ca8b50019d52df58455d3cf9bdaf6315225fdd0c560a"
|
||||
checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
@ -2503,20 +2504,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.177"
|
||||
version = "1.0.183"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "401797fe7833d72109fedec6bfcbe67c0eed9b99772f26eb8afd261f0abc6fd3"
|
||||
checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.104"
|
||||
version = "1.0.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c"
|
||||
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -2560,8 +2561,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"async-recursion",
|
||||
"axum",
|
||||
"base64 0.21.2",
|
||||
"bitflags 2.3.3",
|
||||
"bitflags 2.4.0",
|
||||
"bytes",
|
||||
"clap",
|
||||
"epub",
|
||||
|
@ -2632,9 +2632,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sha2-asm"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf27176fb5d15398e3a479c652c20459d9dac830dedd1fa55b42a77dbcdbfcea"
|
||||
checksum = "f27ba7066011e3fb30d808b51affff34f0a66d3a03a58edd787c6e420e40e44e"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
@ -2709,6 +2709,16 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
|
@ -2841,9 +2851,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|||
name = "store-fs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum",
|
||||
"flume",
|
||||
"futures-util",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -2915,9 +2923,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.27"
|
||||
version = "2.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
|
||||
checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -3075,9 +3083,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.7.0"
|
||||
version = "3.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998"
|
||||
checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
|
@ -3099,22 +3107,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.44"
|
||||
version = "1.0.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
|
||||
checksum = "d9207952ae1a003f42d3d5e892dac3c6ba42aa6ac0c79a6a91a2b5cb4253e75c"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.44"
|
||||
version = "1.0.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
|
||||
checksum = "f1728216d3244de4f14f14f8c15c79be1a7c67867d28d69b719690e2a19fb445"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3129,9 +3137,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tiff"
|
||||
version = "0.8.1"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471"
|
||||
checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"jpeg-decoder",
|
||||
|
@ -3140,10 +3148,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.23"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446"
|
||||
checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"serde",
|
||||
"time-core",
|
||||
|
@ -3158,9 +3167,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
|
|||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.10"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4"
|
||||
checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
@ -3182,11 +3191,10 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.29.1"
|
||||
version = "1.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
|
||||
checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
|
@ -3194,7 +3202,7 @@ dependencies = [
|
|||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"socket2 0.5.3",
|
||||
"tokio-macros",
|
||||
"windows-sys",
|
||||
]
|
||||
|
@ -3207,7 +3215,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3227,7 +3235,7 @@ version = "0.24.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
|
||||
dependencies = [
|
||||
"rustls 0.21.5",
|
||||
"rustls 0.21.6",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
|
@ -3244,9 +3252,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-tungstenite"
|
||||
version = "0.19.0"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c"
|
||||
checksum = "2b2dbec703c26b00d74844519606ef15d09a7d6857860f84ad223dec002ddea2"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
|
@ -3324,7 +3332,7 @@ version = "0.4.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55ae70283aba8d2a8b411c695c437fe25b8b5e44e23e780662002fc72fb47a82"
|
||||
dependencies = [
|
||||
"bitflags 2.3.3",
|
||||
"bitflags 2.4.0",
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
|
@ -3370,7 +3378,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3420,9 +3428,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
|||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.19.0"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67"
|
||||
checksum = "e862a1c4128df0112ab625f55cd5c934bcb4312ba80b39ae4b4835a3fd58e649"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"bytes",
|
||||
|
@ -3629,7 +3637,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -3663,7 +3671,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -3751,9 +3759,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.1"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
|
||||
checksum = "d1eeca1c172a285ee6c2c84c341ccea837e7c01b12fbb2d0fe3c9e550ce49ec8"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
|
@ -3766,51 +3774,51 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.0"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
checksum = "b10d0c968ba7f6166195e13d593af609ec2e3d24f916f081690695cf5eaffb2f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
checksum = "571d8d4e62f26d4932099a9efe89660e8bd5087775a2ab5cdd8b747b811f1058"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
checksum = "2229ad223e178db5fbbc8bd8d3835e51e566b8474bfca58d2e6150c48bb723cd"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
checksum = "600956e2d840c194eedfc5d18f8242bc2e17c7775b6684488af3a9fff6fe3287"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.0"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
checksum = "ea99ff3f8b49fb7a8e0d305e5aec485bd068c2ba691b6e277d29eaeac945868a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.0"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
checksum = "8f1a05a1ece9a7a0d5a7ccf30ba2c33e3a61a30e042ffd247567d1de1d94120d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
version = "0.48.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
checksum = "d419259aba16b663966e29e6d7c6ecfa0bb8425818bb96f6f1f3c3eb71a6e7b9"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.3"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f46aab759304e4d7b2075a9aecba26228bb073ee8c50db796b2c72c676b5d807"
|
||||
checksum = "1e461589e194280efaa97236b73623445efa195aa633fd7004f39805707a9d53"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -3843,15 +3851,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "1.0.0-rc"
|
||||
version = "1.0.0-rc.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ee746ad3851dd3bc40e4a028ab3b00b99278d929e48957bcb2d111874a7e43e"
|
||||
checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.6.1"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236"
|
||||
checksum = "f3b9c234616391070b0b173963ebc65a9195068e7ed3731c6edac2ec45ebe106"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"zerocopy-derive",
|
||||
|
@ -3859,13 +3867,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.3.2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3"
|
||||
checksum = "8f7f3a471f98d0a61c34322fbbfd10c384b07687f680d4119813713f72308d91"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3885,7 +3893,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -6,14 +6,11 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
ascii_table = "4.0.2"
|
||||
base64 = "0.21.2"
|
||||
bytes = "1.4.0"
|
||||
clap = { version = "4.3.11", features = ["derive"] }
|
||||
colored = "2.0.4"
|
||||
ctrlc = "3.4.0"
|
||||
dirs = "5.0.1"
|
||||
ed25519-dalek = "1.0.1"
|
||||
fuser = "0.12.0"
|
||||
humantime = "2.1.0"
|
||||
json-canon = "0.1.3"
|
||||
|
|
|
@ -112,6 +112,8 @@ pub struct ActorEvent {
|
|||
pub name: String,
|
||||
#[serde(rename = "type")]
|
||||
pub actor_type: ActorType,
|
||||
#[serde(flatten)]
|
||||
pub _other: HashMap<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
|
|
|
@ -8,7 +8,6 @@ edition = "2021"
|
|||
[dependencies]
|
||||
async-recursion = "1.0.4"
|
||||
axum = { version = "0.6.18", features = ["macros", "headers", "ws"] }
|
||||
base64 = "0.21.2"
|
||||
bitflags = "2.3.3"
|
||||
bytes = "1.4.0"
|
||||
clap = { version = "4.3.14", features = ["derive"] }
|
||||
|
@ -31,7 +30,7 @@ serde = { version = "1.0.164", features = ["derive"] }
|
|||
serde-aux = "4.2.0"
|
||||
serde_json = "1.0.97"
|
||||
sha2 = { version = "0.10.7", features = ["asm"] }
|
||||
sqlx = { version = "0.6.3", features = ["sqlite", "runtime-tokio-rustls", "offline"] }
|
||||
sqlx = { version = "0.6.3", features = ["sqlite", "runtime-tokio-rustls"] }
|
||||
tantivy = "0.20.2"
|
||||
thiserror = "1.0.40"
|
||||
tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros", "process"] }
|
||||
|
|
|
@ -80,26 +80,31 @@ impl Client {
|
|||
Ok(res.item_ref)
|
||||
}
|
||||
|
||||
pub async fn get(&self, item_ref: &ItemRef) -> Result<Item, Error> {
|
||||
pub async fn get(&self, item_ref: &ItemRef) -> Result<Option<Item>, Error> {
|
||||
debug!("get blob");
|
||||
let req = self
|
||||
.http
|
||||
.get(format!("{}/blobs/{}", self.base_url, item_ref))
|
||||
.send()
|
||||
.await?
|
||||
.await?;
|
||||
if req.status() == StatusCode::NOT_FOUND {
|
||||
return Ok(None);
|
||||
}
|
||||
let bytes = req
|
||||
.error_for_status()?
|
||||
.bytes()
|
||||
.await?;
|
||||
Item::from_bytes(req)
|
||||
Ok(Some(Item::from_bytes(bytes)?))
|
||||
}
|
||||
|
||||
pub async fn get_via(&self, item_ref: &ItemRef, via: &str) -> Result<Item, Error> {
|
||||
pub async fn get_via(&self, item_ref: &ItemRef, via: &str) -> Result<Option<Item>, Error> {
|
||||
debug!("get blob through server {}", via);
|
||||
let url = format!("http://{}/things/{}", via, item_ref);
|
||||
trace!("target url: {}", url);
|
||||
|
||||
let req = match self.http.get(url).send().await? {
|
||||
req if req.status() == StatusCode::GONE => req,
|
||||
req if req.status() == StatusCode::NOT_MODIFIED => return Ok(None),
|
||||
req => req.error_for_status()?,
|
||||
};
|
||||
let header = req
|
||||
|
@ -127,6 +132,6 @@ impl Client {
|
|||
return Err(Error::Validation("server gave an invalid hash"));
|
||||
}
|
||||
|
||||
Ok(item)
|
||||
Ok(Some(item))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use axum::http::StatusCode;
|
|||
use axum::response::IntoResponse;
|
||||
use serde_json::json;
|
||||
use tracing::error;
|
||||
use ufh::item::ItemRef;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
|
@ -12,8 +13,8 @@ pub enum Error {
|
|||
Json(serde_json::Error),
|
||||
#[error("{0}")]
|
||||
Database(sqlx::Error),
|
||||
#[error("not found")]
|
||||
NotFound,
|
||||
#[error("{0} not found")]
|
||||
NotFound(String),
|
||||
#[error("{0}")]
|
||||
Image(image::ImageError),
|
||||
#[error("{1}")]
|
||||
|
@ -35,8 +36,11 @@ pub enum Error {
|
|||
|
||||
impl From<reqwest::Error> for Error {
|
||||
fn from(err: reqwest::Error) -> Self {
|
||||
if err.status().is_some_and(|code| code == StatusCode::NOT_FOUND) {
|
||||
Error::NotFound
|
||||
if err
|
||||
.status()
|
||||
.is_some_and(|code| code == StatusCode::NOT_FOUND)
|
||||
{
|
||||
Error::NotFound(err.url().expect("404 error should have a url").to_string())
|
||||
} else {
|
||||
Error::Reqwest(err)
|
||||
}
|
||||
|
@ -52,7 +56,7 @@ impl From<serde_json::Error> for Error {
|
|||
impl From<sqlx::Error> for Error {
|
||||
fn from(err: sqlx::Error) -> Self {
|
||||
match err {
|
||||
sqlx::Error::RowNotFound => Error::NotFound,
|
||||
sqlx::Error::RowNotFound => Error::NotFound("row".into()),
|
||||
err => Error::Database(err),
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +120,7 @@ impl Error {
|
|||
sqlx::Error::RowNotFound => unreachable!(),
|
||||
_ => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
},
|
||||
Error::NotFound => StatusCode::NOT_FOUND,
|
||||
Error::NotFound(_) => StatusCode::NOT_FOUND,
|
||||
Error::Image(_) => StatusCode::UNSUPPORTED_MEDIA_TYPE,
|
||||
Error::Validation(_) => StatusCode::BAD_REQUEST,
|
||||
Error::ItemRefParse(_) => StatusCode::BAD_REQUEST,
|
||||
|
@ -127,4 +131,9 @@ impl Error {
|
|||
Error::Http(status, _) => *status,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn no_ref(item_ref: &ItemRef) -> Error {
|
||||
Error::NotFound(format!("ref {}", item_ref))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,15 @@ type Relations = HashMap<ItemRef, (Event, RelInfo)>;
|
|||
pub async fn get_relations(db: &Sqlite, event: &Event) -> Result<Relations, Error> {
|
||||
// get/validate relations
|
||||
let rel_ids: Vec<_> = event.relations.keys().cloned().collect();
|
||||
let rel_events = db.bulk_fetch(&rel_ids, false).await?;
|
||||
let rel_events = db.bulk_fetch(&rel_ids).await?;
|
||||
if rel_events.iter().any(|i| i.1.is_none()) {
|
||||
return Err(Error::Validation("one or more chunk items doesn't exist"));
|
||||
}
|
||||
rel_events
|
||||
.into_iter()
|
||||
.map(|(item_ref, item)| {
|
||||
let rel_info = &event.relations[&item_ref];
|
||||
match item {
|
||||
match item.unwrap() {
|
||||
DbItem::Event(event) => Ok((item_ref, (*event, rel_info.clone()))),
|
||||
DbItem::Blob(_) => Err(Error::Validation(
|
||||
"some relations are to blobs instead of events",
|
||||
|
@ -53,7 +56,7 @@ pub async fn prepare_special(
|
|||
match &event.content {
|
||||
EventContent::Actor(_) => {
|
||||
let query = ufh::query::Query::builder()
|
||||
.with_type("x.user")
|
||||
.with_type("x.actor")
|
||||
.with_sender(&event.sender)
|
||||
.build();
|
||||
let result = me.db.query_events(&query, Location::Beginning, 1).await?;
|
||||
|
@ -62,14 +65,13 @@ pub async fn prepare_special(
|
|||
}
|
||||
},
|
||||
EventContent::File(f) => {
|
||||
match me.db.bulk_fetch(&f.chunks, false).await {
|
||||
Ok(items) if items.iter().all(|i| matches!(i, (_, DbItem::Blob(_)))) => Ok(()),
|
||||
Ok(_) => Err(Error::Validation("one or more chunk items isn't a blob")),
|
||||
Err(Error::NotFound) => {
|
||||
Err(Error::Validation("one or more chunk items doesn't exist"))
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}?;
|
||||
let items = me.db.bulk_fetch(&f.chunks).await?;
|
||||
if items.iter().any(|i| i.1.is_none()) {
|
||||
return Err(Error::Validation("one or more chunk items doesn't exist"));
|
||||
}
|
||||
if items.iter().any(|i| !matches!(i, (_, Some(DbItem::Blob(_))))) {
|
||||
return Err(Error::Validation("one or more chunk items isn't a blob"));
|
||||
}
|
||||
}
|
||||
EventContent::Redact(_) => {
|
||||
if event.relations.is_empty() {
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
use crate::{
|
||||
blobs,
|
||||
items::events::update_search_index,
|
||||
peer::{Contact, NodeId, RPCRequest, RPCResponse},
|
||||
perms::can_send_event,
|
||||
routes::things::{thumbnail::ThumbnailSize, Error},
|
||||
state::{
|
||||
db::{sqlite::Sqlite, Database},
|
||||
search::tantivy::Tantivy,
|
||||
},
|
||||
Relations, peer::{NodeId, Contact, RPCResponse, RPCRequest}, P2PState,
|
||||
P2PState, Relations,
|
||||
};
|
||||
use axum::http::StatusCode;
|
||||
use bytes::Bytes;
|
||||
use events::DelayedAction;
|
||||
use lru::LruCache;
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::{num::NonZeroUsize, sync::Arc, collections::HashSet};
|
||||
use std::{collections::HashSet, num::NonZeroUsize, sync::Arc};
|
||||
use tokio::sync::RwLock;
|
||||
use tracing::{trace, debug, info, error};
|
||||
use tracing::{debug, error, info, trace};
|
||||
use ufh::{
|
||||
derived::Derived,
|
||||
event::{Event, EventContent, WipEvent},
|
||||
|
@ -25,6 +26,9 @@ use ufh::{
|
|||
|
||||
pub mod events;
|
||||
|
||||
// TODO: make this tuneable via config file
|
||||
const CACHE_SIZE: usize = 100;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum Item {
|
||||
|
@ -124,7 +128,7 @@ impl Items {
|
|||
#[async_recursion::async_recursion]
|
||||
pub async fn commit_event_create(&self, wip: WipCreate) -> Result<DerivelessCreate, Error> {
|
||||
let event = wip.event;
|
||||
|
||||
|
||||
let rowid = self.db.event_create(&event).await?;
|
||||
debug!("created event (rowid={})", rowid);
|
||||
|
||||
|
@ -133,7 +137,11 @@ impl Items {
|
|||
debug!("commit special cases");
|
||||
}
|
||||
|
||||
Ok(DerivelessCreate { item_ref: wip.item_ref, rowid, event })
|
||||
Ok(DerivelessCreate {
|
||||
item_ref: wip.item_ref,
|
||||
rowid,
|
||||
event,
|
||||
})
|
||||
}
|
||||
|
||||
/// finish extra processing, eg. deriving metadata or indexing for fts
|
||||
|
@ -164,14 +172,21 @@ impl Items {
|
|||
Derived::default()
|
||||
};
|
||||
|
||||
let event = Event { derived: derived.clone(), ..event };
|
||||
let event = Event {
|
||||
derived: derived.clone(),
|
||||
..event
|
||||
};
|
||||
|
||||
// TODO (performance): this exists to get the updated event derives, but could easily be done without a query
|
||||
let relations = events::get_relations(&self.db, &event).await?;
|
||||
|
||||
update_search_index(self, &event, &relations).await?;
|
||||
|
||||
Ok(Create { event, relations, rowid: wip.rowid })
|
||||
|
||||
Ok(Create {
|
||||
event,
|
||||
relations,
|
||||
rowid: wip.rowid,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn create_event(&self, wip: WipEvent) -> Result<Create, Error> {
|
||||
|
@ -189,82 +204,81 @@ impl Items {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip_all, fields(item_ref))]
|
||||
pub async fn get(&self, item_ref: &ItemRef) -> Result<Item, Error> {
|
||||
pub async fn get(&self, item_ref: &ItemRef) -> Result<Option<Item>, Error> {
|
||||
static CACHE: OnceCell<RwLock<LruCache<ItemRef, Item>>> = OnceCell::new();
|
||||
// let mut cache = CACHE.get_or_init(|| Mutex::new(LruCache::new(NonZeroUsize::new(100).unwrap()))).lock().await;
|
||||
let cache = CACHE
|
||||
.get_or_init(|| RwLock::new(LruCache::new(NonZeroUsize::new(1).unwrap())))
|
||||
.read()
|
||||
.await;
|
||||
let cached = cache.peek(item_ref).cloned();
|
||||
drop(cache);
|
||||
.get_or_init(|| RwLock::new(LruCache::new(NonZeroUsize::new(CACHE_SIZE).unwrap())));
|
||||
let cached = cache.read().await.peek(item_ref).cloned();
|
||||
match cached {
|
||||
Some(item) => {
|
||||
CACHE.get().expect("already init").write().await.promote(item_ref);
|
||||
Ok(item)
|
||||
cache.write().await.promote(item_ref);
|
||||
Ok(Some(item))
|
||||
}
|
||||
None => {
|
||||
let item = self.get_uncached(item_ref).await?;
|
||||
CACHE.get().expect("already init").write().await.put(item_ref.clone(), item.clone());
|
||||
Ok(item)
|
||||
let Some(item) = self.get_uncached(item_ref).await? else {
|
||||
return Ok(None);
|
||||
};
|
||||
cache.write().await.put(item_ref.clone(), item.clone());
|
||||
Ok(Some(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_uncached(&self, item_ref: &ItemRef) -> Result<Item, Error> {
|
||||
// TODO (future, maybe): batch lookup requests per bucket
|
||||
// this only makes sense when you have a lot of requests concerning one bucket at once
|
||||
async fn get_uncached(&self, item_ref: &ItemRef) -> Result<Option<Item>, Error> {
|
||||
tracing::Span::current().record("item_ref", item_ref.to_string());
|
||||
|
||||
|
||||
if let Some(item) = self.db.event_fetch(item_ref).await? {
|
||||
return Ok(Item::Event(item));
|
||||
return Ok(Some(Item::Event(item)));
|
||||
}
|
||||
|
||||
match self.blobs.get(item_ref).await {
|
||||
Ok(blobs::Item::WipEvent(wip)) => {
|
||||
Ok(Some(blobs::Item::WipEvent(wip))) => {
|
||||
debug!("event didn't exist in db, re-adding");
|
||||
return self.import_event(wip).await;
|
||||
return Ok(Some(self.import_event(wip).await?));
|
||||
}
|
||||
Ok(blobs::Item::Raw(bytes)) => {
|
||||
Ok(Some(blobs::Item::Raw(bytes))) => {
|
||||
// make sure the blob is in db
|
||||
// TODO (performance): remove this
|
||||
debug!("re-inserting into db");
|
||||
self.db.create_blob(item_ref, bytes.len() as u32).await?;
|
||||
return Ok(Item::Blob(bytes));
|
||||
},
|
||||
Err(Error::NotFound) => {
|
||||
trace!("not found");
|
||||
},
|
||||
return Ok(Some(Item::Blob(bytes)));
|
||||
}
|
||||
Ok(None) => trace!("not found"),
|
||||
Err(err) => {
|
||||
error!("blobs::get failed: {}", err);
|
||||
return Err(err)
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
|
||||
for hoster in find_hosters(&self.p2p, &NodeId::new_from_ref(item_ref)).await {
|
||||
trace!("importing item from (host={})", hoster.host);
|
||||
match self.blobs.get_via(item_ref, &hoster.host).await {
|
||||
Ok(blobs::Item::WipEvent(wip)) => {
|
||||
Ok(Some(blobs::Item::WipEvent(wip))) => {
|
||||
debug!("importing event from other server");
|
||||
return self.import_event(wip).await;
|
||||
},
|
||||
Ok(blobs::Item::Raw(bytes)) => {
|
||||
return Ok(Some(self.import_event(wip).await?));
|
||||
}
|
||||
Ok(Some(blobs::Item::Raw(bytes))) => {
|
||||
debug!("pulled new blob (size={})", bytes.len());
|
||||
self.blobs.put(blobs::Item::Raw(bytes.clone())).await?;
|
||||
self.db.create_blob(item_ref, bytes.len() as u32).await?;
|
||||
return Ok(Item::Blob(bytes));
|
||||
},
|
||||
Err(Error::NotFound) => {
|
||||
return Ok(Some(Item::Blob(bytes)));
|
||||
}
|
||||
Ok(None) => {
|
||||
trace!("target item not found");
|
||||
},
|
||||
}
|
||||
Err(Error::Reqwest(err)) if err.status().is_some_and(|s| s.is_client_error()) => {
|
||||
debug!("couldn't fetch from other server: {}", err);
|
||||
return Err(err.into());
|
||||
},
|
||||
}
|
||||
Err(_) => (),
|
||||
};
|
||||
}
|
||||
|
||||
trace!("item not found");
|
||||
return Err(Error::NotFound);
|
||||
// TODO: cache `None`s
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[async_recursion::async_recursion]
|
||||
|
@ -295,10 +309,10 @@ impl Items {
|
|||
#[tracing::instrument(skip_all, fields(key))]
|
||||
async fn find_hosters(p2p: &P2PState, key: &NodeId) -> Vec<Contact> {
|
||||
tracing::Span::current().record("key", key.to_string());
|
||||
|
||||
|
||||
let map = p2p.map.lock().await;
|
||||
trace!("map: {:?}", map);
|
||||
|
||||
|
||||
if let Some(value) = map.get(key) {
|
||||
trace!("found item locally");
|
||||
value.clone()
|
||||
|
@ -314,7 +328,10 @@ async fn find_hosters(p2p: &P2PState, key: &NodeId) -> Vec<Contact> {
|
|||
if contact == p2p.contact {
|
||||
continue;
|
||||
}
|
||||
let Ok(response) = contact.send(&p2p.contact, RPCRequest::FindValue(*key)).await else {
|
||||
let Ok(response) = contact
|
||||
.send(&p2p.contact, RPCRequest::FindValue(*key))
|
||||
.await
|
||||
else {
|
||||
trace!("failed to send, removing node (host={})", p2p.contact.host);
|
||||
let mut router = p2p.router.lock().await;
|
||||
router.remove(&contact.id);
|
||||
|
@ -339,7 +356,7 @@ async fn find_hosters(p2p: &P2PState, key: &NodeId) -> Vec<Contact> {
|
|||
}
|
||||
RPCResponse::Ok => {
|
||||
trace!("node sent Ok message (host={})", p2p.contact.host);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
trace!("no nodes");
|
||||
|
|
|
@ -54,6 +54,9 @@ use crate::state::db::{Database, Location};
|
|||
|
||||
const MAX_SIZE: u64 = 1024 * 1024;
|
||||
|
||||
// TODO: split out indexers a bit more quickly than anticipated: build
|
||||
// times are getting long!
|
||||
|
||||
// TODO (future): maybe use a websocket instead of long polling?
|
||||
// for receiving new events, would potentially be a lot more complicated though
|
||||
|
||||
|
|
|
@ -30,8 +30,8 @@ pub async fn can_view_event(db: &Sqlite, event: &Event, user: &ActorId) -> bool
|
|||
}
|
||||
|
||||
// FIXME (security): don't allow user enumeration! and find a better way to do this
|
||||
if event.get_type() == "x.user" {
|
||||
trace!("TEMP: matches because this is an x.user event");
|
||||
if event.get_type() == "x.actor" {
|
||||
trace!("TEMP: matches because this is an x.actor event");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -97,18 +97,18 @@ pub async fn can_send_event(db: &Sqlite, wip: &WipEvent) -> Result<bool, Error>
|
|||
};
|
||||
|
||||
let rel_ids: Vec<_> = relations.keys().cloned().collect();
|
||||
let rel_events = match db.bulk_fetch(&rel_ids, false).await {
|
||||
Ok(rel_events) => rel_events,
|
||||
// Err(Error::NotFound) => {
|
||||
// todo!();
|
||||
// },
|
||||
Err(err) => return Err(err),
|
||||
let rel_events = db.bulk_fetch(&rel_ids).await?;
|
||||
|
||||
if rel_events.iter().any(|i| i.1.is_none()) {
|
||||
// TODO: fetch missing relations
|
||||
todo!();
|
||||
};
|
||||
|
||||
let relations = rel_events
|
||||
.into_iter()
|
||||
.map(|(item_ref, item)| {
|
||||
let rel_info = &relations[&item_ref];
|
||||
match item {
|
||||
match item.unwrap() {
|
||||
DbItem::Event(event) => Ok((item_ref, (*event, rel_info.clone()))),
|
||||
DbItem::Blob(_) => Err(Error::Validation(
|
||||
"some relations are to blobs instead of events",
|
||||
|
|
|
@ -58,18 +58,19 @@ async fn search(
|
|||
.search(¶ms.q, limit, offset, sniplen)
|
||||
.await?;
|
||||
let item_refs: Vec<ItemRef> = results.iter().map(|i| i.item_ref.clone()).collect();
|
||||
let results = state.db.bulk_fetch(&item_refs, true)
|
||||
let results = state.db.bulk_fetch(&item_refs)
|
||||
.await?
|
||||
.into_iter()
|
||||
.zip(results)
|
||||
.map(|((_, item), doc)| {
|
||||
match item {
|
||||
DbItem::Blob(_) => panic!("search result returned a blob"),
|
||||
DbItem::Event(event) => SearchDoc {
|
||||
Some(DbItem::Blob(_)) => unreachable!("search result returned a blob"),
|
||||
Some(DbItem::Event(event)) => SearchDoc {
|
||||
score: doc.score,
|
||||
snippet: doc.snippet,
|
||||
event,
|
||||
},
|
||||
None => unreachable!("search result returned a nonexistant event"),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
|
|
@ -26,11 +26,12 @@ pub async fn route(
|
|||
debug!("fetch blob");
|
||||
|
||||
let (event, file) = match state.items.get(&item_ref).await? {
|
||||
Item::Event(event) => match event.content.clone() {
|
||||
Some(Item::Event(event)) => match event.content.clone() {
|
||||
EventContent::File(file) => (event, file),
|
||||
_ => return Err(Error::Validation("this is not a x.file event")),
|
||||
},
|
||||
Item::Blob(_) => return Err(Error::Validation("this is not an event at all")),
|
||||
Some(Item::Blob(_)) => return Err(Error::Validation("this is not an event at all")),
|
||||
None => return Err(Error::no_ref(&item_ref)),
|
||||
};
|
||||
|
||||
let mime = event
|
||||
|
@ -70,14 +71,16 @@ pub async fn route(
|
|||
}
|
||||
let blobs: Vec<(ItemRef, usize)> = state
|
||||
.db
|
||||
.bulk_fetch(&file.chunks, false)
|
||||
.bulk_fetch(&file.chunks)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|(item_ref, item)| match item {
|
||||
DbItem::Event(_) => {
|
||||
Some(DbItem::Event(_)) => {
|
||||
unreachable!("all file chunks should've been validated to be blobs on create")
|
||||
}
|
||||
DbItem::Blob(size) => (item_ref, size as usize),
|
||||
Some(DbItem::Blob(size)) => (item_ref, size as usize),
|
||||
// FIXME (future): this won't be true soon, if servers garbage collect unused foreign blobs
|
||||
None => unreachable!("all file chunks should've been validated to exist on create")
|
||||
})
|
||||
.collect();
|
||||
let total_len: usize = blobs.iter().map(|i| i.1).sum();
|
||||
|
@ -89,7 +92,8 @@ pub async fn route(
|
|||
|
||||
let mut chunks = Vec::with_capacity(file.chunks.len());
|
||||
for item_ref in &intersection {
|
||||
let Item::Blob(blob) = state.items.get(item_ref).await? else {
|
||||
let Some(Item::Blob(blob)) = state.items.get(item_ref).await? else {
|
||||
// should i remove this constraint - allow x.file events to exist without having all blobs?
|
||||
unreachable!("file didn't reference a blob");
|
||||
};
|
||||
chunks.push(blob);
|
||||
|
@ -106,7 +110,7 @@ pub async fn route(
|
|||
|
||||
let mut chunks = Vec::with_capacity(file.chunks.len());
|
||||
for item_ref in &intersection {
|
||||
let Item::Blob(blob) = state.items.get(item_ref).await? else {
|
||||
let Some(Item::Blob(blob)) = state.items.get(item_ref).await? else {
|
||||
unreachable!("file didn't reference a blob");
|
||||
};
|
||||
chunks.push(blob);
|
||||
|
|
|
@ -29,10 +29,10 @@ pub async fn route(
|
|||
debug!("bulk check");
|
||||
let have = state
|
||||
.db
|
||||
.bulk_fetch(&options.refs, true)
|
||||
.bulk_fetch(&options.refs)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|(item_ref, _)| item_ref)
|
||||
.filter_map(|(item_ref, item)| item.is_some().then_some(item_ref))
|
||||
.collect();
|
||||
Ok(Json(BulkCheckResponse { have }))
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ pub async fn route(
|
|||
}
|
||||
|
||||
pub async fn notify_have(p2p: &P2PState, item_ref: &ItemRef) {
|
||||
let key = NodeId::new_from_ref(&item_ref);
|
||||
let key = NodeId::new_from_ref(item_ref);
|
||||
let mut map = p2p.map.lock().await;
|
||||
map.insert(key, vec![p2p.contact.clone()]);
|
||||
drop(map);
|
||||
|
|
|
@ -29,7 +29,7 @@ pub async fn route(
|
|||
let item = state.items.get(&item_ref).await?;
|
||||
|
||||
match item {
|
||||
Item::Blob(blob) => {
|
||||
Some(Item::Blob(blob)) => {
|
||||
debug!("got blob");
|
||||
Ok((
|
||||
StatusCode::OK,
|
||||
|
@ -37,12 +37,12 @@ pub async fn route(
|
|||
blob,
|
||||
))
|
||||
}
|
||||
Item::Event(event) => {
|
||||
Some(Item::Event(event)) => {
|
||||
let is_visible = if let Some(user) = &auth.user {
|
||||
can_view_event(&state.db, &event, user).await
|
||||
} else {
|
||||
// note that this doesn't define whether any event is *enumeratable*
|
||||
(event.get_type() == "x.file" || event.get_type() == "x.user") && !event.is_redacted()
|
||||
(event.get_type() == "x.file" || event.get_type() == "x.actor") && !event.is_redacted()
|
||||
};
|
||||
if !is_visible {
|
||||
// TODO (security): should this be "not found" instead of forbidden?
|
||||
|
@ -67,5 +67,6 @@ pub async fn route(
|
|||
Bytes::from(event_str.into_bytes()),
|
||||
))
|
||||
}
|
||||
None => Err(Error::no_ref(&item_ref)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ pub async fn route(
|
|||
.db
|
||||
.event_fetch(&item_ref)
|
||||
.await?
|
||||
.ok_or(Error::NotFound)?;
|
||||
.ok_or_else(|| Error::no_ref(&item_ref))?;
|
||||
let blob = get_blob(&state.items, &event).await?;
|
||||
debug!("generate thumbnail");
|
||||
let thumb = generate_thumb(&blob, &size)?;
|
||||
|
|
|
@ -176,9 +176,10 @@ pub async fn get_blob(
|
|||
};
|
||||
let mut chunks = Vec::with_capacity(file.chunks.len());
|
||||
for item_ref in &file.chunks {
|
||||
let Item::Blob(blob) = items.get(item_ref).await? else {
|
||||
// possibly unreachable!(), assuming everything validated properly on insert
|
||||
return Err(Error::Validation("file didn't reference a blob"));
|
||||
let blob = match items.get(item_ref).await? {
|
||||
Some(Item::Blob(blob)) => blob,
|
||||
Some(Item::Event(_)) => return Err(Error::Validation("file didn't reference a blob")),
|
||||
None => return Err(Error::no_ref(item_ref)),
|
||||
};
|
||||
chunks.push(blob);
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ pub trait Database {
|
|||
|
||||
// misc
|
||||
async fn tags_set(&self, item_refs: &[ItemRef], tags: &[String]) -> Result<(), Self::Error>;
|
||||
async fn bulk_fetch(&self, item_refs: &[ItemRef], partial: bool) -> Result<Vec<(ItemRef, DbItem)>, Self::Error>;
|
||||
async fn bulk_fetch(&self, item_refs: &[ItemRef]) -> Result<Vec<(ItemRef, Option<DbItem>)>, Self::Error>;
|
||||
|
||||
// thumbnails
|
||||
async fn thumbnail_put(&self, item_ref: &ItemRef, size: &ThumbnailSize, bytes: &[u8]) -> Result<(), Self::Error>;
|
||||
|
|
|
@ -396,8 +396,7 @@ impl Database for Sqlite {
|
|||
async fn bulk_fetch(
|
||||
&self,
|
||||
item_refs: &[ItemRef],
|
||||
partial: bool,
|
||||
) -> Result<Vec<(ItemRef, DbItem)>, Self::Error> {
|
||||
) -> Result<Vec<(ItemRef, Option<DbItem>)>, Self::Error> {
|
||||
let _lock = self.lock.read().await;
|
||||
let mut builder = sqlx::QueryBuilder::new(
|
||||
"
|
||||
|
@ -431,10 +430,7 @@ impl Database for Sqlite {
|
|||
.unwrap_or_default();
|
||||
DbItem::Event(Box::new(Event { derived, ..event }))
|
||||
};
|
||||
items.push((item_ref, item));
|
||||
}
|
||||
if !partial && item_refs.len() != items.len() {
|
||||
return Err(Error::NotFound);
|
||||
items.push((item_ref, Some(item)));
|
||||
}
|
||||
// TODO (performance): ...
|
||||
items.sort_by(|(a_ref, _), (b_ref, _)| {
|
||||
|
|
17
spec/acl.rs
17
spec/acl.rs
|
@ -1,3 +1,6 @@
|
|||
// NOTE: THIS MAY NOT BE ACCURATE!!!
|
||||
// see the real `perms.rs` in server for now, this will be stabalized in the future!
|
||||
|
||||
/// pseudocode for validing events
|
||||
/// the 2 main functions `is_event_visible` and `is_event_sendable`
|
||||
|
||||
|
@ -49,16 +52,16 @@ fn validate_relations(event: &Event, ctx: &Context) -> bool {
|
|||
}
|
||||
|
||||
fn is_relation_valid(relation: &Event, ctx: &Context) -> bool {
|
||||
// a relation is allowed if the user has sent that event
|
||||
if relation.sender == ctx.user {
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Some(acl) = get_acl(&relation) {
|
||||
// or if an acl set on it allows it
|
||||
// a relation is allowed if an acl set on it allows it
|
||||
acl.can_send(ctx.user, ctx.event, ctx.relations)
|
||||
} else {
|
||||
// or if all of it's relations are also valid
|
||||
// or if no acl is set, the user has sent that event
|
||||
if relation.sender == ctx.user {
|
||||
return true;
|
||||
}
|
||||
|
||||
// or if no acl is set, if all of it's relations are also valid
|
||||
validate_relations(relation, ctx)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ For implementation
|
|||
4. servers can synchronize with each other
|
||||
5. i can specify access control on events
|
||||
|
||||
This project is working on impl stage 4, currently.
|
||||
This project is working on impl stage 4/5, currently.
|
||||
|
||||
TODO: work out a proper api spec for blob servers and index servers
|
||||
|
||||
|
|
70
spec/render.ts
Normal file
70
spec/render.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
import * as marked from "npm:marked";
|
||||
|
||||
if (!Deno.args[0]) throw new Error("needs a file as cli arg");
|
||||
|
||||
const filename = Deno.args[0];
|
||||
const input = Deno.readTextFileSync(filename);
|
||||
const rendered = marked.lexer(input).map(renderBlock).filter(i => i);
|
||||
console.log(JSON.stringify({ doc: rendered, name: filename }));
|
||||
// console.log(rendered);
|
||||
|
||||
interface Token {
|
||||
type: string,
|
||||
text: string,
|
||||
tokens?: Array<Token>,
|
||||
[key: string]: any,
|
||||
}
|
||||
|
||||
function renderBlock(token: Token): any {
|
||||
switch (token.type) {
|
||||
case "paragraph": {
|
||||
return renderInline(token);
|
||||
}
|
||||
case "heading": {
|
||||
return { type: "header", level: token.depth, content: renderInline(token) };
|
||||
}
|
||||
case "list": {
|
||||
return {
|
||||
type: token.ordered ? "ol" : "ul",
|
||||
items: token.items.map(i => {
|
||||
if (i.tokens.length === 1) renderBlock(i.tokens[0]);
|
||||
return i.tokens.map(renderBlock);
|
||||
}),
|
||||
};
|
||||
}
|
||||
case "code": {
|
||||
return {
|
||||
type: "code",
|
||||
lang: token.lang,
|
||||
content: renderInline(token),
|
||||
};
|
||||
}
|
||||
case "space": {
|
||||
return null;
|
||||
}
|
||||
case "text": {
|
||||
return renderInline(token);
|
||||
}
|
||||
case "table": {
|
||||
return {
|
||||
type: "table",
|
||||
headers: token.header.map(renderInline),
|
||||
rows: token.rows.map(row => row.map(renderInline)),
|
||||
}
|
||||
}
|
||||
default: {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function renderInline(token: Token): string {
|
||||
const text = token.tokens ? token.tokens.map(renderInline).join("") : token.text;
|
||||
switch (token.type) {
|
||||
case "em": return `~italic{${text}}`;
|
||||
case "strong": return `~bold{${text}}`;
|
||||
case "link": return `~link{${text}}{${token.href}}`;
|
||||
case "codespan": return `~code{${text}}`;
|
||||
default: return `${text}`;
|
||||
}
|
||||
}
|
114
spec/spec.ts
114
spec/spec.ts
|
@ -1,114 +0,0 @@
|
|||
import type { Document } from "./scenes/Document/static";
|
||||
import { api } from "./lib/api"
|
||||
|
||||
const event = api.makeEvent("x.example", {
|
||||
hello: "world",
|
||||
}, {
|
||||
"sha224-123example789": { type: "frobnicates" },
|
||||
});
|
||||
|
||||
const doc: Document = [
|
||||
{
|
||||
type: "header",
|
||||
level: 1,
|
||||
content: "Welcome!"
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
content: [
|
||||
"ufh is a protocol for syncing and querying a distributed graph database."
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
content: [
|
||||
"A decent chunk of inspiration is taken from ",
|
||||
{
|
||||
text: "matrix",
|
||||
href: "https://matrix.org"
|
||||
},
|
||||
", ",
|
||||
{
|
||||
text: "ipfs",
|
||||
href: "https://ipfs.tech/"
|
||||
},
|
||||
", and ",
|
||||
{
|
||||
text: "perkeep",
|
||||
href: "https://perkeep.org/"
|
||||
},
|
||||
"."
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "header",
|
||||
level: 2,
|
||||
content: "Spec"
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
content: [
|
||||
"Everything in ufh is an ",
|
||||
{
|
||||
text: "object",
|
||||
bold: true
|
||||
},
|
||||
", which can be referenced with an immutable ",
|
||||
{
|
||||
text: "ref",
|
||||
bold: true
|
||||
},
|
||||
". The two main types of object are ",
|
||||
{
|
||||
text: "blob",
|
||||
bold: true
|
||||
},
|
||||
"s and ",
|
||||
{
|
||||
text: "event",
|
||||
bold: true
|
||||
},
|
||||
"s."
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "callout",
|
||||
is: "notice",
|
||||
content: [
|
||||
"a ref looks like ",
|
||||
{
|
||||
text: "sha224",
|
||||
color: "#9085f3",
|
||||
note: {
|
||||
doc: "hash",
|
||||
type: "inline"
|
||||
},
|
||||
code: "mono"
|
||||
},
|
||||
{
|
||||
text: "-",
|
||||
code: "mono"
|
||||
},
|
||||
{
|
||||
text: "784093e5719d1935d14...784eb1e332cf750d1a9",
|
||||
color: "#e66e82",
|
||||
note: {
|
||||
doc: "digest",
|
||||
type: "inline"
|
||||
},
|
||||
code: "mono"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
content: "Here's what an event looks like"
|
||||
},
|
||||
{
|
||||
type: "code",
|
||||
lang: "json",
|
||||
content: JSON.stringify(await event, null, 4),
|
||||
},
|
||||
];
|
||||
|
||||
export default { name: "ufh spec", doc }
|
1
spec/test.json
Normal file
1
spec/test.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -7,9 +7,7 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
async-trait = "0.1.68"
|
||||
axum = { version = "0.6.18", features = ["macros", "headers"] }
|
||||
flume = "0.10.14"
|
||||
futures-util = "0.3.28"
|
||||
serde = { version = "1.0.163", features = ["derive"] }
|
||||
serde_json = "1.0.96"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
import log from "./lib/log";
|
||||
import Clock from "./Clock.svelte";
|
||||
import Pins from "./Pins.svelte";
|
||||
import Prompt from "./popups/Prompt.svelte";
|
||||
|
||||
$: log.web("set state", $state);
|
||||
|
||||
|
@ -187,6 +188,10 @@
|
|||
>
|
||||
</div>
|
||||
</Popup>
|
||||
{:else if popup.type === "prompt"}
|
||||
<Popup on:close={() => popup.resolve(null)}>
|
||||
<Prompt {popup} />
|
||||
</Popup>
|
||||
{:else}
|
||||
<Popup>unknown popup</Popup>
|
||||
{/if}
|
||||
|
|
|
@ -45,7 +45,7 @@ export interface QueryOptions {
|
|||
type Relations = Record<ref, { type: string, key?: string }>;
|
||||
|
||||
type TypedEvents = {
|
||||
"x.user": { name: string },
|
||||
"x.user": { name: string, type: "node" | "user" | "bot" },
|
||||
"x.file": { chunks: Array<string>, name?: string },
|
||||
"x.redact": { reason?: string },
|
||||
"x.acl": {
|
||||
|
|
20
web/popups/Prompt.svelte
Normal file
20
web/popups/Prompt.svelte
Normal file
|
@ -0,0 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { state } from "../state";
|
||||
|
||||
export let popup: any;
|
||||
let input: string;
|
||||
|
||||
function exit(cancelled: boolean) {
|
||||
state.do("popup/close");
|
||||
popup.resolve(cancelled ? null : input);
|
||||
}
|
||||
</script>
|
||||
<div>{popup.question}</div>
|
||||
<form on:submit|preventDefault={() => exit(false)}>
|
||||
<input bind:value={input}>
|
||||
</form>
|
||||
<div style="margin-top: 1em; text-align: right">
|
||||
<button on:click={() => exit(true)}>cancel</button>
|
||||
<button on:click={() => exit(false)}>confirm</button>
|
||||
</div>
|
||||
|
|
@ -1,6 +1,41 @@
|
|||
<script lang="ts">
|
||||
import { api, base64 } from "../lib/api";
|
||||
import { query } from "../lib/util";
|
||||
import { state } from "../state";
|
||||
|
||||
const me = query({
|
||||
senders: [api.getUserId()],
|
||||
types: ["x.actor"],
|
||||
});
|
||||
|
||||
function prompt(question: string): Promise<string | null> {
|
||||
return new Promise(res => {
|
||||
state.do("popup/open", {
|
||||
type: "prompt",
|
||||
question,
|
||||
resolve: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function createUser() {
|
||||
const name = await prompt("username?");
|
||||
if (!name) return;
|
||||
api.createEvent("x.actor", { name, type: "user" });
|
||||
}
|
||||
</script>
|
||||
<div class="user">
|
||||
{#if $me[0]}
|
||||
{@const cont = $me[0].getContent()}
|
||||
user event: name={cont.name}, type={cont.type}
|
||||
<details>
|
||||
<summary>full event</summary>
|
||||
<pre><code>{JSON.stringify($me[0].toRaw(), null, 4)}</code></pre>
|
||||
</details>
|
||||
{:else}
|
||||
no user event <button on:click={createUser}>create</button>
|
||||
{/if}
|
||||
</div>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Server:</td>
|
||||
|
@ -43,6 +78,12 @@
|
|||
</tr>
|
||||
</table>
|
||||
<style lang="scss">
|
||||
.user {
|
||||
margin: 1em;
|
||||
padding: 1em;
|
||||
border: solid var(--borders) 1px;
|
||||
}
|
||||
|
||||
table {
|
||||
margin: 1em;
|
||||
|
||||
|
|
|
@ -66,11 +66,15 @@ pre, code {
|
|||
|
||||
&:not(.lang-mono) {
|
||||
background: var(--bg-secondary);
|
||||
padding: 0 2px;
|
||||
padding: 0 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
pre:not(.lang-mono) {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow-x: auto;
|
||||
padding: 4px;
|
||||
|
@ -78,7 +82,7 @@ pre {
|
|||
|
||||
table {
|
||||
border: solid var(--borders) 1px;
|
||||
border-radius: 4px;
|
||||
// border-radius: 4px;
|
||||
border-spacing: 0;
|
||||
|
||||
& > thead {
|
||||
|
|
|
@ -10,5 +10,6 @@ export type Popup =
|
|||
{ type: "edit", event: Event, panel: EditPanels } |
|
||||
{ type: "create" } |
|
||||
{ type: "confirm", question: string, resolve: (accepted: boolean) => void } |
|
||||
{ type: "prompt", question: string, resolve: (text: string | null) => void } |
|
||||
{ type: "text", text: string };
|
||||
|
||||
|
|
Loading…
Reference in a new issue