mirror of
https://git.asonix.dog/asonix/relay.git
synced 2024-11-25 02:51:12 +00:00
Update activitystreams
This commit is contained in:
parent
e65c21582c
commit
2bbcc82d9c
27 changed files with 334 additions and 366 deletions
312
Cargo.lock
generated
312
Cargo.lock
generated
|
@ -1,50 +1,26 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
|
||||||
name = "activitystreams"
|
|
||||||
version = "0.6.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "464cb473bfb402b857cc15b1153974c203a43f1485da4dda15cd17a738548958"
|
|
||||||
dependencies = [
|
|
||||||
"activitystreams-derive",
|
|
||||||
"chrono",
|
|
||||||
"mime",
|
|
||||||
"serde 1.0.111",
|
|
||||||
"serde_json",
|
|
||||||
"thiserror",
|
|
||||||
"url",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "activitystreams-derive"
|
|
||||||
version = "0.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c39ba5929399e9f921055bac76dd8f47419fa5b6b6da1ac4c1e82b94ed0ac7b4"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "activitystreams-ext"
|
name = "activitystreams-ext"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.asonix.dog/asonix/activitystreams-ext#e5c97f4ea9f60e49bc7ff27fb0fb515d3190fd25"
|
source = "git+https://git.asonix.dog/asonix/activitystreams-ext?branch=main#9acc466c7cb550ada31b669a1c47ea088f1c8471"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"activitystreams-new",
|
"activitystreams-new",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "activitystreams-new"
|
name = "activitystreams-new"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.asonix.dog/asonix/activitystreams-sketch#99c7e9aa5596eda846a1ebd5978ca72d11d4c08a"
|
source = "git+https://git.asonix.dog/asonix/activitystreams-sketch?branch=main#df49fcd1a756f2570651f82727c48ace66d9e8a3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"activitystreams",
|
"chrono",
|
||||||
"serde 1.0.111",
|
"mime",
|
||||||
|
"serde 1.0.113",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"typed-builder",
|
"thiserror",
|
||||||
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -97,7 +73,7 @@ dependencies = [
|
||||||
"actix-threadpool",
|
"actix-threadpool",
|
||||||
"actix-tls",
|
"actix-tls",
|
||||||
"actix-utils",
|
"actix-utils",
|
||||||
"base64 0.12.1",
|
"base64 0.12.2",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"brotli2",
|
"brotli2",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -122,7 +98,7 @@ dependencies = [
|
||||||
"pin-project",
|
"pin-project",
|
||||||
"rand",
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sha-1",
|
"sha-1",
|
||||||
|
@ -150,7 +126,7 @@ dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"log",
|
"log",
|
||||||
"regex",
|
"regex",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -296,7 +272,7 @@ dependencies = [
|
||||||
"pin-project",
|
"pin-project",
|
||||||
"regex",
|
"regex",
|
||||||
"rustls",
|
"rustls",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"socket2",
|
"socket2",
|
||||||
|
@ -324,7 +300,7 @@ checksum = "abb66d471f2af5a9ea7b48ea4456f117c56cd1b2348e52ae8d3bc95cddeebf4c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-http",
|
"actix-http",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
@ -340,9 +316,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "adler32"
|
name = "adler32"
|
||||||
version = "1.0.4"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
|
checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
|
@ -400,12 +376,9 @@ checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.4.12"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
|
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
|
||||||
dependencies = [
|
|
||||||
"nodrop",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-mutex"
|
name = "async-mutex"
|
||||||
|
@ -418,9 +391,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.35"
|
version = "0.1.36"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89cb5d814ab2a47fd66d3266e9efccb53ca4c740b7451043b8ffcf9a6208f3f8"
|
checksum = "a265e3abeffdce30b2e26b7a11b222fe37c6067404001b434101457d0385eb92"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -460,7 +433,7 @@ dependencies = [
|
||||||
"actix-http",
|
"actix-http",
|
||||||
"actix-rt",
|
"actix-rt",
|
||||||
"actix-service",
|
"actix-service",
|
||||||
"base64 0.12.1",
|
"base64 0.12.2",
|
||||||
"bytes",
|
"bytes",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
@ -469,7 +442,7 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rand",
|
"rand",
|
||||||
"rustls",
|
"rustls",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
]
|
]
|
||||||
|
@ -498,7 +471,7 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"rand",
|
"rand",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -517,7 +490,7 @@ dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"futures",
|
"futures",
|
||||||
"log",
|
"log",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -526,13 +499,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.48"
|
version = "0.3.49"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130"
|
checksum = "05100821de9e028f12ae3d189176b41ee198341eb8f369956407fea2f5cc666c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"addr2line",
|
"addr2line",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
"object",
|
"object",
|
||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
]
|
]
|
||||||
|
@ -551,9 +525,9 @@ checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.12.1"
|
version = "0.12.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42"
|
checksum = "e223af0dc48c96d4f8342ec01a4974f139df863896b316681efd36742f22cc67"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit-vec"
|
name = "bit-vec"
|
||||||
|
@ -588,7 +562,7 @@ dependencies = [
|
||||||
"block-padding",
|
"block-padding",
|
||||||
"byte-tools",
|
"byte-tools",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"generic-array 0.14.1",
|
"generic-array 0.14.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -646,9 +620,12 @@ checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "0.5.4"
|
version = "0.5.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1"
|
checksum = "118cf036fbb97d0816e3c34b2d7a1e8cfc60f68fcf63d550ddbe9bd5f59c213b"
|
||||||
|
dependencies = [
|
||||||
|
"loom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytestring"
|
name = "bytestring"
|
||||||
|
@ -678,8 +655,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
|
checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits 0.2.11",
|
"num-traits 0.2.12",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"time 0.1.43",
|
"time 0.1.43",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -716,7 +693,7 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"nom",
|
"nom",
|
||||||
"rust-ini",
|
"rust-ini",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde-hjson",
|
"serde-hjson",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"toml",
|
"toml",
|
||||||
|
@ -760,12 +737,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab6bffe714b6bb07e42f201352c34f51fefd355ace793f9e638ebd52d23f98d2"
|
checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
|
"maybe-uninit",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -799,7 +777,7 @@ dependencies = [
|
||||||
"config",
|
"config",
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -814,16 +792,16 @@ dependencies = [
|
||||||
"deadpool",
|
"deadpool",
|
||||||
"futures",
|
"futures",
|
||||||
"log",
|
"log",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-postgres",
|
"tokio-postgres",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_more"
|
name = "derive_more"
|
||||||
version = "0.99.7"
|
version = "0.99.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2127768764f1556535c01b5326ef94bd60ff08dcfbdc544d53e69ed155610f5d"
|
checksum = "bc655351f820d774679da6cdc23355a93de496867d8203496675162e17b1d671"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -845,7 +823,7 @@ version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array 0.14.1",
|
"generic-array 0.14.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -862,9 +840,9 @@ checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dtoa"
|
name = "dtoa"
|
||||||
version = "0.4.5"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3"
|
checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
|
@ -1094,6 +1072,19 @@ dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generator"
|
||||||
|
version = "0.6.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "add72f17bb81521258fcc8a7a3245b1e184e916bfbe34f0ea89558f440df5c68"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"rustc_version",
|
||||||
|
"winapi 0.3.8",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
|
@ -1105,11 +1096,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.1"
|
version = "0.14.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6d2664c2cf08049036f31015b04c6ac3671379a1d86f52ed2416893f16022deb"
|
checksum = "ac746a5f3bbfdadd6106868134545e684693d54d9d44f6e9588a7d54af0bf980"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1169,9 +1161,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.13"
|
version = "0.1.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
|
checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
@ -1240,7 +1232,7 @@ checksum = "60a0614ef2d44d570f78932a25cfa6975fa41d1f06f12c4b338e3f1ee1e3b6ab"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-http",
|
"actix-http",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"base64 0.12.1",
|
"base64 0.12.2",
|
||||||
"bytes",
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
"futures",
|
"futures",
|
||||||
|
@ -1317,9 +1309,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.5"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
|
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
|
@ -1357,13 +1349,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lexical-core"
|
name = "lexical-core"
|
||||||
version = "0.6.2"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7043aa5c05dd34fb73b47acb8c3708eac428de4545ea3682ed2f11293ebd890"
|
checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"rustc_version",
|
|
||||||
"ryu",
|
"ryu",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
@ -1415,10 +1407,21 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lru"
|
name = "loom"
|
||||||
version = "0.5.1"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28e0c685219cd60e49a2796bba7e4fe6523e10daca4fd721e84e7f905093d60c"
|
checksum = "4ecc775857611e1df29abba5c41355cdf540e7e9d4acfdf0f355eefee82330b7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"generator",
|
||||||
|
"scoped-tls",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lru"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "297efb9401445cf7b6986a583d7ac194023334b46b294ff7da0d36662c1251c2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
@ -1453,7 +1456,7 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"phf",
|
"phf",
|
||||||
"phf_codegen",
|
"phf_codegen",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"string_cache",
|
"string_cache",
|
||||||
|
@ -1485,6 +1488,12 @@ version = "0.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "maybe-uninit"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "md5"
|
name = "md5"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -1571,17 +1580,11 @@ version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nodrop"
|
|
||||||
version = "0.1.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "5.1.1"
|
version = "5.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6"
|
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lexical-core",
|
"lexical-core",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
@ -1596,7 +1599,7 @@ checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.0.0",
|
"autocfg 1.0.0",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits 0.2.11",
|
"num-traits 0.2.12",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1611,32 +1614,32 @@ dependencies = [
|
||||||
"libm",
|
"libm",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-iter",
|
"num-iter",
|
||||||
"num-traits 0.2.11",
|
"num-traits 0.2.12",
|
||||||
"rand",
|
"rand",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.42"
|
version = "0.1.43"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
|
checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.0.0",
|
"autocfg 1.0.0",
|
||||||
"num-traits 0.2.11",
|
"num-traits 0.2.12",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-iter"
|
name = "num-iter"
|
||||||
version = "0.1.40"
|
version = "0.1.41"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00"
|
checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.0.0",
|
"autocfg 1.0.0",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits 0.2.11",
|
"num-traits 0.2.12",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1647,7 +1650,7 @@ checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.0.0",
|
"autocfg 1.0.0",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits 0.2.11",
|
"num-traits 0.2.12",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1656,14 +1659,14 @@ version = "0.1.43"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-traits 0.2.11",
|
"num-traits 0.2.12",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.11"
|
version = "0.2.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.0.0",
|
"autocfg 1.0.0",
|
||||||
]
|
]
|
||||||
|
@ -1680,9 +1683,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.19.0"
|
version = "0.20.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2"
|
checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
|
@ -1777,18 +1780,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project"
|
name = "pin-project"
|
||||||
version = "0.4.20"
|
version = "0.4.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e75373ff9037d112bb19bc61333a06a159eaeb217660dcfbea7d88e1db823919"
|
checksum = "12e3a6cdbfe94a5e4572812a0201f8c0ed98c1c452c7b8563ce2276988ef9c17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pin-project-internal",
|
"pin-project-internal",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-internal"
|
name = "pin-project-internal"
|
||||||
version = "0.4.20"
|
version = "0.4.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "10b4b44893d3c370407a1d6a5cfde7c41ae0478e31c516c85f67eb3adc51be6d"
|
checksum = "6a0ffd45cf79d88737d7cc85bfd5d2894bee1139b356e616fe85dc389c61aaf7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1813,7 +1816,7 @@ version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f611afe4d1407ebe7f3ced1ffc66f730fac1b1c13085e230a8cdcb921e97710"
|
checksum = "3f611afe4d1407ebe7f3ced1ffc66f730fac1b1c13085e230a8cdcb921e97710"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.12.1",
|
"base64 0.12.2",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"bytes",
|
"bytes",
|
||||||
"fallible-iterator",
|
"fallible-iterator",
|
||||||
|
@ -1835,7 +1838,7 @@ dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"fallible-iterator",
|
"fallible-iterator",
|
||||||
"postgres-protocol",
|
"postgres-protocol",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
@ -1896,9 +1899,9 @@ checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-nested"
|
name = "proc-macro-nested"
|
||||||
version = "0.1.5"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0afe1bd463b9e9ed51d0e0f0b50b6b146aec855c56fd182bb242388710a9b6de"
|
checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
|
@ -2013,7 +2016,7 @@ dependencies = [
|
||||||
"async-mutex",
|
"async-mutex",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"background-jobs",
|
"background-jobs",
|
||||||
"base64 0.12.1",
|
"base64 0.12.2",
|
||||||
"bytes",
|
"bytes",
|
||||||
"config",
|
"config",
|
||||||
"deadpool",
|
"deadpool",
|
||||||
|
@ -2032,7 +2035,7 @@ dependencies = [
|
||||||
"rsa-magic-public-key",
|
"rsa-magic-public-key",
|
||||||
"rsa-pem",
|
"rsa-pem",
|
||||||
"ructe",
|
"ructe",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2 0.9.0",
|
"sha2 0.9.0",
|
||||||
"structopt",
|
"structopt",
|
||||||
|
@ -2055,9 +2058,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.16.14"
|
version = "0.16.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06b3fefa4f12272808f809a0af618501fdaba41a58963c5fb72238ab0be09603"
|
checksum = "952cd6b98c85bbc30efa1ba5783b8abf12fec8b3287ffa52605b9432313e34e4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -2080,7 +2083,7 @@ dependencies = [
|
||||||
"num-bigint-dig",
|
"num-bigint-dig",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-iter",
|
"num-iter",
|
||||||
"num-traits 0.2.11",
|
"num-traits 0.2.12",
|
||||||
"rand",
|
"rand",
|
||||||
"subtle 2.2.3",
|
"subtle 2.2.3",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
|
@ -2108,7 +2111,7 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-bigint-dig",
|
"num-bigint-dig",
|
||||||
"num-traits 0.2.11",
|
"num-traits 0.2.12",
|
||||||
"pem",
|
"pem",
|
||||||
"rsa",
|
"rsa",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -2125,7 +2128,7 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"nom",
|
"nom",
|
||||||
"num-rational",
|
"num-rational",
|
||||||
"num-traits 0.2.11",
|
"num-traits 0.2.12",
|
||||||
"rand",
|
"rand",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2135,7 +2138,7 @@ version = "0.11.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f615d1e172dcc01a7cd78c7f77f21a5669c6de4341548ad2e7764e9045d06657"
|
checksum = "f615d1e172dcc01a7cd78c7f77f21a5669c6de4341548ad2e7764e9045d06657"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.12.1",
|
"base64 0.12.2",
|
||||||
"bytecount",
|
"bytecount",
|
||||||
"itertools",
|
"itertools",
|
||||||
"md5",
|
"md5",
|
||||||
|
@ -2184,6 +2187,12 @@ version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scoped-tls"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -2223,9 +2232,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.111"
|
version = "1.0.113"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d"
|
checksum = "6135c78461981c79497158ef777264c51d9d0f4f3fc3a4d22b915900e42dac6a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
@ -2245,9 +2254,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.111"
|
version = "1.0.113"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
|
checksum = "93c5eaa17d0954cb481cdcfffe9d84fcfa7a1a9f2349271e678677be4c26ae31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -2262,7 +2271,7 @@ checksum = "ec2c5d7e739bc07a3e73381a39d61fdb5f671c60c1df26a130690665803d8226"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2282,7 +2291,7 @@ checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dtoa",
|
"dtoa",
|
||||||
"itoa",
|
"itoa",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2385,9 +2394,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "0.3.4"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3"
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stdweb"
|
name = "stdweb"
|
||||||
|
@ -2411,7 +2420,7 @@ checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
@ -2425,7 +2434,7 @@ dependencies = [
|
||||||
"base-x",
|
"base-x",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha1",
|
"sha1",
|
||||||
|
@ -2448,7 +2457,7 @@ dependencies = [
|
||||||
"new_debug_unreachable",
|
"new_debug_unreachable",
|
||||||
"phf_shared",
|
"phf_shared",
|
||||||
"precomputed-hash",
|
"precomputed-hash",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2481,9 +2490,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structopt"
|
name = "structopt"
|
||||||
version = "0.3.14"
|
version = "0.3.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef"
|
checksum = "de2f5e239ee807089b62adce73e48c625e0ed80df02c7ab3f068f5db5281065c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
@ -2492,9 +2501,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structopt-derive"
|
name = "structopt-derive"
|
||||||
version = "0.4.7"
|
version = "0.4.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a"
|
checksum = "510413f9de616762a4fbeab62509bf15c729603b72d7cd71280fbca431b1c118"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
|
@ -2580,18 +2589,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.19"
|
version = "1.0.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b13f926965ad00595dd129fa12823b04bbf866e9085ab0a5f2b05b850fbfc344"
|
checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.19"
|
version = "1.0.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479"
|
checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -2759,7 +2768,7 @@ version = "0.5.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
|
checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2811,17 +2820,6 @@ dependencies = [
|
||||||
"linked-hash-map 0.5.3",
|
"linked-hash-map 0.5.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typed-builder"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "85fc4459191c621a53ef6c6ca5642e6e0e5ccc61f3e5b8ad6b6ab5317f0200fb"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.12.0"
|
version = "1.12.0"
|
||||||
|
@ -2839,11 +2837,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-normalization"
|
name = "unicode-normalization"
|
||||||
version = "0.1.12"
|
version = "0.1.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4"
|
checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"smallvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2894,7 +2892,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
|
checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
"serde 1.0.111",
|
"serde 1.0.113",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -17,8 +17,8 @@ anyhow = "1.0"
|
||||||
actix-rt = "1.1.1"
|
actix-rt = "1.1.1"
|
||||||
actix-web = { version = "3.0.0-alpha.2", features = ["rustls"] }
|
actix-web = { version = "3.0.0-alpha.2", features = ["rustls"] }
|
||||||
actix-webfinger = "0.3.0-alpha.6"
|
actix-webfinger = "0.3.0-alpha.6"
|
||||||
activitystreams-new = { git = "https://git.asonix.dog/asonix/activitystreams-sketch" }
|
activitystreams-new = { git = "https://git.asonix.dog/asonix/activitystreams-sketch", branch = "main" }
|
||||||
activitystreams-ext = { git = "https://git.asonix.dog/asonix/activitystreams-ext" }
|
activitystreams-ext = { git = "https://git.asonix.dog/asonix/activitystreams-ext", branch = "main" }
|
||||||
ammonia = "3.1.0"
|
ammonia = "3.1.0"
|
||||||
async-mutex = "1.0.1"
|
async-mutex = "1.0.1"
|
||||||
async-trait = "0.1.24"
|
async-trait = "0.1.24"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{data::ActorCache, error::MyError, middleware::MyVerify, requests::Requests};
|
use crate::{data::ActorCache, error::MyError, middleware::MyVerify, requests::Requests};
|
||||||
use activitystreams_new::{primitives::XsdAnyUri, uri};
|
use activitystreams_new::{uri, url::Url};
|
||||||
use config::Environment;
|
use config::Environment;
|
||||||
use http_signature_normalization_actix::prelude::{VerifyDigest, VerifySignature};
|
use http_signature_normalization_actix::prelude::{VerifyDigest, VerifySignature};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
@ -33,7 +33,7 @@ pub struct Config {
|
||||||
pretty_log: bool,
|
pretty_log: bool,
|
||||||
publish_blocks: bool,
|
publish_blocks: bool,
|
||||||
max_connections: usize,
|
max_connections: usize,
|
||||||
base_uri: XsdAnyUri,
|
base_uri: Url,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum UrlKind {
|
pub enum UrlKind {
|
||||||
|
@ -157,9 +157,8 @@ impl Config {
|
||||||
"https://git.asonix.dog/asonix/ap-relay".to_owned()
|
"https://git.asonix.dog/asonix/ap-relay".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_url(&self, kind: UrlKind) -> XsdAnyUri {
|
pub fn generate_url(&self, kind: UrlKind) -> Url {
|
||||||
let mut uri = self.base_uri.clone();
|
let mut url = self.base_uri.clone();
|
||||||
let url = uri.as_url_mut();
|
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
UrlKind::Activity => url.set_path(&format!("activity/{}", Uuid::new_v4())),
|
UrlKind::Activity => url.set_path(&format!("activity/{}", Uuid::new_v4())),
|
||||||
|
@ -177,6 +176,6 @@ impl Config {
|
||||||
UrlKind::Outbox => url.set_path("outbox"),
|
UrlKind::Outbox => url.set_path("outbox"),
|
||||||
};
|
};
|
||||||
|
|
||||||
uri
|
url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{apub::AcceptedActors, db::Db, error::MyError, requests::Requests};
|
use crate::{apub::AcceptedActors, db::Db, error::MyError, requests::Requests};
|
||||||
use activitystreams_new::{prelude::*, primitives::XsdAnyUri, uri};
|
use activitystreams_new::{prelude::*, primitives::XsdAnyUri, uri, url::Url};
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::{collections::HashSet, sync::Arc, time::Duration};
|
use std::{collections::HashSet, sync::Arc, time::Duration};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
@ -32,8 +32,8 @@ impl<T> MaybeCached<T> {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ActorCache {
|
pub struct ActorCache {
|
||||||
db: Db,
|
db: Db,
|
||||||
cache: Arc<RwLock<TtlCache<XsdAnyUri, Actor>>>,
|
cache: Arc<RwLock<TtlCache<Url, Actor>>>,
|
||||||
following: Arc<RwLock<HashSet<XsdAnyUri>>>,
|
following: Arc<RwLock<HashSet<Url>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActorCache {
|
impl ActorCache {
|
||||||
|
@ -49,43 +49,25 @@ impl ActorCache {
|
||||||
cache
|
cache
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_following(&self, id: &XsdAnyUri) -> bool {
|
pub async fn is_following(&self, id: &Url) -> bool {
|
||||||
self.following.read().await.contains(id)
|
self.following.read().await.contains(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_no_cache(
|
pub async fn get_no_cache(&self, id: &Url, requests: &Requests) -> Result<Actor, MyError> {
|
||||||
&self,
|
|
||||||
id: &XsdAnyUri,
|
|
||||||
requests: &Requests,
|
|
||||||
) -> Result<Actor, MyError> {
|
|
||||||
let accepted_actor = requests.fetch::<AcceptedActors>(id.as_str()).await?;
|
let accepted_actor = requests.fetch::<AcceptedActors>(id.as_str()).await?;
|
||||||
|
|
||||||
let input_host = id.as_url().host();
|
let input_domain = id.domain().ok_or(MyError::MissingDomain)?;
|
||||||
let accepted_actor_id = accepted_actor.id().ok_or(MyError::MissingId)?;
|
let accepted_actor_id = accepted_actor
|
||||||
let actor_host = accepted_actor_id.as_url().host();
|
.id(&input_domain)?
|
||||||
let inbox_host = get_inbox(&accepted_actor).as_url().host();
|
.ok_or(MyError::MissingId)?;
|
||||||
|
|
||||||
if input_host != actor_host {
|
let inbox = get_inbox(&accepted_actor)?.clone();
|
||||||
let input_host = input_host.map(|h| h.to_string()).unwrap_or_default();
|
|
||||||
let actor_host = actor_host.map(|h| h.to_string()).unwrap_or_default();
|
|
||||||
|
|
||||||
return Err(MyError::HostMismatch(input_host, actor_host));
|
|
||||||
}
|
|
||||||
|
|
||||||
if actor_host != inbox_host {
|
|
||||||
let actor_host = actor_host.map(|h| h.to_string()).unwrap_or_default();
|
|
||||||
let inbox_host = inbox_host.map(|h| h.to_string()).unwrap_or_default();
|
|
||||||
|
|
||||||
return Err(MyError::HostMismatch(actor_host, inbox_host));
|
|
||||||
}
|
|
||||||
|
|
||||||
let inbox = get_inbox(&accepted_actor).clone();
|
|
||||||
|
|
||||||
let actor = Actor {
|
let actor = Actor {
|
||||||
id: accepted_actor_id.clone(),
|
id: accepted_actor_id.clone().into(),
|
||||||
public_key: accepted_actor.ext_one.public_key.public_key_pem,
|
public_key: accepted_actor.ext_one.public_key.public_key_pem,
|
||||||
public_key_id: accepted_actor.ext_one.public_key.id,
|
public_key_id: accepted_actor.ext_one.public_key.id,
|
||||||
inbox,
|
inbox: inbox.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.cache
|
self.cache
|
||||||
|
@ -99,11 +81,7 @@ impl ActorCache {
|
||||||
Ok(actor)
|
Ok(actor)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get(
|
pub async fn get(&self, id: &Url, requests: &Requests) -> Result<MaybeCached<Actor>, MyError> {
|
||||||
&self,
|
|
||||||
id: &XsdAnyUri,
|
|
||||||
requests: &Requests,
|
|
||||||
) -> Result<MaybeCached<Actor>, MyError> {
|
|
||||||
if let Some(actor) = self.cache.read().await.get(id) {
|
if let Some(actor) = self.cache.read().await.get(id) {
|
||||||
return Ok(MaybeCached::Cached(actor.clone()));
|
return Ok(MaybeCached::Cached(actor.clone()));
|
||||||
}
|
}
|
||||||
|
@ -125,11 +103,11 @@ impl ActorCache {
|
||||||
self.save(actor.clone()).await
|
self.save(actor.clone()).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn cache_follower(&self, id: XsdAnyUri) {
|
pub async fn cache_follower(&self, id: Url) {
|
||||||
self.following.write().await.insert(id);
|
self.following.write().await.insert(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn bust_follower(&self, id: &XsdAnyUri) {
|
pub async fn bust_follower(&self, id: &Url) {
|
||||||
self.following.write().await.remove(id);
|
self.following.write().await.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +152,7 @@ impl ActorCache {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn lookup(&self, id: &XsdAnyUri) -> Result<Option<Actor>, MyError> {
|
async fn lookup(&self, id: &Url) -> Result<Option<Actor>, MyError> {
|
||||||
let row_opt = self
|
let row_opt = self
|
||||||
.db
|
.db
|
||||||
.pool()
|
.pool()
|
||||||
|
@ -203,10 +181,10 @@ impl ActorCache {
|
||||||
let public_key_id: String = row.try_get(2)?;
|
let public_key_id: String = row.try_get(2)?;
|
||||||
|
|
||||||
Ok(Some(Actor {
|
Ok(Some(Actor {
|
||||||
id: id.clone(),
|
id: id.clone().into(),
|
||||||
inbox: uri!(inbox),
|
inbox: uri!(inbox).into(),
|
||||||
public_key: row.try_get(1)?,
|
public_key: row.try_get(1)?,
|
||||||
public_key_id: uri!(public_key_id),
|
public_key_id: uri!(public_key_id).into(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,12 +240,7 @@ impl ActorCache {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update(
|
async fn update(&self, id: &Url, public_key: &str, public_key_id: &Url) -> Result<(), MyError> {
|
||||||
&self,
|
|
||||||
id: &XsdAnyUri,
|
|
||||||
public_key: &str,
|
|
||||||
public_key_id: &XsdAnyUri,
|
|
||||||
) -> Result<(), MyError> {
|
|
||||||
self.db
|
self.db
|
||||||
.pool()
|
.pool()
|
||||||
.get()
|
.get()
|
||||||
|
@ -335,11 +308,11 @@ impl ActorCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_inbox(actor: &AcceptedActors) -> &XsdAnyUri {
|
fn get_inbox(actor: &AcceptedActors) -> Result<&Url, MyError> {
|
||||||
actor
|
Ok(actor
|
||||||
.endpoints()
|
.endpoints()?
|
||||||
.and_then(|e| e.shared_inbox.as_ref())
|
.and_then(|e| e.shared_inbox)
|
||||||
.unwrap_or(actor.inbox())
|
.unwrap_or(actor.inbox()?))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{db::Db, error::MyError};
|
use crate::{db::Db, error::MyError};
|
||||||
use activitystreams_new::primitives::XsdAnyUri;
|
use activitystreams_new::url::Url;
|
||||||
use async_mutex::Mutex;
|
use async_mutex::Mutex;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::join;
|
use futures::join;
|
||||||
|
@ -14,8 +14,8 @@ static MEDIA_DURATION: Duration = Duration::from_secs(60 * 60 * 24 * 2);
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Media {
|
pub struct Media {
|
||||||
db: Db,
|
db: Db,
|
||||||
inverse: Arc<Mutex<HashMap<XsdAnyUri, Uuid>>>,
|
inverse: Arc<Mutex<HashMap<Url, Uuid>>>,
|
||||||
url_cache: Arc<Mutex<LruCache<Uuid, XsdAnyUri>>>,
|
url_cache: Arc<Mutex<LruCache<Uuid, Url>>>,
|
||||||
byte_cache: Arc<RwLock<TtlCache<Uuid, (String, Bytes)>>>,
|
byte_cache: Arc<RwLock<TtlCache<Uuid, (String, Bytes)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ impl Media {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_uuid(&self, url: &XsdAnyUri) -> Result<Option<Uuid>, MyError> {
|
pub async fn get_uuid(&self, url: &Url) -> Result<Option<Uuid>, MyError> {
|
||||||
let res = self.inverse.lock().await.get(url).cloned();
|
let res = self.inverse.lock().await.get(url).cloned();
|
||||||
let uuid = match res {
|
let uuid = match res {
|
||||||
Some(uuid) => uuid,
|
Some(uuid) => uuid,
|
||||||
|
@ -90,7 +90,7 @@ impl Media {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_url(&self, uuid: Uuid) -> Result<Option<XsdAnyUri>, MyError> {
|
pub async fn get_url(&self, uuid: Uuid) -> Result<Option<Url>, MyError> {
|
||||||
if let Some(url) = self.url_cache.lock().await.get(&uuid).cloned() {
|
if let Some(url) = self.url_cache.lock().await.get(&uuid).cloned() {
|
||||||
return Ok(Some(url));
|
return Ok(Some(url));
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ impl Media {
|
||||||
|
|
||||||
if let Some(row) = row_opt {
|
if let Some(row) = row_opt {
|
||||||
let url: String = row.try_get(0)?;
|
let url: String = row.try_get(0)?;
|
||||||
let url: XsdAnyUri = url.parse()?;
|
let url: Url = url.parse()?;
|
||||||
return Ok(Some(url));
|
return Ok(Some(url));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ impl Media {
|
||||||
self.byte_cache.read().await.get(&uuid).cloned()
|
self.byte_cache.read().await.get(&uuid).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn store_url(&self, url: &XsdAnyUri) -> Result<Uuid, MyError> {
|
pub async fn store_url(&self, url: &Url) -> Result<Uuid, MyError> {
|
||||||
let uuid = Uuid::new_v4();
|
let uuid = Uuid::new_v4();
|
||||||
|
|
||||||
let (_, _, res) = join!(
|
let (_, _, res) = join!(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{db::Db, error::MyError};
|
use crate::{db::Db, error::MyError};
|
||||||
use activitystreams_new::{primitives::XsdAnyUri, uri};
|
use activitystreams_new::{primitives::XsdAnyUri, uri, url::Url};
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
|
@ -10,13 +10,13 @@ use tokio::sync::RwLock;
|
||||||
use tokio_postgres::types::Json;
|
use tokio_postgres::types::Json;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub type ListenersCache = Arc<RwLock<HashSet<XsdAnyUri>>>;
|
pub type ListenersCache = Arc<RwLock<HashSet<Url>>>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct NodeCache {
|
pub struct NodeCache {
|
||||||
db: Db,
|
db: Db,
|
||||||
listeners: ListenersCache,
|
listeners: ListenersCache,
|
||||||
nodes: Arc<RwLock<HashMap<XsdAnyUri, Node>>>,
|
nodes: Arc<RwLock<HashMap<Url, Node>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeCache {
|
impl NodeCache {
|
||||||
|
@ -45,7 +45,7 @@ impl NodeCache {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_nodeinfo_outdated(&self, listener: &XsdAnyUri) -> bool {
|
pub async fn is_nodeinfo_outdated(&self, listener: &Url) -> bool {
|
||||||
let read_guard = self.nodes.read().await;
|
let read_guard = self.nodes.read().await;
|
||||||
|
|
||||||
let node = match read_guard.get(listener) {
|
let node = match read_guard.get(listener) {
|
||||||
|
@ -65,7 +65,7 @@ impl NodeCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_contact_outdated(&self, listener: &XsdAnyUri) -> bool {
|
pub async fn is_contact_outdated(&self, listener: &Url) -> bool {
|
||||||
let read_guard = self.nodes.read().await;
|
let read_guard = self.nodes.read().await;
|
||||||
|
|
||||||
let node = match read_guard.get(listener) {
|
let node = match read_guard.get(listener) {
|
||||||
|
@ -85,7 +85,7 @@ impl NodeCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_instance_outdated(&self, listener: &XsdAnyUri) -> bool {
|
pub async fn is_instance_outdated(&self, listener: &Url) -> bool {
|
||||||
let read_guard = self.nodes.read().await;
|
let read_guard = self.nodes.read().await;
|
||||||
|
|
||||||
let node = match read_guard.get(listener) {
|
let node = match read_guard.get(listener) {
|
||||||
|
@ -196,7 +196,7 @@ impl NodeCache {
|
||||||
|
|
||||||
pub async fn set_info(
|
pub async fn set_info(
|
||||||
&self,
|
&self,
|
||||||
listener: &XsdAnyUri,
|
listener: &Url,
|
||||||
software: String,
|
software: String,
|
||||||
version: String,
|
version: String,
|
||||||
reg: bool,
|
reg: bool,
|
||||||
|
@ -221,7 +221,7 @@ impl NodeCache {
|
||||||
|
|
||||||
pub async fn set_instance(
|
pub async fn set_instance(
|
||||||
&self,
|
&self,
|
||||||
listener: &XsdAnyUri,
|
listener: &Url,
|
||||||
title: String,
|
title: String,
|
||||||
description: String,
|
description: String,
|
||||||
version: String,
|
version: String,
|
||||||
|
@ -248,11 +248,11 @@ impl NodeCache {
|
||||||
|
|
||||||
pub async fn set_contact(
|
pub async fn set_contact(
|
||||||
&self,
|
&self,
|
||||||
listener: &XsdAnyUri,
|
listener: &Url,
|
||||||
username: String,
|
username: String,
|
||||||
display_name: String,
|
display_name: String,
|
||||||
url: XsdAnyUri,
|
url: Url,
|
||||||
avatar: XsdAnyUri,
|
avatar: Url,
|
||||||
) -> Result<(), MyError> {
|
) -> Result<(), MyError> {
|
||||||
if !self.listeners.read().await.contains(listener) {
|
if !self.listeners.read().await.contains(listener) {
|
||||||
let mut nodes = self.nodes.write().await;
|
let mut nodes = self.nodes.write().await;
|
||||||
|
@ -272,7 +272,7 @@ impl NodeCache {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn save(&self, listener: &XsdAnyUri, node: &Node) -> Result<(), MyError> {
|
pub async fn save(&self, listener: &Url, node: &Node) -> Result<(), MyError> {
|
||||||
let row_opt = self
|
let row_opt = self
|
||||||
.db
|
.db
|
||||||
.pool()
|
.pool()
|
||||||
|
@ -328,21 +328,20 @@ impl NodeCache {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Node {
|
pub struct Node {
|
||||||
pub base: XsdAnyUri,
|
pub base: Url,
|
||||||
pub info: Option<Info>,
|
pub info: Option<Info>,
|
||||||
pub instance: Option<Instance>,
|
pub instance: Option<Instance>,
|
||||||
pub contact: Option<Contact>,
|
pub contact: Option<Contact>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
pub fn new(mut uri: XsdAnyUri) -> Self {
|
pub fn new(mut url: Url) -> Self {
|
||||||
let url = uri.as_mut();
|
|
||||||
url.set_fragment(None);
|
url.set_fragment(None);
|
||||||
url.set_query(None);
|
url.set_query(None);
|
||||||
url.set_path("");
|
url.set_path("");
|
||||||
|
|
||||||
Node {
|
Node {
|
||||||
base: uri,
|
base: url,
|
||||||
info: None,
|
info: None,
|
||||||
instance: None,
|
instance: None,
|
||||||
contact: None,
|
contact: None,
|
||||||
|
@ -382,14 +381,14 @@ impl Node {
|
||||||
&mut self,
|
&mut self,
|
||||||
username: String,
|
username: String,
|
||||||
display_name: String,
|
display_name: String,
|
||||||
url: XsdAnyUri,
|
url: Url,
|
||||||
avatar: XsdAnyUri,
|
avatar: Url,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.contact = Some(Contact {
|
self.contact = Some(Contact {
|
||||||
username,
|
username,
|
||||||
display_name,
|
display_name,
|
||||||
url,
|
url: url.into(),
|
||||||
avatar,
|
avatar: avatar.into(),
|
||||||
updated: SystemTime::now(),
|
updated: SystemTime::now(),
|
||||||
});
|
});
|
||||||
self
|
self
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
error::MyError,
|
error::MyError,
|
||||||
requests::Requests,
|
requests::Requests,
|
||||||
};
|
};
|
||||||
use activitystreams_new::primitives::XsdAnyUri;
|
use activitystreams_new::url::Url;
|
||||||
use actix_rt::{
|
use actix_rt::{
|
||||||
spawn,
|
spawn,
|
||||||
time::{interval_at, Instant},
|
time::{interval_at, Instant},
|
||||||
|
@ -24,10 +24,10 @@ pub struct State {
|
||||||
pub public_key: RSAPublicKey,
|
pub public_key: RSAPublicKey,
|
||||||
private_key: RSAPrivateKey,
|
private_key: RSAPrivateKey,
|
||||||
config: Config,
|
config: Config,
|
||||||
actor_id_cache: Arc<RwLock<LruCache<XsdAnyUri, XsdAnyUri>>>,
|
actor_id_cache: Arc<RwLock<LruCache<Url, Url>>>,
|
||||||
blocks: Arc<RwLock<HashSet<String>>>,
|
blocks: Arc<RwLock<HashSet<String>>>,
|
||||||
whitelists: Arc<RwLock<HashSet<String>>>,
|
whitelists: Arc<RwLock<HashSet<String>>>,
|
||||||
listeners: Arc<RwLock<HashSet<XsdAnyUri>>>,
|
listeners: Arc<RwLock<HashSet<Url>>>,
|
||||||
node_cache: NodeCache,
|
node_cache: NodeCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,11 +57,11 @@ impl State {
|
||||||
self.blocks.write().await.remove(block);
|
self.blocks.write().await.remove(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn bust_listener(&self, inbox: &XsdAnyUri) {
|
pub async fn bust_listener(&self, inbox: &Url) {
|
||||||
self.listeners.write().await.remove(inbox);
|
self.listeners.write().await.remove(inbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn listeners(&self) -> Vec<XsdAnyUri> {
|
pub async fn listeners(&self) -> Vec<Url> {
|
||||||
self.listeners.read().await.iter().cloned().collect()
|
self.listeners.read().await.iter().cloned().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,13 +69,13 @@ impl State {
|
||||||
self.blocks.read().await.iter().cloned().collect()
|
self.blocks.read().await.iter().cloned().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn listeners_without(&self, inbox: &XsdAnyUri, domain: &str) -> Vec<XsdAnyUri> {
|
pub async fn listeners_without(&self, inbox: &Url, domain: &str) -> Vec<Url> {
|
||||||
self.listeners
|
self.listeners
|
||||||
.read()
|
.read()
|
||||||
.await
|
.await
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|listener| {
|
.filter_map(|listener| {
|
||||||
if let Some(dom) = listener.as_url().domain() {
|
if let Some(dom) = listener.domain() {
|
||||||
if listener != inbox && dom != domain {
|
if listener != inbox && dom != domain {
|
||||||
return Some(listener.clone());
|
return Some(listener.clone());
|
||||||
}
|
}
|
||||||
|
@ -86,35 +86,35 @@ impl State {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_whitelisted(&self, actor_id: &XsdAnyUri) -> bool {
|
pub async fn is_whitelisted(&self, actor_id: &Url) -> bool {
|
||||||
if !self.config.whitelist_mode() {
|
if !self.config.whitelist_mode() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(domain) = actor_id.as_url().domain() {
|
if let Some(domain) = actor_id.domain() {
|
||||||
return self.whitelists.read().await.contains(domain);
|
return self.whitelists.read().await.contains(domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_blocked(&self, actor_id: &XsdAnyUri) -> bool {
|
pub async fn is_blocked(&self, actor_id: &Url) -> bool {
|
||||||
if let Some(domain) = actor_id.as_url().domain() {
|
if let Some(domain) = actor_id.domain() {
|
||||||
return self.blocks.read().await.contains(domain);
|
return self.blocks.read().await.contains(domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_listener(&self, actor_id: &XsdAnyUri) -> bool {
|
pub async fn is_listener(&self, actor_id: &Url) -> bool {
|
||||||
self.listeners.read().await.contains(actor_id)
|
self.listeners.read().await.contains(actor_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_cached(&self, object_id: &XsdAnyUri) -> bool {
|
pub async fn is_cached(&self, object_id: &Url) -> bool {
|
||||||
self.actor_id_cache.read().await.contains(object_id)
|
self.actor_id_cache.read().await.contains(object_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn cache(&self, object_id: XsdAnyUri, actor_id: XsdAnyUri) {
|
pub async fn cache(&self, object_id: Url, actor_id: Url) {
|
||||||
self.actor_id_cache.write().await.put(object_id, actor_id);
|
self.actor_id_cache.write().await.put(object_id, actor_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ impl State {
|
||||||
self.whitelists.write().await.insert(host);
|
self.whitelists.write().await.insert(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn cache_listener(&self, listener: XsdAnyUri) {
|
pub async fn cache_listener(&self, listener: Url) {
|
||||||
self.listeners.write().await.insert(listener);
|
self.listeners.write().await.insert(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::error::MyError;
|
use crate::error::MyError;
|
||||||
use activitystreams_new::primitives::XsdAnyUri;
|
use activitystreams_new::url::Url;
|
||||||
use deadpool_postgres::{Manager, Pool};
|
use deadpool_postgres::{Manager, Pool};
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use rsa::RSAPrivateKey;
|
use rsa::RSAPrivateKey;
|
||||||
|
@ -32,7 +32,7 @@ impl Db {
|
||||||
&self.pool
|
&self.pool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn remove_listener(&self, inbox: XsdAnyUri) -> Result<(), MyError> {
|
pub async fn remove_listener(&self, inbox: Url) -> Result<(), MyError> {
|
||||||
info!("DELETE FROM listeners WHERE actor_id = {};", inbox.as_str());
|
info!("DELETE FROM listeners WHERE actor_id = {};", inbox.as_str());
|
||||||
self.pool
|
self.pool
|
||||||
.get()
|
.get()
|
||||||
|
@ -46,7 +46,7 @@ impl Db {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn add_listener(&self, inbox: XsdAnyUri) -> Result<(), MyError> {
|
pub async fn add_listener(&self, inbox: Url) -> Result<(), MyError> {
|
||||||
info!(
|
info!(
|
||||||
"INSERT INTO listeners (actor_id, created_at) VALUES ($1::TEXT, 'now'); [{}]",
|
"INSERT INTO listeners (actor_id, created_at) VALUES ($1::TEXT, 'now'); [{}]",
|
||||||
inbox.as_str(),
|
inbox.as_str(),
|
||||||
|
@ -129,7 +129,7 @@ impl Db {
|
||||||
parse_rows(rows)
|
parse_rows(rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn hydrate_listeners(&self) -> Result<HashSet<XsdAnyUri>, MyError> {
|
pub async fn hydrate_listeners(&self) -> Result<HashSet<Url>, MyError> {
|
||||||
info!("SELECT actor_id FROM listeners");
|
info!("SELECT actor_id FROM listeners");
|
||||||
let rows = self
|
let rows = self
|
||||||
.pool
|
.pool
|
||||||
|
|
11
src/error.rs
11
src/error.rs
|
@ -1,4 +1,4 @@
|
||||||
use activitystreams_new::primitives::XsdAnyUriError;
|
use activitystreams_new::{error::DomainError, url::ParseError};
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
error::{BlockingError, ResponseError},
|
error::{BlockingError, ResponseError},
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
|
@ -25,7 +25,7 @@ pub enum MyError {
|
||||||
Key(#[from] KeyError),
|
Key(#[from] KeyError),
|
||||||
|
|
||||||
#[error("Couldn't parse URI, {0}")]
|
#[error("Couldn't parse URI, {0}")]
|
||||||
Uri(#[from] XsdAnyUriError),
|
Uri(#[from] ParseError),
|
||||||
|
|
||||||
#[error("Couldn't perform IO, {0}")]
|
#[error("Couldn't perform IO, {0}")]
|
||||||
Io(#[from] Error),
|
Io(#[from] Error),
|
||||||
|
@ -69,8 +69,8 @@ pub enum MyError {
|
||||||
#[error("Too many CPUs, {0}")]
|
#[error("Too many CPUs, {0}")]
|
||||||
CpuCount(#[from] std::num::TryFromIntError),
|
CpuCount(#[from] std::num::TryFromIntError),
|
||||||
|
|
||||||
#[error("Hosts don't match, {0}, {1}")]
|
#[error("{0}")]
|
||||||
HostMismatch(String, String),
|
HostMismatch(#[from] DomainError),
|
||||||
|
|
||||||
#[error("Invalid or missing content type")]
|
#[error("Invalid or missing content type")]
|
||||||
ContentType,
|
ContentType,
|
||||||
|
@ -108,6 +108,9 @@ pub enum MyError {
|
||||||
#[error("Input is missing a 'id' field")]
|
#[error("Input is missing a 'id' field")]
|
||||||
MissingId,
|
MissingId,
|
||||||
|
|
||||||
|
#[error("Url is missing a domain")]
|
||||||
|
MissingDomain,
|
||||||
|
|
||||||
#[error("URI is missing domain field")]
|
#[error("URI is missing domain field")]
|
||||||
Domain,
|
Domain,
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
DeliverMany, JobState,
|
DeliverMany, JobState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use activitystreams_new::{activity::Announce as AsAnnounce, primitives::XsdAnyUri};
|
use activitystreams_new::{activity::Announce as AsAnnounce, primitives::XsdAnyUri, url::Url};
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
|
||||||
|
@ -18,8 +18,11 @@ pub struct Announce {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Announce {
|
impl Announce {
|
||||||
pub fn new(object_id: XsdAnyUri, actor: Actor) -> Self {
|
pub fn new(object_id: Url, actor: Actor) -> Self {
|
||||||
Announce { object_id, actor }
|
Announce {
|
||||||
|
object_id: object_id.into(),
|
||||||
|
actor,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn perform(self, state: JobState) -> Result<(), anyhow::Error> {
|
async fn perform(self, state: JobState) -> Result<(), anyhow::Error> {
|
||||||
|
@ -31,7 +34,10 @@ impl Announce {
|
||||||
.job_server
|
.job_server
|
||||||
.queue(DeliverMany::new(inboxes, announce)?)?;
|
.queue(DeliverMany::new(inboxes, announce)?)?;
|
||||||
|
|
||||||
state.state.cache(self.object_id, activity_id).await;
|
state
|
||||||
|
.state
|
||||||
|
.cache(self.object_id.into_inner(), activity_id)
|
||||||
|
.await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +45,8 @@ impl Announce {
|
||||||
// Generate a type that says "Look at this object"
|
// Generate a type that says "Look at this object"
|
||||||
fn generate_announce(
|
fn generate_announce(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
activity_id: &XsdAnyUri,
|
activity_id: &Url,
|
||||||
object_id: &XsdAnyUri,
|
object_id: &Url,
|
||||||
) -> Result<AsAnnounce, MyError> {
|
) -> Result<AsAnnounce, MyError> {
|
||||||
let announce = AsAnnounce::new(config.generate_url(UrlKind::Actor), object_id.clone());
|
let announce = AsAnnounce::new(config.generate_url(UrlKind::Actor), object_id.clone());
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
use activitystreams_new::{
|
use activitystreams_new::{
|
||||||
activity::{Accept as AsAccept, Follow as AsFollow},
|
activity::{Accept as AsAccept, Follow as AsFollow},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
primitives::XsdAnyUri,
|
url::Url,
|
||||||
};
|
};
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
@ -31,7 +31,10 @@ impl Follow {
|
||||||
|
|
||||||
async fn perform(self, state: JobState) -> Result<(), anyhow::Error> {
|
async fn perform(self, state: JobState) -> Result<(), anyhow::Error> {
|
||||||
if !self.is_listener {
|
if !self.is_listener {
|
||||||
state.db.add_listener(self.actor.inbox.clone()).await?;
|
state
|
||||||
|
.db
|
||||||
|
.add_listener(self.actor.inbox.clone().into_inner())
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
let my_id = state.config.generate_url(UrlKind::Actor);
|
let my_id = state.config.generate_url(UrlKind::Actor);
|
||||||
|
|
||||||
|
@ -48,7 +51,7 @@ impl Follow {
|
||||||
let accept = generate_accept_follow(
|
let accept = generate_accept_follow(
|
||||||
&state.config,
|
&state.config,
|
||||||
&self.actor.id,
|
&self.actor.id,
|
||||||
self.input.id().ok_or(MyError::MissingId)?,
|
self.input.id_unchecked().ok_or(MyError::MissingId)?,
|
||||||
&my_id,
|
&my_id,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -60,11 +63,7 @@ impl Follow {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a type that says "I want to follow you"
|
// Generate a type that says "I want to follow you"
|
||||||
fn generate_follow(
|
fn generate_follow(config: &Config, actor_id: &Url, my_id: &Url) -> Result<AsFollow, MyError> {
|
||||||
config: &Config,
|
|
||||||
actor_id: &XsdAnyUri,
|
|
||||||
my_id: &XsdAnyUri,
|
|
||||||
) -> Result<AsFollow, MyError> {
|
|
||||||
let follow = AsFollow::new(my_id.clone(), actor_id.clone());
|
let follow = AsFollow::new(my_id.clone(), actor_id.clone());
|
||||||
|
|
||||||
prepare_activity(
|
prepare_activity(
|
||||||
|
@ -77,9 +76,9 @@ fn generate_follow(
|
||||||
// Generate a type that says "I accept your follow request"
|
// Generate a type that says "I accept your follow request"
|
||||||
fn generate_accept_follow(
|
fn generate_accept_follow(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
actor_id: &XsdAnyUri,
|
actor_id: &Url,
|
||||||
input_id: &XsdAnyUri,
|
input_id: &Url,
|
||||||
my_id: &XsdAnyUri,
|
my_id: &Url,
|
||||||
) -> Result<AsAccept, MyError> {
|
) -> Result<AsAccept, MyError> {
|
||||||
let mut follow = AsFollow::new(actor_id.clone(), my_id.clone());
|
let mut follow = AsFollow::new(actor_id.clone(), my_id.clone());
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ use activitystreams_new::{
|
||||||
activity::{Follow as AsFollow, Undo as AsUndo},
|
activity::{Follow as AsFollow, Undo as AsUndo},
|
||||||
context,
|
context,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
primitives::XsdAnyUri,
|
|
||||||
security,
|
security,
|
||||||
|
url::Url,
|
||||||
};
|
};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
@ -20,24 +20,16 @@ mod undo;
|
||||||
|
|
||||||
pub use self::{announce::Announce, follow::Follow, forward::Forward, reject::Reject, undo::Undo};
|
pub use self::{announce::Announce, follow::Follow, forward::Forward, reject::Reject, undo::Undo};
|
||||||
|
|
||||||
async fn get_inboxes(
|
async fn get_inboxes(state: &State, actor: &Actor, object_id: &Url) -> Result<Vec<Url>, MyError> {
|
||||||
state: &State,
|
let domain = object_id.host().ok_or(MyError::Domain)?.to_string();
|
||||||
actor: &Actor,
|
|
||||||
object_id: &XsdAnyUri,
|
|
||||||
) -> Result<Vec<XsdAnyUri>, MyError> {
|
|
||||||
let domain = object_id
|
|
||||||
.as_url()
|
|
||||||
.host()
|
|
||||||
.ok_or(MyError::Domain)?
|
|
||||||
.to_string();
|
|
||||||
|
|
||||||
Ok(state.listeners_without(&actor.inbox, &domain).await)
|
Ok(state.listeners_without(&actor.inbox, &domain).await)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_activity<T, U, V, Kind>(
|
fn prepare_activity<T, U, V, Kind>(
|
||||||
mut t: T,
|
mut t: T,
|
||||||
id: impl TryInto<XsdAnyUri, Error = U>,
|
id: impl TryInto<Url, Error = U>,
|
||||||
to: impl TryInto<XsdAnyUri, Error = V>,
|
to: impl TryInto<Url, Error = V>,
|
||||||
) -> Result<T, MyError>
|
) -> Result<T, MyError>
|
||||||
where
|
where
|
||||||
T: ObjectExt<Kind> + BaseExt<Kind>,
|
T: ObjectExt<Kind> + BaseExt<Kind>,
|
||||||
|
@ -50,11 +42,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a type that says "I want to stop following you"
|
// Generate a type that says "I want to stop following you"
|
||||||
fn generate_undo_follow(
|
fn generate_undo_follow(config: &Config, actor_id: &Url, my_id: &Url) -> Result<AsUndo, MyError> {
|
||||||
config: &Config,
|
|
||||||
actor_id: &XsdAnyUri,
|
|
||||||
my_id: &XsdAnyUri,
|
|
||||||
) -> Result<AsUndo, MyError> {
|
|
||||||
let mut follow = AsFollow::new(my_id.clone(), actor_id.clone());
|
let mut follow = AsFollow::new(my_id.clone(), actor_id.clone());
|
||||||
|
|
||||||
follow.set_id(config.generate_url(UrlKind::Activity));
|
follow.set_id(config.generate_url(UrlKind::Activity));
|
||||||
|
|
|
@ -12,7 +12,10 @@ pub struct Reject(pub Actor);
|
||||||
impl Reject {
|
impl Reject {
|
||||||
async fn perform(self, state: JobState) -> Result<(), anyhow::Error> {
|
async fn perform(self, state: JobState) -> Result<(), anyhow::Error> {
|
||||||
if state.actors.unfollower(&self.0).await?.is_some() {
|
if state.actors.unfollower(&self.0).await?.is_some() {
|
||||||
state.db.remove_listener(self.0.inbox.clone()).await?;
|
state
|
||||||
|
.db
|
||||||
|
.remove_listener(self.0.inbox.clone().into_inner())
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let my_id = state.config.generate_url(UrlKind::Actor);
|
let my_id = state.config.generate_url(UrlKind::Actor);
|
||||||
|
|
|
@ -22,7 +22,10 @@ impl Undo {
|
||||||
let was_following = state.actors.is_following(&self.actor.id).await;
|
let was_following = state.actors.is_following(&self.actor.id).await;
|
||||||
|
|
||||||
if state.actors.unfollower(&self.actor).await?.is_some() {
|
if state.actors.unfollower(&self.actor).await?.is_some() {
|
||||||
state.db.remove_listener(self.actor.inbox.clone()).await?;
|
state
|
||||||
|
.db
|
||||||
|
.remove_listener(self.actor.inbox.clone().into_inner())
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if was_following {
|
if was_following {
|
||||||
|
|
|
@ -31,7 +31,10 @@ impl ActixJob for Deliver {
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
state.requests.deliver(self.to, &self.data).await?;
|
state
|
||||||
|
.requests
|
||||||
|
.deliver(self.to.into_inner(), &self.data)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
error::MyError,
|
error::MyError,
|
||||||
jobs::{Deliver, JobState},
|
jobs::{Deliver, JobState},
|
||||||
};
|
};
|
||||||
use activitystreams_new::primitives::XsdAnyUri;
|
use activitystreams_new::{primitives::XsdAnyUri, url::Url};
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use futures::future::{ready, Ready};
|
use futures::future::{ready, Ready};
|
||||||
|
@ -14,12 +14,12 @@ pub struct DeliverMany {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeliverMany {
|
impl DeliverMany {
|
||||||
pub fn new<T>(to: Vec<XsdAnyUri>, data: T) -> Result<Self, MyError>
|
pub fn new<T>(to: Vec<Url>, data: T) -> Result<Self, MyError>
|
||||||
where
|
where
|
||||||
T: serde::ser::Serialize,
|
T: serde::ser::Serialize,
|
||||||
{
|
{
|
||||||
Ok(DeliverMany {
|
Ok(DeliverMany {
|
||||||
to,
|
to: to.into_iter().map(XsdAnyUri::from).collect(),
|
||||||
data: serde_json::to_value(data)?,
|
data: serde_json::to_value(data)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
config::UrlKind,
|
config::UrlKind,
|
||||||
jobs::{cache_media::CacheMedia, JobState},
|
jobs::{cache_media::CacheMedia, JobState},
|
||||||
};
|
};
|
||||||
use activitystreams_new::primitives::XsdAnyUri;
|
use activitystreams_new::{primitives::XsdAnyUri, url::Url};
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use futures::join;
|
use futures::join;
|
||||||
|
@ -14,26 +14,25 @@ pub struct QueryInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QueryInstance {
|
impl QueryInstance {
|
||||||
pub fn new(listener: XsdAnyUri) -> Self {
|
pub fn new(listener: Url) -> Self {
|
||||||
QueryInstance { listener }
|
QueryInstance {
|
||||||
|
listener: listener.into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn perform(mut self, state: JobState) -> Result<(), Error> {
|
async fn perform(mut self, state: JobState) -> Result<(), Error> {
|
||||||
let listener = self.listener.clone();
|
|
||||||
|
|
||||||
let (o1, o2) = join!(
|
let (o1, o2) = join!(
|
||||||
state.node_cache.is_contact_outdated(&listener),
|
state.node_cache.is_contact_outdated(&self.listener),
|
||||||
state.node_cache.is_instance_outdated(&listener),
|
state.node_cache.is_instance_outdated(&self.listener),
|
||||||
);
|
);
|
||||||
|
|
||||||
if !(o1 || o2) {
|
if !(o1 || o2) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = self.listener.as_url_mut();
|
self.listener.set_fragment(None);
|
||||||
url.set_fragment(None);
|
self.listener.set_query(None);
|
||||||
url.set_query(None);
|
self.listener.set_path("api/v1/instance");
|
||||||
url.set_path("api/v1/instance");
|
|
||||||
|
|
||||||
let instance = state
|
let instance = state
|
||||||
.requests
|
.requests
|
||||||
|
@ -48,11 +47,11 @@ impl QueryInstance {
|
||||||
|
|
||||||
if let Some(mut contact) = instance.contact {
|
if let Some(mut contact) = instance.contact {
|
||||||
let uuid = if let Some(uuid) = state.media.get_uuid(&contact.avatar).await? {
|
let uuid = if let Some(uuid) = state.media.get_uuid(&contact.avatar).await? {
|
||||||
contact.avatar = state.config.generate_url(UrlKind::Media(uuid));
|
contact.avatar = state.config.generate_url(UrlKind::Media(uuid)).into();
|
||||||
uuid
|
uuid
|
||||||
} else {
|
} else {
|
||||||
let uuid = state.media.store_url(&contact.avatar).await?;
|
let uuid = state.media.store_url(&contact.avatar).await?;
|
||||||
contact.avatar = state.config.generate_url(UrlKind::Media(uuid));
|
contact.avatar = state.config.generate_url(UrlKind::Media(uuid)).into();
|
||||||
uuid
|
uuid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,11 +60,11 @@ impl QueryInstance {
|
||||||
state
|
state
|
||||||
.node_cache
|
.node_cache
|
||||||
.set_contact(
|
.set_contact(
|
||||||
&listener,
|
&self.listener,
|
||||||
contact.username,
|
contact.username,
|
||||||
contact.display_name,
|
contact.display_name,
|
||||||
contact.url,
|
contact.url.into_inner(),
|
||||||
contact.avatar,
|
contact.avatar.into_inner(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +74,7 @@ impl QueryInstance {
|
||||||
state
|
state
|
||||||
.node_cache
|
.node_cache
|
||||||
.set_instance(
|
.set_instance(
|
||||||
&listener,
|
&self.listener,
|
||||||
instance.title,
|
instance.title,
|
||||||
description,
|
description,
|
||||||
instance.version,
|
instance.version,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::jobs::JobState;
|
use crate::jobs::JobState;
|
||||||
use activitystreams_new::primitives::XsdAnyUri;
|
use activitystreams_new::{primitives::XsdAnyUri, url::Url};
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use background_jobs::ActixJob;
|
use background_jobs::ActixJob;
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
@ -10,21 +10,20 @@ pub struct QueryNodeinfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QueryNodeinfo {
|
impl QueryNodeinfo {
|
||||||
pub fn new(listener: XsdAnyUri) -> Self {
|
pub fn new(listener: Url) -> Self {
|
||||||
QueryNodeinfo { listener }
|
QueryNodeinfo {
|
||||||
|
listener: listener.into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn perform(mut self, state: JobState) -> Result<(), Error> {
|
async fn perform(mut self, state: JobState) -> Result<(), Error> {
|
||||||
let listener = self.listener.clone();
|
if !state.node_cache.is_nodeinfo_outdated(&self.listener).await {
|
||||||
|
|
||||||
if !state.node_cache.is_nodeinfo_outdated(&listener).await {
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = self.listener.as_url_mut();
|
self.listener.set_fragment(None);
|
||||||
url.set_fragment(None);
|
self.listener.set_query(None);
|
||||||
url.set_query(None);
|
self.listener.set_path(".well-known/nodeinfo");
|
||||||
url.set_path(".well-known/nodeinfo");
|
|
||||||
|
|
||||||
let well_known = state
|
let well_known = state
|
||||||
.requests
|
.requests
|
||||||
|
@ -42,7 +41,7 @@ impl QueryNodeinfo {
|
||||||
state
|
state
|
||||||
.node_cache
|
.node_cache
|
||||||
.set_info(
|
.set_info(
|
||||||
&listener,
|
&self.listener,
|
||||||
nodeinfo.software.name,
|
nodeinfo.software.name,
|
||||||
nodeinfo.software.version,
|
nodeinfo.software.version,
|
||||||
nodeinfo.open_registrations,
|
nodeinfo.open_registrations,
|
||||||
|
|
|
@ -20,7 +20,7 @@ impl MyVerify {
|
||||||
signing_string: String,
|
signing_string: String,
|
||||||
) -> Result<bool, MyError> {
|
) -> Result<bool, MyError> {
|
||||||
let mut uri = uri!(key_id);
|
let mut uri = uri!(key_id);
|
||||||
uri.as_url_mut().set_fragment(None);
|
uri.set_fragment(None);
|
||||||
let actor = self.1.get(&uri, &self.0).await?;
|
let actor = self.1.get(&uri, &self.0).await?;
|
||||||
let was_cached = actor.is_cached();
|
let was_cached = actor.is_cached();
|
||||||
let actor = actor.into_inner();
|
let actor = actor.into_inner();
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
||||||
db::listen,
|
db::listen,
|
||||||
jobs::{JobServer, QueryInstance, QueryNodeinfo},
|
jobs::{JobServer, QueryInstance, QueryNodeinfo},
|
||||||
};
|
};
|
||||||
use activitystreams_new::primitives::XsdAnyUri;
|
use activitystreams_new::url::Url;
|
||||||
use actix_rt::{spawn, time::delay_for};
|
use actix_rt::{spawn, time::delay_for};
|
||||||
use futures::stream::{poll_fn, StreamExt};
|
use futures::stream::{poll_fn, StreamExt};
|
||||||
use log::{debug, error, warn};
|
use log::{debug, error, warn};
|
||||||
|
@ -144,7 +144,7 @@ impl Listener for NewListeners {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&self, payload: &str) {
|
fn execute(&self, payload: &str) {
|
||||||
if let Ok(uri) = payload.parse::<XsdAnyUri>() {
|
if let Ok(uri) = payload.parse::<Url>() {
|
||||||
debug!("Caching listener {}", uri);
|
debug!("Caching listener {}", uri);
|
||||||
let state = self.0.clone();
|
let state = self.0.clone();
|
||||||
let _ = self.1.queue(QueryInstance::new(uri.clone()));
|
let _ = self.1.queue(QueryInstance::new(uri.clone()));
|
||||||
|
@ -162,7 +162,7 @@ impl Listener for NewActors {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&self, payload: &str) {
|
fn execute(&self, payload: &str) {
|
||||||
if let Ok(uri) = payload.parse::<XsdAnyUri>() {
|
if let Ok(uri) = payload.parse::<Url>() {
|
||||||
debug!("Caching actor {}", uri);
|
debug!("Caching actor {}", uri);
|
||||||
let actors = self.0.clone();
|
let actors = self.0.clone();
|
||||||
spawn(async move { actors.cache_follower(uri).await });
|
spawn(async move { actors.cache_follower(uri).await });
|
||||||
|
@ -220,7 +220,7 @@ impl Listener for RmListeners {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&self, payload: &str) {
|
fn execute(&self, payload: &str) {
|
||||||
if let Ok(uri) = payload.parse::<XsdAnyUri>() {
|
if let Ok(uri) = payload.parse::<Url>() {
|
||||||
debug!("Busting listener cache for {}", uri);
|
debug!("Busting listener cache for {}", uri);
|
||||||
let state = self.0.clone();
|
let state = self.0.clone();
|
||||||
spawn(async move { state.bust_listener(&uri).await });
|
spawn(async move { state.bust_listener(&uri).await });
|
||||||
|
@ -236,7 +236,7 @@ impl Listener for RmActors {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&self, payload: &str) {
|
fn execute(&self, payload: &str) {
|
||||||
if let Ok(uri) = payload.parse::<XsdAnyUri>() {
|
if let Ok(uri) = payload.parse::<Url>() {
|
||||||
debug!("Busting actor cache for {}", uri);
|
debug!("Busting actor cache for {}", uri);
|
||||||
let actors = self.0.clone();
|
let actors = self.0.clone();
|
||||||
spawn(async move { actors.bust_follower(&uri).await });
|
spawn(async move { actors.bust_follower(&uri).await });
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::error::MyError;
|
use crate::error::MyError;
|
||||||
use activitystreams_new::primitives::XsdAnyUri;
|
use activitystreams_new::url::Url;
|
||||||
use actix_web::{client::Client, http::header::Date};
|
use actix_web::{client::Client, http::header::Date};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use http_signature_normalization_actix::prelude::*;
|
use http_signature_normalization_actix::prelude::*;
|
||||||
|
@ -159,7 +159,7 @@ impl Requests {
|
||||||
Ok((content_type, bytes))
|
Ok((content_type, bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn deliver<T>(&self, inbox: XsdAnyUri, item: &T) -> Result<(), MyError>
|
pub async fn deliver<T>(&self, inbox: Url, item: &T) -> Result<(), MyError>
|
||||||
where
|
where
|
||||||
T: serde::ser::Serialize,
|
T: serde::ser::Serialize,
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,8 +23,8 @@ pub async fn route(
|
||||||
ApActor::new(config.generate_url(UrlKind::Inbox), Application::new()),
|
ApActor::new(config.generate_url(UrlKind::Inbox), Application::new()),
|
||||||
PublicKey {
|
PublicKey {
|
||||||
public_key: PublicKeyInner {
|
public_key: PublicKeyInner {
|
||||||
id: config.generate_url(UrlKind::MainKey),
|
id: config.generate_url(UrlKind::MainKey).into(),
|
||||||
owner: config.generate_url(UrlKind::Actor),
|
owner: config.generate_url(UrlKind::Actor).into(),
|
||||||
public_key_pem: state.public_key.to_pem_pkcs8()?,
|
public_key_pem: state.public_key.to_pem_pkcs8()?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,11 +9,7 @@ use crate::{
|
||||||
routes::accepted,
|
routes::accepted,
|
||||||
};
|
};
|
||||||
use activitystreams_new::{
|
use activitystreams_new::{
|
||||||
activity,
|
activity, base::AnyBase, prelude::*, primitives::OneOrMany, public, url::Url,
|
||||||
base::AnyBase,
|
|
||||||
prelude::*,
|
|
||||||
primitives::{OneOrMany, XsdAnyUri},
|
|
||||||
public,
|
|
||||||
};
|
};
|
||||||
use actix_web::{web, HttpResponse};
|
use actix_web::{web, HttpResponse};
|
||||||
use futures::join;
|
use futures::join;
|
||||||
|
@ -33,7 +29,7 @@ pub async fn route(
|
||||||
|
|
||||||
let actor = actors
|
let actor = actors
|
||||||
.get(
|
.get(
|
||||||
input.actor().as_single_id().ok_or(MyError::MissingId)?,
|
input.actor()?.as_single_id().ok_or(MyError::MissingId)?,
|
||||||
&client,
|
&client,
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
|
@ -97,7 +93,7 @@ fn kind_str(base: &AnyBase) -> Result<&str, MyError> {
|
||||||
base.kind_str().ok_or(MyError::MissingKind)
|
base.kind_str().ok_or(MyError::MissingKind)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn id_string(id: Option<&XsdAnyUri>) -> Result<String, MyError> {
|
fn id_string(id: Option<&Url>) -> Result<String, MyError> {
|
||||||
id.map(|s| s.to_string()).ok_or(MyError::MissingId)
|
id.map(|s| s.to_string()).ok_or(MyError::MissingId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +113,7 @@ async fn handle_accept(config: &Config, input: AcceptedActivities) -> Result<(),
|
||||||
|
|
||||||
if !follow.actor_is(&config.generate_url(UrlKind::Actor)) {
|
if !follow.actor_is(&config.generate_url(UrlKind::Actor)) {
|
||||||
return Err(MyError::WrongActor(id_string(
|
return Err(MyError::WrongActor(id_string(
|
||||||
follow.actor().as_single_id(),
|
follow.actor()?.as_single_id(),
|
||||||
)?));
|
)?));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +137,7 @@ async fn handle_reject(
|
||||||
|
|
||||||
if !follow.actor_is(&config.generate_url(UrlKind::Actor)) {
|
if !follow.actor_is(&config.generate_url(UrlKind::Actor)) {
|
||||||
return Err(MyError::WrongActor(id_string(
|
return Err(MyError::WrongActor(id_string(
|
||||||
follow.actor().as_single_id(),
|
follow.actor()?.as_single_id(),
|
||||||
)?));
|
)?));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +166,7 @@ async fn handle_undo(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let my_id: XsdAnyUri = config.generate_url(UrlKind::Actor);
|
let my_id: Url = config.generate_url(UrlKind::Actor);
|
||||||
|
|
||||||
if !undone_object.object_is(&my_id) && !undone_object.object_is(&public()) {
|
if !undone_object.object_is(&my_id) && !undone_object.object_is(&public()) {
|
||||||
return Err(MyError::WrongActor(id_string(
|
return Err(MyError::WrongActor(id_string(
|
||||||
|
@ -220,7 +216,7 @@ async fn handle_follow(
|
||||||
actor: Actor,
|
actor: Actor,
|
||||||
is_listener: bool,
|
is_listener: bool,
|
||||||
) -> Result<(), MyError> {
|
) -> Result<(), MyError> {
|
||||||
let my_id: XsdAnyUri = config.generate_url(UrlKind::Actor);
|
let my_id: Url = config.generate_url(UrlKind::Actor);
|
||||||
|
|
||||||
if !input.object_is(&my_id) && !input.object_is(&public()) {
|
if !input.object_is(&my_id) && !input.object_is(&public()) {
|
||||||
return Err(MyError::WrongActor(id_string(
|
return Err(MyError::WrongActor(id_string(
|
||||||
|
|
|
@ -49,7 +49,7 @@ pub async fn route(config: web::Data<Config>, state: web::Data<State>) -> web::J
|
||||||
.listeners()
|
.listeners()
|
||||||
.await
|
.await
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|listener| listener.as_url().domain())
|
.filter_map(|listener| listener.domain())
|
||||||
.map(|s| s.to_owned())
|
.map(|s| s.to_owned())
|
||||||
.collect(),
|
.collect(),
|
||||||
blocks: if config.publish_blocks() {
|
blocks: if config.publish_blocks() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@use crate::data::Contact;
|
@use crate::data::Contact;
|
||||||
@use activitystreams_new::primitives::XsdAnyUri;
|
@use activitystreams_new::url::Url;
|
||||||
|
|
||||||
@(contact: &Contact, base: &XsdAnyUri)
|
@(contact: &Contact, base: &Url)
|
||||||
|
|
||||||
<div class="admin">
|
<div class="admin">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<p class="display-name"><a href="@contact.url">@contact.display_name</a></p>
|
<p class="display-name"><a href="@contact.url">@contact.display_name</a></p>
|
||||||
@if let Some(domain) = base.as_url().domain() {
|
@if let Some(domain) = base.domain() {
|
||||||
<p class="username">@@@contact.username@@@domain</p>
|
<p class="username">@@@contact.username@@@domain</p>
|
||||||
} else {
|
} else {
|
||||||
<p class="username">@@@contact.username</p>
|
<p class="username">@@@contact.username</p>
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
@use crate::data::Info;
|
@use crate::data::Info;
|
||||||
@use activitystreams_new::primitives::XsdAnyUri;
|
@use activitystreams_new::url::Url;
|
||||||
|
|
||||||
@(info: &Info, base: &XsdAnyUri)
|
@(info: &Info, base: &Url)
|
||||||
|
|
||||||
<article class="info">
|
<article class="info">
|
||||||
@if let Some(domain) = base.as_url().domain() {
|
@if let Some(domain) = base.domain() {
|
||||||
<h4 class="padded"><a href="@base">@domain</a></h4>
|
<h4 class="padded"><a href="@base">@domain</a></h4>
|
||||||
}
|
}
|
||||||
<p class="padded">
|
<p class="padded">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@use crate::{data::{Contact, Instance}, templates::admin};
|
@use crate::{data::{Contact, Instance}, templates::admin};
|
||||||
@use activitystreams_new::primitives::XsdAnyUri;
|
@use activitystreams_new::url::Url;
|
||||||
|
|
||||||
@(instance: &Instance, software: Option<&str>, contact: Option<&Contact>, base: &XsdAnyUri)
|
@(instance: &Instance, software: Option<&str>, contact: Option<&Contact>, base: &Url)
|
||||||
|
|
||||||
<article class="instance">
|
<article class="instance">
|
||||||
<h4 class="padded"><a href="@base">@instance.title</a></h4>
|
<h4 class="padded"><a href="@base">@instance.title</a></h4>
|
||||||
|
|
Loading…
Reference in a new issue