Update activitystreams library to latest version (#71)

Merge branch 'main' into more-upgrade-apub-3

Update activitystreams library to latest version

Remove remaining usages of old activitystreams library

Migrate community inbox and user inbox

Migrate private message

Migrate post

Migrate community activities

Migrate extensions to new activitystreams library

Co-authored-by: dessalines <dessalines@noreply.yerbamate.dev>
Co-authored-by: Felix Ableitner <me@nutomic.com>
Reviewed-on: https://yerbamate.dev/LemmyNet/lemmy/pulls/71
This commit is contained in:
nutomic 2020-07-17 21:11:07 +00:00 committed by dessalines
parent 09f892a7fa
commit 77a2a5eb01
19 changed files with 831 additions and 1160 deletions

323
server/Cargo.lock generated vendored
View file

@ -1,35 +1,9 @@
# 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.114",
"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.114", "serde 1.0.114",
@ -39,12 +13,14 @@ dependencies = [
[[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#857d5167dfa13054dd0d21d3d54f8147eea0d546"
dependencies = [ dependencies = [
"activitystreams", "chrono",
"mime",
"serde 1.0.114", "serde 1.0.114",
"serde_json", "serde_json",
"typed-builder", "thiserror",
"url",
] ]
[[package]] [[package]]
@ -111,9 +87,9 @@ dependencies = [
[[package]] [[package]]
name = "actix-files" name = "actix-files"
version = "0.3.0-alpha.1" version = "0.3.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b32e0fdd5998c2712549cbc39dff46c8754d55e3dd9f4d017d9e28de30cac6" checksum = "627f597ad98061816766201db8afc7444752992f2919b2e60f53a7fa27f01aed"
dependencies = [ dependencies = [
"actix-http", "actix-http",
"actix-service", "actix-service",
@ -132,9 +108,9 @@ dependencies = [
[[package]] [[package]]
name = "actix-http" name = "actix-http"
version = "2.0.0-alpha.4" version = "2.0.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd7ea0568480d199952a51de70271946da57c33cc0e8b83f54383e70958dff21" checksum = "33f501768e82e8548763b7f55309e2f8bcc7f9f4273c75b47af99ac2b2581f37"
dependencies = [ dependencies = [
"actix-codec", "actix-codec",
"actix-connect", "actix-connect",
@ -147,6 +123,7 @@ dependencies = [
"bitflags", "bitflags",
"brotli2", "brotli2",
"bytes", "bytes",
"cookie",
"copyless", "copyless",
"derive_more", "derive_more",
"either", "either",
@ -160,6 +137,7 @@ dependencies = [
"http", "http",
"httparse", "httparse",
"indexmap", "indexmap",
"itoa",
"language-tags", "language-tags",
"lazy_static", "lazy_static",
"log", "log",
@ -171,7 +149,7 @@ dependencies = [
"serde 1.0.114", "serde 1.0.114",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"sha-1", "sha-1 0.9.1",
"slab", "slab",
"time 0.2.16", "time 0.2.16",
] ]
@ -260,16 +238,16 @@ dependencies = [
[[package]] [[package]]
name = "actix-threadpool" name = "actix-threadpool"
version = "0.3.2" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91164716d956745c79dcea5e66d2aa04506549958accefcede5368c70f2fd4ff" checksum = "d209f04d002854b9afd3743032a27b066158817965bf5d036824d19ac2cc0e30"
dependencies = [ dependencies = [
"derive_more", "derive_more",
"futures-channel", "futures-channel",
"lazy_static", "lazy_static",
"log", "log",
"num_cpus", "num_cpus",
"parking_lot 0.10.2", "parking_lot 0.11.0",
"threadpool", "threadpool",
] ]
@ -313,9 +291,9 @@ dependencies = [
[[package]] [[package]]
name = "actix-web" name = "actix-web"
version = "3.0.0-alpha.3" version = "3.0.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bd6df56ec5f9a1a0d8335f156f36e1e8f76dbd736fa0cc0f6bc3a69be1e6124" checksum = "9125c29b7d9911bfdb4d0d4d8f1cf4fee4f21515cf2a405a423c30c245364297"
dependencies = [ dependencies = [
"actix-codec", "actix-codec",
"actix-http", "actix-http",
@ -353,24 +331,25 @@ dependencies = [
[[package]] [[package]]
name = "actix-web-actors" name = "actix-web-actors"
version = "3.0.0-alpha.1" version = "3.0.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b5efeb3907582f9c724ce27be093ab8aafabd97be828bc6750c0d467f5e1aa3" checksum = "55ef22b33c49a28dda61866d5573c5b8ceb080a099cd59e7371b78b48bbf1bc0"
dependencies = [ dependencies = [
"actix", "actix",
"actix-codec", "actix-codec",
"actix-http", "actix-http",
"actix-web", "actix-web",
"bytes", "bytes",
"futures", "futures-channel",
"futures-core",
"pin-project", "pin-project",
] ]
[[package]] [[package]]
name = "actix-web-codegen" name = "actix-web-codegen"
version = "0.2.2" version = "0.3.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766" checksum = "df9679f5b1f4c819de08b63b0a61a131b2fdc30b367c2c208984fda8eaa07fa0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -390,24 +369,18 @@ dependencies = [
[[package]] [[package]]
name = "addr2line" name = "addr2line"
version = "0.12.2" version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "602d785912f476e480434627e8732e6766b760c045bbf897d9dfaa9f4fbd399c" checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
dependencies = [ dependencies = [
"gimli", "gimli",
] ]
[[package]] [[package]]
name = "adler" name = "adler"
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 = "ccc9a9dd069569f212bc4330af9f17c4afb5e8ce185e83dbb14f1349dda18b10" checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
[[package]]
name = "adler32"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d"
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
@ -481,9 +454,9 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]] [[package]]
name = "awc" name = "awc"
version = "2.0.0-alpha.2" version = "2.0.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7038a9747cd5159b9f0550895eaf865c0143baa7e4eee834e9294d0a7e0e4be" checksum = "374057b508d4083208996be82141891c2e14c8885f45991b21c1621200ab6df3"
dependencies = [ dependencies = [
"actix-codec", "actix-codec",
"actix-http", "actix-http",
@ -505,14 +478,14 @@ dependencies = [
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.49" version = "0.3.50"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05100821de9e028f12ae3d189176b41ee198341eb8f369956407fea2f5cc666c" checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293"
dependencies = [ dependencies = [
"addr2line", "addr2line",
"cfg-if", "cfg-if",
"libc", "libc",
"miniz_oxide 0.3.7", "miniz_oxide",
"object", "object",
"rustc-demangle", "rustc-demangle",
] ]
@ -590,7 +563,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 = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [ dependencies = [
"generic-array 0.14.2", "generic-array 0.14.3",
] ]
[[package]] [[package]]
@ -599,7 +572,7 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa136449e765dc7faa244561ccae839c394048667929af599b5d931ebe7b7f10" checksum = "fa136449e765dc7faa244561ccae839c394048667929af599b5d931ebe7b7f10"
dependencies = [ dependencies = [
"generic-array 0.14.2", "generic-array 0.14.3",
] ]
[[package]] [[package]]
@ -642,6 +615,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "buf-min"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6ae7069aad07c7cdefe6a22a671f00650728bd2331a4cc62e1e5d0becdf9ca4"
dependencies = [
"bytes",
]
[[package]] [[package]]
name = "bufstream" name = "bufstream"
version = "0.1.4" version = "0.1.4"
@ -668,12 +650,9 @@ checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "0.5.5" 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 = "118cf036fbb97d0816e3c34b2d7a1e8cfc60f68fcf63d550ddbe9bd5f59c213b" checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
dependencies = [
"loom",
]
[[package]] [[package]]
name = "bytestring" name = "bytestring"
@ -686,9 +665,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.57" version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fde55d2a2bfaa4c9668bbc63f531fbdeee3ffe188f4662511ce2c22b3eedebe" checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -698,9 +677,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.12" version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0fee792e164f78f5fe0c296cc2eb3688a2ca2b70cdff33040922d298203f0c4" checksum = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6"
dependencies = [ dependencies = [
"num-integer", "num-integer",
"num-traits 0.2.12", "num-traits 0.2.12",
@ -770,6 +749,16 @@ dependencies = [
"serde-hjson", "serde-hjson",
] ]
[[package]]
name = "cookie"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca761767cf3fa9068cc893ec8c247a22d0fd0535848e65640c0548bd1f8bbb36"
dependencies = [
"percent-encoding",
"time 0.2.16",
]
[[package]] [[package]]
name = "copyless" name = "copyless"
version = "0.1.5" version = "0.1.5"
@ -794,9 +783,9 @@ checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
[[package]] [[package]]
name = "cpuid-bool" name = "cpuid-bool"
version = "0.1.0" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d375c433320f6c5057ae04a04376eef4d04ce2801448cf8863a78da99107be4" checksum = "ec6763c20301ab0dc67051d1b6f4cc9132ad9e6eddcb1f10c6c53ea6d6ae2183"
[[package]] [[package]]
name = "crc32fast" name = "crc32fast"
@ -950,7 +939,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.2", "generic-array 0.14.3",
] ]
[[package]] [[package]]
@ -1142,7 +1131,7 @@ dependencies = [
"cfg-if", "cfg-if",
"crc32fast", "crc32fast",
"libc", "libc",
"miniz_oxide 0.4.0", "miniz_oxide",
] ]
[[package]] [[package]]
@ -1292,19 +1281,6 @@ 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.9",
]
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.12.3" version = "0.12.3"
@ -1316,9 +1292,9 @@ dependencies = [
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.2" version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac746a5f3bbfdadd6106868134545e684693d54d9d44f6e9588a7d54af0bf980" checksum = "60fb4bb6bba52f78a471264d9a3b7d026cc0af47b22cd2cffbc0b787ca003e63"
dependencies = [ dependencies = [
"typenum", "typenum",
"version_check 0.9.2", "version_check 0.9.2",
@ -1337,15 +1313,15 @@ dependencies = [
[[package]] [[package]]
name = "gimli" name = "gimli"
version = "0.21.0" version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c" checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.2.5" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79b7246d7e4b979c03fa093da39cfb3617a96bbeee6310af63991668d7e843ff" checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53"
dependencies = [ dependencies = [
"bytes", "bytes",
"fnv", "fnv",
@ -1354,10 +1330,10 @@ dependencies = [
"futures-util", "futures-util",
"http", "http",
"indexmap", "indexmap",
"log",
"slab", "slab",
"tokio", "tokio",
"tokio-util 0.3.1", "tokio-util 0.3.1",
"tracing",
] ]
[[package]] [[package]]
@ -1371,9 +1347,9 @@ dependencies = [
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.14" version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909" checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@ -1481,9 +1457,9 @@ dependencies = [
[[package]] [[package]]
name = "instant" name = "instant"
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 = "69da7ce1490173c2bf4d26bc8be429aaeeaf4cce6c4b970b7949651fa17655fe" checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485"
[[package]] [[package]]
name = "iovec" name = "iovec"
@ -1523,9 +1499,9 @@ checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.41" version = "0.3.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4b9172132a62451e56142bff9afc91c8e4a4500aa5b847da36815b63bfda916" checksum = "52732a3d3ad72c58ad2dc70624f9c17b46ecd0943b9a4f1ee37c4c18c5d983e2"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
@ -1579,13 +1555,13 @@ dependencies = [
"sha2", "sha2",
"strum", "strum",
"strum_macros", "strum_macros",
"url",
] ]
[[package]] [[package]]
name = "lemmy_server" name = "lemmy_server"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"activitystreams",
"activitystreams-ext", "activitystreams-ext",
"activitystreams-new", "activitystreams-new",
"actix", "actix",
@ -1693,9 +1669,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.71" version = "0.2.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" checksum = "a9f8082297d534141b30c8d39e9b1773713ab50fdbe4ff30f750d063b3bfd701"
[[package]] [[package]]
name = "linked-hash-map" name = "linked-hash-map"
@ -1724,33 +1700,22 @@ dependencies = [
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.0" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de302ce1fe7482db13738fbaf2e21cfb06a986b89c0bf38d88abf16681aada4e" checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c"
dependencies = [ dependencies = [
"scopeguard", "scopeguard",
] ]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.8" version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "loom"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ecc775857611e1df29abba5c41355cdf540e7e9d4acfdf0f355eefee82330b7"
dependencies = [
"cfg-if",
"generator",
"scoped-tls",
]
[[package]] [[package]]
name = "lru-cache" name = "lru-cache"
version = "0.1.2" version = "0.1.2"
@ -1827,15 +1792,6 @@ dependencies = [
"unicase", "unicase",
] ]
[[package]]
name = "miniz_oxide"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
dependencies = [
"adler32",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.4.0" version = "0.4.0"
@ -2060,7 +2016,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733"
dependencies = [ dependencies = [
"instant", "instant",
"lock_api 0.4.0", "lock_api 0.4.1",
"parking_lot_core 0.8.0", "parking_lot_core 0.8.0",
] ]
@ -2150,7 +2106,7 @@ checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
dependencies = [ dependencies = [
"maplit", "maplit",
"pest", "pest",
"sha-1", "sha-1 0.8.2",
] ]
[[package]] [[package]]
@ -2187,9 +2143,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.17" version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
@ -2434,9 +2390,9 @@ dependencies = [
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.1.56" version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]] [[package]]
name = "regex" name = "regex"
@ -2559,12 +2515,6 @@ dependencies = [
"parking_lot 0.11.0", "parking_lot 0.11.0",
] ]
[[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"
@ -2703,6 +2653,19 @@ dependencies = [
"opaque-debug 0.2.3", "opaque-debug 0.2.3",
] ]
[[package]]
name = "sha-1"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "170a36ea86c864a3f16dd2687712dd6646f7019f301e57537c7f4dc9f5916770"
dependencies = [
"block-buffer 0.9.0",
"cfg-if",
"cpuid-bool",
"digest 0.9.0",
"opaque-debug 0.3.0",
]
[[package]] [[package]]
name = "sha1" name = "sha1"
version = "0.6.0" version = "0.6.0"
@ -2734,9 +2697,9 @@ dependencies = [
[[package]] [[package]]
name = "simple_asn1" name = "simple_asn1"
version = "0.4.0" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b25ecba7165254f0c97d6c22a64b1122a03634b18d20a34daf21e18f892e618" checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b"
dependencies = [ dependencies = [
"chrono", "chrono",
"num-bigint", "num-bigint",
@ -2751,9 +2714,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.4.0" version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" checksum = "3757cb9d89161a2f24e1cf78efa0c1fcff485d18e3f55e0aa3480824ddaa0f3f"
[[package]] [[package]]
name = "socket2" name = "socket2"
@ -2869,9 +2832,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.33" version = "1.0.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8d5d96e8cbb005d6959f119f773bfaebb5684296108fb32600c00cde305b2cd" checksum = "936cae2873c940d92e697597c5eee105fb570cd5689c695806f672883653349b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -3076,6 +3039,26 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tracing"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2e2a2de6b0d5cbb13fc21193a2296888eaab62b6044479aafb3c54c01c29fcd"
dependencies = [
"cfg-if",
"log",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94ae75f0d28ae10786f3b1895c55fe72e79928fd5ccdebb5438c75e93fec178f"
dependencies = [
"lazy_static",
]
[[package]] [[package]]
name = "trust-dns-proto" name = "trust-dns-proto"
version = "0.19.5" version = "0.19.5"
@ -3132,17 +3115,6 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d"
[[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"
@ -3251,18 +3223,19 @@ dependencies = [
[[package]] [[package]]
name = "v_escape" name = "v_escape"
version = "0.7.4" version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "660b101c07b5d0863deb9e7fb3138777e858d6d2a79f9e6049a27d1cc77c6da6" checksum = "b66158ce426982197fd44266d68125fd4000f1d42f5ee33ef02b500b4b6b0024"
dependencies = [ dependencies = [
"buf-min",
"v_escape_derive", "v_escape_derive",
] ]
[[package]] [[package]]
name = "v_escape_derive" name = "v_escape_derive"
version = "0.5.6" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2ca2a14bc3fc5b64d188b087a7d3a927df87b152e941ccfbc66672e20c467ae" checksum = "cae7cffca0b1f9af9b20610f6fdeee9ffcce61417b5ad186a5d482dc904e24cd"
dependencies = [ dependencies = [
"nom 4.2.3", "nom 4.2.3",
"proc-macro2", "proc-macro2",
@ -3272,9 +3245,9 @@ dependencies = [
[[package]] [[package]]
name = "v_htmlescape" name = "v_htmlescape"
version = "0.4.5" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e33e939c0d8cf047514fb6ba7d5aac78bc56677a6938b2ee67000b91f2e97e41" checksum = "f5fd25529cb2f78527b5ee507bcfb357b26d057b5e480853c26d49a4ead5c629"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"v_escape", "v_escape",
@ -3312,9 +3285,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.64" version = "0.2.65"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a634620115e4a229108b71bde263bb4220c483b3f07f5ba514ee8d15064c4c2" checksum = "f3edbcc9536ab7eababcc6d2374a0b7bfe13a2b6d562c5e07f370456b1a8f33d"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"wasm-bindgen-macro", "wasm-bindgen-macro",
@ -3322,9 +3295,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "wasm-bindgen-backend"
version = "0.2.64" version = "0.2.65"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e53963b583d18a5aa3aaae4b4c1cb535218246131ba22a71f05b518098571df" checksum = "89ed2fb8c84bfad20ea66b26a3743f3e7ba8735a69fe7d95118c33ec8fc1244d"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"lazy_static", "lazy_static",
@ -3337,9 +3310,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.64" version = "0.2.65"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fcfd5ef6eec85623b4c6e844293d4516470d8f19cd72d0d12246017eb9060b8" checksum = "eb071268b031a64d92fc6cf691715ca5a40950694d8f683c5bb43db7c730929e"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@ -3347,9 +3320,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.64" version = "0.2.65"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9adff9ee0e94b926ca81b57f57f86d5545cdcb1d259e21ec9bdd95b901754c75" checksum = "cf592c807080719d1ff2f245a687cbadb3ed28b2077ed7084b47aba8b691f2c6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -3360,15 +3333,15 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.64" version = "0.2.65"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f7b90ea6c632dd06fd765d44542e234d5e63d9bb917ecd64d79778a13bd79ae" checksum = "72b6c0220ded549d63860c78c38f3bcc558d1ca3f4efa74942c536ddbbb55e87"
[[package]] [[package]]
name = "web-sys" name = "web-sys"
version = "0.3.41" version = "0.3.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "863539788676619aac1a23e2df3655e96b32b0e05eb72ca34ba045ad573c625d" checksum = "8be2398f326b7ba09815d0b403095f34dd708579220d099caae89be0b32137b2"
dependencies = [ dependencies = [
"js-sys", "js-sys",
"wasm-bindgen", "wasm-bindgen",

5
server/Cargo.toml vendored
View file

@ -18,9 +18,8 @@ lemmy_db = { path = "./lemmy_db" }
diesel = "1.4.4" diesel = "1.4.4"
diesel_migrations = "1.4.0" diesel_migrations = "1.4.0"
dotenv = "0.15.0" dotenv = "0.15.0"
activitystreams = "0.6.2" activitystreams-new = { git = "https://git.asonix.dog/asonix/activitystreams-sketch", branch = "main" }
activitystreams-new = { git = "https://git.asonix.dog/asonix/activitystreams-sketch" } activitystreams-ext = { git = "https://git.asonix.dog/asonix/activitystreams-ext", branch = "main" }
activitystreams-ext = { git = "https://git.asonix.dog/asonix/activitystreams-ext" }
bcrypt = "0.8.0" bcrypt = "0.8.0"
chrono = { version = "0.4.7", features = ["serde"] } chrono = { version = "0.4.7", features = ["serde"] }
serde_json = { version = "1.0.52", features = ["preserve_order"]} serde_json = { version = "1.0.52", features = ["preserve_order"]}

View file

@ -12,4 +12,5 @@ strum = "0.18.0"
strum_macros = "0.18.0" strum_macros = "0.18.0"
log = "0.4.0" log = "0.4.0"
sha2 = "0.9" sha2 = "0.9"
bcrypt = "0.8.0" bcrypt = "0.8.0"
url = { version = "2.1.1", features = ["serde"] }

View file

@ -1,5 +1,6 @@
use super::{post::Post, *}; use super::{post::Post, *};
use crate::schema::{comment, comment_like, comment_saved}; use crate::schema::{comment, comment_like, comment_saved};
use url::{ParseError, Url};
// WITH RECURSIVE MyTree AS ( // WITH RECURSIVE MyTree AS (
// SELECT * FROM comment WHERE parent_id IS NULL // SELECT * FROM comment WHERE parent_id IS NULL
@ -42,6 +43,12 @@ pub struct CommentForm {
pub local: bool, pub local: bool,
} }
impl CommentForm {
pub fn get_ap_id(&self) -> Result<Url, ParseError> {
Url::parse(&self.ap_id)
}
}
impl Crud<CommentForm> for Comment { impl Crud<CommentForm> for Comment {
fn read(conn: &PgConnection, comment_id: i32) -> Result<Self, Error> { fn read(conn: &PgConnection, comment_id: i32) -> Result<Self, Error> {
use crate::schema::comment::dsl::*; use crate::schema::comment::dsl::*;

View file

@ -8,6 +8,7 @@ use crate::{
}; };
use diesel::{dsl::*, result::Error, *}; use diesel::{dsl::*, result::Error, *};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use url::{ParseError, Url};
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)] #[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
#[table_name = "post"] #[table_name = "post"]
@ -56,6 +57,12 @@ pub struct PostForm {
pub local: bool, pub local: bool,
} }
impl PostForm {
pub fn get_ap_id(&self) -> Result<Url, ParseError> {
Url::parse(&self.ap_id)
}
}
impl Post { impl Post {
pub fn read(conn: &PgConnection, post_id: i32) -> Result<Self, Error> { pub fn read(conn: &PgConnection, post_id: i32) -> Result<Self, Error> {
use crate::schema::post::dsl::*; use crate::schema::post::dsl::*;

View file

@ -6,41 +6,20 @@ use crate::{
request::retry_custom, request::retry_custom,
DbPool, LemmyError, DbPool, LemmyError,
}; };
use activitystreams::{context, object::properties::ObjectProperties, public, Activity, Base}; use activitystreams_new::base::AnyBase;
use actix_web::client::Client; use actix_web::client::Client;
use lemmy_db::{community::Community, user::User_}; use lemmy_db::{community::Community, user::User_};
use log::debug; use log::debug;
use serde::Serialize;
use std::fmt::Debug;
use url::Url; use url::Url;
pub fn populate_object_props( pub async fn send_activity_to_community(
props: &mut ObjectProperties,
addressed_ccs: Vec<String>,
object_id: &str,
) -> Result<(), LemmyError> {
props
.set_context_xsd_any_uri(context())?
// TODO: the activity needs a seperate id from the object
.set_id(object_id)?
// TODO: should to/cc go on the Create, or on the Post? or on both?
// TODO: handle privacy on the receiving side (at least ignore anything thats not public)
.set_to_xsd_any_uri(public())?
.set_many_cc_xsd_any_uris(addressed_ccs)?;
Ok(())
}
pub async fn send_activity_to_community<A>(
creator: &User_, creator: &User_,
community: &Community, community: &Community,
to: Vec<String>, to: Vec<String>,
activity: A, activity: AnyBase,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<(), LemmyError> ) -> Result<(), LemmyError> {
where
A: Activity + Base + Serialize + Debug + Clone + Send + 'static,
{
insert_activity(creator.id, activity.clone(), true, pool).await?; insert_activity(creator.id, activity.clone(), true, pool).await?;
// if this is a local community, we need to do an announce from the community instead // if this is a local community, we need to do an announce from the community instead
@ -54,15 +33,12 @@ where
} }
/// Send an activity to a list of recipients, using the correct headers etc. /// Send an activity to a list of recipients, using the correct headers etc.
pub async fn send_activity<A>( pub async fn send_activity(
client: &Client, client: &Client,
activity: &A, activity: &AnyBase,
actor: &dyn ActorType, actor: &dyn ActorType,
to: Vec<String>, to: Vec<String>,
) -> Result<(), LemmyError> ) -> Result<(), LemmyError> {
where
A: Serialize,
{
let activity = serde_json::to_string(&activity)?; let activity = serde_json::to_string(&activity)?;
debug!("Sending activitypub activity {} to {:?}", activity, to); debug!("Sending activitypub activity {} to {:?}", activity, to);

View file

@ -19,7 +19,6 @@ use activitystreams_new::{
link::Mention, link::Mention,
object::{kind::NoteType, Note, Tombstone}, object::{kind::NoteType, Note, Tombstone},
prelude::*, prelude::*,
primitives::XsdAnyUri,
public, public,
}; };
use actix_web::{body::Body, client::Client, web::Path, HttpResponse}; use actix_web::{body::Body, client::Client, web::Path, HttpResponse};
@ -35,7 +34,7 @@ use lemmy_utils::{convert_datetime, scrape_text_for_mentions, MentionData};
use log::debug; use log::debug;
use serde::Deserialize; use serde::Deserialize;
use serde_json::Error; use serde_json::Error;
use std::str::FromStr; use url::Url;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct CommentQuery { pub struct CommentQuery {
@ -86,15 +85,15 @@ impl ToApub for Comment {
comment comment
// Not needed when the Post is embedded in a collection (like for community outbox) // Not needed when the Post is embedded in a collection (like for community outbox)
.set_context(context()) .set_context(context())
.set_id(self.ap_id.parse::<XsdAnyUri>()?) .set_id(Url::parse(&self.ap_id)?)
.set_published(convert_datetime(self.published).into()) .set_published(convert_datetime(self.published))
.set_to(community.actor_id) .set_to(community.actor_id)
.set_many_in_reply_tos(in_reply_to_vec) .set_many_in_reply_tos(in_reply_to_vec)
.set_content(self.content.to_owned()) .set_content(self.content.to_owned())
.set_attributed_to(creator.actor_id); .set_attributed_to(creator.actor_id);
if let Some(u) = self.updated { if let Some(u) = self.updated {
comment.set_updated(convert_datetime(u).into()); comment.set_updated(convert_datetime(u));
} }
Ok(comment) Ok(comment)
@ -105,7 +104,7 @@ impl ToApub for Comment {
self.deleted, self.deleted,
&self.ap_id, &self.ap_id,
self.updated, self.updated,
NoteType.to_string(), NoteType::Note.to_string(),
) )
} }
} }
@ -119,6 +118,7 @@ impl FromApub for CommentForm {
note: &Note, note: &Note,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
actor_id: &Url,
) -> Result<CommentForm, LemmyError> { ) -> Result<CommentForm, LemmyError> {
let creator_actor_id = &note let creator_actor_id = &note
.attributed_to() .attributed_to()
@ -129,14 +129,14 @@ impl FromApub for CommentForm {
let creator = get_or_fetch_and_upsert_remote_user(creator_actor_id, client, pool).await?; let creator = get_or_fetch_and_upsert_remote_user(creator_actor_id, client, pool).await?;
let mut in_reply_tos = note let mut in_reply_tos = note
.in_reply_to .in_reply_to()
.as_ref() .as_ref()
.unwrap() .unwrap()
.as_many() .as_many()
.unwrap() .unwrap()
.iter() .iter()
.map(|i| i.as_xsd_any_uri().unwrap()); .map(|i| i.as_xsd_any_uri().unwrap());
let post_ap_id = in_reply_tos.next().unwrap().to_string(); let post_ap_id = in_reply_tos.next().unwrap();
// This post, or the parent comment might not yet exist on this server yet, fetch them. // This post, or the parent comment might not yet exist on this server yet, fetch them.
let post = get_or_fetch_and_insert_remote_post(&post_ap_id, client, pool).await?; let post = get_or_fetch_and_insert_remote_post(&post_ap_id, client, pool).await?;
@ -145,7 +145,7 @@ impl FromApub for CommentForm {
// For deeply nested comments, FromApub automatically gets called recursively // For deeply nested comments, FromApub automatically gets called recursively
let parent_id: Option<i32> = match in_reply_tos.next() { let parent_id: Option<i32> = match in_reply_tos.next() {
Some(parent_comment_uri) => { Some(parent_comment_uri) => {
let parent_comment_ap_id = &parent_comment_uri.to_string(); let parent_comment_ap_id = &parent_comment_uri;
let parent_comment = let parent_comment =
get_or_fetch_and_insert_remote_comment(&parent_comment_ap_id, client, pool).await?; get_or_fetch_and_insert_remote_comment(&parent_comment_ap_id, client, pool).await?;
@ -166,12 +166,10 @@ impl FromApub for CommentForm {
.to_string(), .to_string(),
removed: None, removed: None,
read: None, read: None,
published: note published: note.published().map(|u| u.to_owned().naive_local()),
.published() updated: note.updated().map(|u| u.to_owned().naive_local()),
.map(|u| u.as_ref().to_owned().naive_local()),
updated: note.updated().map(|u| u.as_ref().to_owned().naive_local()),
deleted: None, deleted: None,
ap_id: note.id().unwrap().to_string(), ap_id: note.id(actor_id.domain().unwrap())?.unwrap().to_string(),
local: false, local: false,
}) })
} }
@ -201,13 +199,21 @@ impl ApubObjectType for Comment {
let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?); let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?);
create create
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&id)?) .set_id(Url::parse(&id)?)
.set_to(public()) .set_to(public())
.set_many_ccs(maa.addressed_ccs.to_owned()) .set_many_ccs(maa.addressed_ccs.to_owned())
// Set the mention tags // Set the mention tags
.set_many_tags(maa.get_tags()?); .set_many_tags(maa.get_tags()?);
send_activity_to_community(&creator, &community, maa.inboxes, create, client, pool).await?; send_activity_to_community(
&creator,
&community,
maa.inboxes,
create.into_any_base()?,
client,
pool,
)
.await?;
Ok(()) Ok(())
} }
@ -233,13 +239,21 @@ impl ApubObjectType for Comment {
let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?); let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?);
update update
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&id)?) .set_id(Url::parse(&id)?)
.set_to(public()) .set_to(public())
.set_many_ccs(maa.addressed_ccs.to_owned()) .set_many_ccs(maa.addressed_ccs.to_owned())
// Set the mention tags // Set the mention tags
.set_many_tags(maa.get_tags()?); .set_many_tags(maa.get_tags()?);
send_activity_to_community(&creator, &community, maa.inboxes, update, client, pool).await?; send_activity_to_community(
&creator,
&community,
maa.inboxes,
update.into_any_base()?,
client,
pool,
)
.await?;
Ok(()) Ok(())
} }
@ -261,7 +275,7 @@ impl ApubObjectType for Comment {
let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
delete delete
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&id)?) .set_id(Url::parse(&id)?)
.set_to(public()) .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]); .set_many_ccs(vec![community.get_followers_url()]);
@ -269,7 +283,7 @@ impl ApubObjectType for Comment {
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
delete, delete.into_any_base()?,
client, client,
pool, pool,
) )
@ -296,7 +310,7 @@ impl ApubObjectType for Comment {
let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?); let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
delete delete
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&id)?) .set_id(Url::parse(&id)?)
.set_to(public()) .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]); .set_many_ccs(vec![community.get_followers_url()]);
@ -306,7 +320,7 @@ impl ApubObjectType for Comment {
let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?); let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?);
undo undo
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&undo_id)?) .set_id(Url::parse(&undo_id)?)
.set_to(public()) .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]); .set_many_ccs(vec![community.get_followers_url()]);
@ -314,7 +328,7 @@ impl ApubObjectType for Comment {
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
undo, undo.into_any_base()?,
client, client,
pool, pool,
) )
@ -340,7 +354,7 @@ impl ApubObjectType for Comment {
let mut remove = Remove::new(mod_.actor_id.to_owned(), note.into_any_base()?); let mut remove = Remove::new(mod_.actor_id.to_owned(), note.into_any_base()?);
remove remove
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&id)?) .set_id(Url::parse(&id)?)
.set_to(public()) .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]); .set_many_ccs(vec![community.get_followers_url()]);
@ -348,7 +362,7 @@ impl ApubObjectType for Comment {
&mod_, &mod_,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
remove, remove.into_any_base()?,
client, client,
pool, pool,
) )
@ -375,7 +389,7 @@ impl ApubObjectType for Comment {
let mut remove = Remove::new(mod_.actor_id.to_owned(), note.into_any_base()?); let mut remove = Remove::new(mod_.actor_id.to_owned(), note.into_any_base()?);
remove remove
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&id)?) .set_id(Url::parse(&id)?)
.set_to(public()) .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]); .set_many_ccs(vec![community.get_followers_url()]);
@ -384,7 +398,7 @@ impl ApubObjectType for Comment {
let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?); let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?);
undo undo
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&undo_id)?) .set_id(Url::parse(&undo_id)?)
.set_to(public()) .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]); .set_many_ccs(vec![community.get_followers_url()]);
@ -392,7 +406,7 @@ impl ApubObjectType for Comment {
&mod_, &mod_,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
undo, undo.into_any_base()?,
client, client,
pool, pool,
) )
@ -422,7 +436,7 @@ impl ApubLikeableType for Comment {
let mut like = Like::new(creator.actor_id.to_owned(), note.into_any_base()?); let mut like = Like::new(creator.actor_id.to_owned(), note.into_any_base()?);
like like
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&id)?) .set_id(Url::parse(&id)?)
.set_to(public()) .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]); .set_many_ccs(vec![community.get_followers_url()]);
@ -430,7 +444,7 @@ impl ApubLikeableType for Comment {
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
like, like.into_any_base()?,
client, client,
pool, pool,
) )
@ -457,7 +471,7 @@ impl ApubLikeableType for Comment {
let mut dislike = Dislike::new(creator.actor_id.to_owned(), note.into_any_base()?); let mut dislike = Dislike::new(creator.actor_id.to_owned(), note.into_any_base()?);
dislike dislike
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&id)?) .set_id(Url::parse(&id)?)
.set_to(public()) .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]); .set_many_ccs(vec![community.get_followers_url()]);
@ -465,7 +479,7 @@ impl ApubLikeableType for Comment {
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
dislike, dislike.into_any_base()?,
client, client,
pool, pool,
) )
@ -492,7 +506,7 @@ impl ApubLikeableType for Comment {
let mut like = Like::new(creator.actor_id.to_owned(), note.into_any_base()?); let mut like = Like::new(creator.actor_id.to_owned(), note.into_any_base()?);
like like
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&id)?) .set_id(Url::parse(&id)?)
.set_to(public()) .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]); .set_many_ccs(vec![community.get_followers_url()]);
@ -502,7 +516,7 @@ impl ApubLikeableType for Comment {
let mut undo = Undo::new(creator.actor_id.to_owned(), like.into_any_base()?); let mut undo = Undo::new(creator.actor_id.to_owned(), like.into_any_base()?);
undo undo
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&undo_id)?) .set_id(Url::parse(&undo_id)?)
.set_to(public()) .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]); .set_many_ccs(vec![community.get_followers_url()]);
@ -510,7 +524,7 @@ impl ApubLikeableType for Comment {
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
undo, undo.into_any_base()?,
client, client,
pool, pool,
) )

View file

@ -1,29 +1,24 @@
use crate::{ use crate::{
apub::{ apub::{
activities::{populate_object_props, send_activity}, activities::send_activity, create_apub_response, create_apub_tombstone_response,
create_apub_response, create_apub_tombstone_response, create_tombstone, create_tombstone, extensions::group_extensions::GroupExtension,
extensions::group_extensions::GroupExtension, fetcher::get_or_fetch_and_upsert_remote_user, get_shared_inbox, insert_activity, ActorType,
fetcher::get_or_fetch_and_upsert_remote_user, FromApub, GroupExt, ToApub,
get_shared_inbox, insert_activity, ActorType, FromApub, GroupExt, ToApub,
}, },
blocking, blocking,
routes::DbPoolParam, routes::DbPoolParam,
DbPool, LemmyError, DbPool, LemmyError,
}; };
use activitystreams::{
activity::{Accept, Announce, Delete, Remove, Undo},
Activity, Base, BaseBox,
};
use activitystreams_ext::Ext2; use activitystreams_ext::Ext2;
use activitystreams_new::{ use activitystreams_new::{
activity::Follow, activity::{Accept, Announce, Delete, Follow, Remove, Undo},
actor::{kind::GroupType, ApActor, Endpoints, Group}, actor::{kind::GroupType, ApActor, Endpoints, Group},
base::BaseExt, base::{AnyBase, BaseExt},
collection::UnorderedCollection, collection::UnorderedCollection,
context, context,
object::Tombstone, object::Tombstone,
prelude::*, prelude::*,
primitives::{XsdAnyUri, XsdDateTime}, public,
}; };
use actix_web::{body::Body, client::Client, web, HttpResponse}; use actix_web::{body::Body, client::Client, web, HttpResponse};
use itertools::Itertools; use itertools::Itertools;
@ -34,8 +29,8 @@ use lemmy_db::{
user::User_, user::User_,
}; };
use lemmy_utils::convert_datetime; use lemmy_utils::convert_datetime;
use serde::{Deserialize, Serialize}; use serde::Deserialize;
use std::{fmt::Debug, str::FromStr}; use url::Url;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct CommunityQuery { pub struct CommunityQuery {
@ -62,13 +57,13 @@ impl ToApub for Community {
let mut group = Group::new(); let mut group = Group::new();
group group
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&self.actor_id)?) .set_id(Url::parse(&self.actor_id)?)
.set_name(self.name.to_owned()) .set_name(self.name.to_owned())
.set_published(XsdDateTime::from(convert_datetime(self.published))) .set_published(convert_datetime(self.published))
.set_many_attributed_tos(moderators); .set_many_attributed_tos(moderators);
if let Some(u) = self.updated.to_owned() { if let Some(u) = self.updated.to_owned() {
group.set_updated(XsdDateTime::from(convert_datetime(u))); group.set_updated(convert_datetime(u));
} }
if let Some(d) = self.description.to_owned() { if let Some(d) = self.description.to_owned() {
// TODO: this should be html, also add source field with raw markdown // TODO: this should be html, also add source field with raw markdown
@ -107,14 +102,14 @@ impl ToApub for Community {
self.deleted, self.deleted,
&self.actor_id, &self.actor_id,
self.updated, self.updated,
GroupType.to_string(), GroupType::Group.to_string(),
) )
} }
} }
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl ActorType for Community { impl ActorType for Community {
fn actor_id(&self) -> String { fn actor_id_str(&self) -> String {
self.actor_id.to_owned() self.actor_id.to_owned()
} }
@ -128,27 +123,23 @@ impl ActorType for Community {
/// As a local community, accept the follow request from a remote user. /// As a local community, accept the follow request from a remote user.
async fn send_accept_follow( async fn send_accept_follow(
&self, &self,
follow: &Follow, follow: Follow,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let actor_uri = follow.actor.as_single_xsd_any_uri().unwrap().to_string(); let actor_uri = follow.actor()?.as_single_xsd_any_uri().unwrap().to_string();
let id = format!("{}/accept/{}", self.actor_id, uuid::Uuid::new_v4()); let id = format!("{}/accept/{}", self.actor_id, uuid::Uuid::new_v4());
let mut accept = Accept::new(); let mut accept = Accept::new(self.actor_id.to_owned(), follow.into_any_base()?);
accept
.object_props
.set_context_xsd_any_uri(context())?
.set_id(id)?;
accept
.accept_props
.set_actor_xsd_any_uri(self.actor_id.to_owned())?
.set_object_base_box(BaseBox::from_concrete(follow.clone())?)?;
let to = format!("{}/inbox", actor_uri); let to = format!("{}/inbox", actor_uri);
accept
.set_context(context())
.set_id(Url::parse(&id)?)
.set_to(to.clone());
insert_activity(self.creator_id, accept.clone(), true, pool).await?; insert_activity(self.creator_id, accept.clone(), true, pool).await?;
send_activity(client, &accept, self, vec![to]).await?; send_activity(client, &accept.into_any_base()?, self, vec![to]).await?;
Ok(()) Ok(())
} }
@ -162,17 +153,12 @@ impl ActorType for Community {
let id = format!("{}/delete/{}", self.actor_id, uuid::Uuid::new_v4()); let id = format!("{}/delete/{}", self.actor_id, uuid::Uuid::new_v4());
let mut delete = Delete::default(); let mut delete = Delete::new(creator.actor_id.to_owned(), group.into_any_base()?);
populate_object_props(
&mut delete.object_props,
vec![self.get_followers_url()],
&id,
)?;
delete delete
.delete_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(group)?)?; .set_to(public())
.set_many_ccs(vec![self.get_followers_url()]);
insert_activity(self.creator_id, delete.clone(), true, pool).await?; insert_activity(self.creator_id, delete.clone(), true, pool).await?;
@ -181,7 +167,7 @@ impl ActorType for Community {
// Note: For an accept, since it was automatic, no one pushed a button, // Note: For an accept, since it was automatic, no one pushed a button,
// the community was the actor. // the community was the actor.
// But for delete, the creator is the actor, and does the signing // But for delete, the creator is the actor, and does the signing
send_activity(client, &delete, creator, inboxes).await?; send_activity(client, &delete.into_any_base()?, creator, inboxes).await?;
Ok(()) Ok(())
} }
@ -195,33 +181,22 @@ impl ActorType for Community {
let id = format!("{}/delete/{}", self.actor_id, uuid::Uuid::new_v4()); let id = format!("{}/delete/{}", self.actor_id, uuid::Uuid::new_v4());
let mut delete = Delete::default(); let mut delete = Delete::new(creator.actor_id.to_owned(), group.into_any_base()?);
populate_object_props(
&mut delete.object_props,
vec![self.get_followers_url()],
&id,
)?;
delete delete
.delete_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(group)?)?; .set_to(public())
.set_many_ccs(vec![self.get_followers_url()]);
// TODO // TODO
// Undo that fake activity // Undo that fake activity
let undo_id = format!("{}/undo/delete/{}", self.actor_id, uuid::Uuid::new_v4()); let undo_id = format!("{}/undo/delete/{}", self.actor_id, uuid::Uuid::new_v4());
let mut undo = Undo::default(); let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?);
populate_object_props(
&mut undo.object_props,
vec![self.get_followers_url()],
&undo_id,
)?;
undo undo
.undo_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&undo_id)?)
.set_object_base_box(delete)?; .set_to(public())
.set_many_ccs(vec![self.get_followers_url()]);
insert_activity(self.creator_id, undo.clone(), true, pool).await?; insert_activity(self.creator_id, undo.clone(), true, pool).await?;
@ -230,7 +205,7 @@ impl ActorType for Community {
// Note: For an accept, since it was automatic, no one pushed a button, // Note: For an accept, since it was automatic, no one pushed a button,
// the community was the actor. // the community was the actor.
// But for delete, the creator is the actor, and does the signing // But for delete, the creator is the actor, and does the signing
send_activity(client, &undo, creator, inboxes).await?; send_activity(client, &undo.into_any_base()?, creator, inboxes).await?;
Ok(()) Ok(())
} }
@ -244,17 +219,12 @@ impl ActorType for Community {
let id = format!("{}/remove/{}", self.actor_id, uuid::Uuid::new_v4()); let id = format!("{}/remove/{}", self.actor_id, uuid::Uuid::new_v4());
let mut remove = Remove::default(); let mut remove = Remove::new(mod_.actor_id.to_owned(), group.into_any_base()?);
populate_object_props(
&mut remove.object_props,
vec![self.get_followers_url()],
&id,
)?;
remove remove
.remove_props .set_context(context())
.set_actor_xsd_any_uri(mod_.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(group)?)?; .set_to(public())
.set_many_ccs(vec![self.get_followers_url()]);
insert_activity(mod_.id, remove.clone(), true, pool).await?; insert_activity(mod_.id, remove.clone(), true, pool).await?;
@ -263,7 +233,7 @@ impl ActorType for Community {
// Note: For an accept, since it was automatic, no one pushed a button, // Note: For an accept, since it was automatic, no one pushed a button,
// the community was the actor. // the community was the actor.
// But for delete, the creator is the actor, and does the signing // But for delete, the creator is the actor, and does the signing
send_activity(client, &remove, mod_, inboxes).await?; send_activity(client, &remove.into_any_base()?, mod_, inboxes).await?;
Ok(()) Ok(())
} }
@ -277,32 +247,21 @@ impl ActorType for Community {
let id = format!("{}/remove/{}", self.actor_id, uuid::Uuid::new_v4()); let id = format!("{}/remove/{}", self.actor_id, uuid::Uuid::new_v4());
let mut remove = Remove::default(); let mut remove = Remove::new(mod_.actor_id.to_owned(), group.into_any_base()?);
populate_object_props(
&mut remove.object_props,
vec![self.get_followers_url()],
&id,
)?;
remove remove
.remove_props .set_context(context())
.set_actor_xsd_any_uri(mod_.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(group)?)?; .set_to(public())
.set_many_ccs(vec![self.get_followers_url()]);
// Undo that fake activity // Undo that fake activity
let undo_id = format!("{}/undo/remove/{}", self.actor_id, uuid::Uuid::new_v4()); let undo_id = format!("{}/undo/remove/{}", self.actor_id, uuid::Uuid::new_v4());
let mut undo = Undo::default(); let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?);
populate_object_props(
&mut undo.object_props,
vec![self.get_followers_url()],
&undo_id,
)?;
undo undo
.undo_props .set_context(context())
.set_actor_xsd_any_uri(mod_.actor_id.to_owned())? .set_id(Url::parse(&undo_id)?)
.set_object_base_box(remove)?; .set_to(public())
.set_many_ccs(vec![self.get_followers_url()]);
insert_activity(mod_.id, undo.clone(), true, pool).await?; insert_activity(mod_.id, undo.clone(), true, pool).await?;
@ -311,7 +270,7 @@ impl ActorType for Community {
// Note: For an accept, since it was automatic, no one pushed a button, // Note: For an accept, since it was automatic, no one pushed a button,
// the community was the actor. // the community was the actor.
// But for remove , the creator is the actor, and does the signing // But for remove , the creator is the actor, and does the signing
send_activity(client, &undo, mod_, inboxes).await?; send_activity(client, &undo.into_any_base()?, mod_, inboxes).await?;
Ok(()) Ok(())
} }
@ -325,7 +284,7 @@ impl ActorType for Community {
.await??; .await??;
let inboxes = inboxes let inboxes = inboxes
.into_iter() .into_iter()
.map(|c| get_shared_inbox(&c.user_actor_id)) .map(|c| get_shared_inbox(&Url::parse(&c.user_actor_id).unwrap()))
.filter(|s| !s.is_empty()) .filter(|s| !s.is_empty())
.unique() .unique()
.collect(); .collect();
@ -357,8 +316,13 @@ impl FromApub for CommunityForm {
type ApubType = GroupExt; type ApubType = GroupExt;
/// Parse an ActivityPub group received from another instance into a Lemmy community. /// Parse an ActivityPub group received from another instance into a Lemmy community.
async fn from_apub(group: &GroupExt, client: &Client, pool: &DbPool) -> Result<Self, LemmyError> { async fn from_apub(
let creator_and_moderator_uris = group.attributed_to().unwrap(); group: &GroupExt,
client: &Client,
pool: &DbPool,
actor_id: &Url,
) -> Result<Self, LemmyError> {
let creator_and_moderator_uris = group.inner.attributed_to().unwrap();
let creator_uri = creator_and_moderator_uris let creator_uri = creator_and_moderator_uris
.as_many() .as_many()
.unwrap() .unwrap()
@ -371,23 +335,34 @@ impl FromApub for CommunityForm {
let creator = get_or_fetch_and_upsert_remote_user(creator_uri, client, pool).await?; let creator = get_or_fetch_and_upsert_remote_user(creator_uri, client, pool).await?;
Ok(CommunityForm { Ok(CommunityForm {
name: group.name().unwrap().as_single_xsd_string().unwrap().into(), name: group
.inner
.name()
.unwrap()
.as_one()
.unwrap()
.as_xsd_string()
.unwrap()
.into(),
title: group.inner.preferred_username().unwrap().to_string(), title: group.inner.preferred_username().unwrap().to_string(),
// TODO: should be parsed as html and tags like <script> removed (or use markdown source) // TODO: should be parsed as html and tags like <script> removed (or use markdown source)
// -> same for post.content etc // -> same for post.content etc
description: group description: group
.inner
.content() .content()
.map(|s| s.as_single_xsd_string().unwrap().into()), .map(|s| s.as_single_xsd_string().unwrap().into()),
category_id: group.ext_one.category.identifier.parse::<i32>()?, category_id: group.ext_one.category.identifier.parse::<i32>()?,
creator_id: creator.id, creator_id: creator.id,
removed: None, removed: None,
published: group published: group.inner.published().map(|u| u.to_owned().naive_local()),
.published() updated: group.inner.updated().map(|u| u.to_owned().naive_local()),
.map(|u| u.as_ref().to_owned().naive_local()),
updated: group.updated().map(|u| u.as_ref().to_owned().naive_local()),
deleted: None, deleted: None,
nsfw: group.ext_one.sensitive, nsfw: group.ext_one.sensitive,
actor_id: group.id().unwrap().to_string(), actor_id: group
.inner
.id(actor_id.domain().unwrap())?
.unwrap()
.to_string(),
local: false, local: false,
private_key: None, private_key: None,
public_key: Some(group.ext_two.to_owned().public_key.public_key_pem), public_key: Some(group.ext_two.to_owned().public_key.public_key_pem),
@ -440,26 +415,20 @@ pub async fn get_apub_community_followers(
Ok(create_apub_response(&collection)) Ok(create_apub_response(&collection))
} }
pub async fn do_announce<A>( pub async fn do_announce(
activity: A, activity: AnyBase,
community: &Community, community: &Community,
sender: &dyn ActorType, sender: &dyn ActorType,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<HttpResponse, LemmyError> ) -> Result<HttpResponse, LemmyError> {
where let id = format!("{}/announce/{}", community.actor_id, uuid::Uuid::new_v4());
A: Activity + Base + Serialize + Debug, let mut announce = Announce::new(community.actor_id.to_owned(), activity);
{
let mut announce = Announce::default();
populate_object_props(
&mut announce.object_props,
vec![community.get_followers_url()],
&format!("{}/announce/{}", community.actor_id, uuid::Uuid::new_v4()),
)?;
announce announce
.announce_props .set_context(context())
.set_actor_xsd_any_uri(community.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(activity)?)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
insert_activity(community.creator_id, announce.clone(), true, pool).await?; insert_activity(community.creator_id, announce.clone(), true, pool).await?;
@ -470,7 +439,7 @@ where
// this seems to be the "easiest" stable alternative for remove_item() // this seems to be the "easiest" stable alternative for remove_item()
to.retain(|x| *x != sender.get_shared_inbox_url()); to.retain(|x| *x != sender.get_shared_inbox_url());
send_activity(client, &announce, community, to).await?; send_activity(client, &announce.into_any_base()?, community, to).await?;
Ok(HttpResponse::Ok().finish()) Ok(HttpResponse::Ok().finish())
} }

View file

@ -8,8 +8,10 @@ use crate::{
routes::{ChatServerParam, DbPoolParam}, routes::{ChatServerParam, DbPoolParam},
LemmyError, LemmyError,
}; };
use activitystreams::activity::Undo; use activitystreams_new::{
use activitystreams_new::activity::Follow; activity::{Follow, Undo},
prelude::*,
};
use actix_web::{client::Client, web, HttpRequest, HttpResponse}; use actix_web::{client::Client, web, HttpRequest, HttpResponse};
use lemmy_db::{ use lemmy_db::{
community::{Community, CommunityFollower, CommunityFollowerForm}, community::{Community, CommunityFollower, CommunityFollowerForm},
@ -31,14 +33,9 @@ impl CommunityAcceptedObjects {
fn follow(&self) -> Result<Follow, LemmyError> { fn follow(&self) -> Result<Follow, LemmyError> {
match self { match self {
CommunityAcceptedObjects::Follow(f) => Ok(f.to_owned()), CommunityAcceptedObjects::Follow(f) => Ok(f.to_owned()),
CommunityAcceptedObjects::Undo(u) => Ok( CommunityAcceptedObjects::Undo(u) => {
u.undo_props Ok(Follow::from_any_base(u.object().as_one().unwrap().to_owned())?.unwrap())
.get_object_base_box() }
.to_owned()
.unwrap()
.to_owned()
.into_concrete::<Follow>()?,
),
} }
} }
} }
@ -71,11 +68,11 @@ pub async fn community_inbox(
&community.name, &input &community.name, &input
); );
let follow = input.follow()?; let follow = input.follow()?;
let user_uri = follow.actor.as_single_xsd_any_uri().unwrap(); let user_uri = follow.actor()?.as_single_xsd_any_uri().unwrap();
let community_uri = follow.object.as_single_xsd_any_uri().unwrap().to_string(); let community_uri = follow.object().as_single_xsd_any_uri().unwrap();
let user = get_or_fetch_and_upsert_remote_user(&user_uri, &client, &db).await?; let user = get_or_fetch_and_upsert_remote_user(&user_uri, &client, &db).await?;
let community = get_or_fetch_and_upsert_remote_community(&community_uri, &client, &db).await?; let community = get_or_fetch_and_upsert_remote_community(community_uri, &client, &db).await?;
verify(&request, &user)?; verify(&request, &user)?;
@ -107,7 +104,7 @@ async fn handle_follow(
}) })
.await?; .await?;
community.send_accept_follow(&follow, &client, &db).await?; community.send_accept_follow(follow, &client, &db).await?;
Ok(HttpResponse::Ok().finish()) Ok(HttpResponse::Ok().finish())
} }

View file

@ -1,5 +1,6 @@
use crate::LemmyError; use crate::LemmyError;
use activitystreams::{ext::Extension, Actor}; use activitystreams_ext::UnparsedExtension;
use activitystreams_new::unparsed::UnparsedMutExt;
use diesel::PgConnection; use diesel::PgConnection;
use lemmy_db::{category::Category, Crud}; use lemmy_db::{category::Category, Crud};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -37,4 +38,22 @@ impl GroupExtension {
} }
} }
impl<T> Extension<T> for GroupExtension where T: Actor {} impl<U> UnparsedExtension<U> for GroupExtension
where
U: UnparsedMutExt,
{
type Error = serde_json::Error;
fn try_from_unparsed(unparsed_mut: &mut U) -> Result<Self, Self::Error> {
Ok(GroupExtension {
category: unparsed_mut.remove("category")?,
sensitive: unparsed_mut.remove("sensitive")?,
})
}
fn try_into_unparsed(self, unparsed_mut: &mut U) -> Result<(), Self::Error> {
unparsed_mut.insert("category", self.category)?;
unparsed_mut.insert("sensitive", self.sensitive)?;
Ok(())
}
}

View file

@ -1,4 +1,5 @@
use activitystreams::{ext::Extension, Base}; use activitystreams_ext::UnparsedExtension;
use activitystreams_new::unparsed::UnparsedMutExt;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
@ -8,4 +9,22 @@ pub struct PageExtension {
pub sensitive: bool, pub sensitive: bool,
} }
impl<T> Extension<T> for PageExtension where T: Base {} impl<U> UnparsedExtension<U> for PageExtension
where
U: UnparsedMutExt,
{
type Error = serde_json::Error;
fn try_from_unparsed(unparsed_mut: &mut U) -> Result<Self, Self::Error> {
Ok(PageExtension {
comments_enabled: unparsed_mut.remove("commentsEnabled")?,
sensitive: unparsed_mut.remove("sensitive")?,
})
}
fn try_into_unparsed(self, unparsed_mut: &mut U) -> Result<(), Self::Error> {
unparsed_mut.insert("commentsEnabled", self.comments_enabled)?;
unparsed_mut.insert("sensitive", self.sensitive)?;
Ok(())
}
}

View file

@ -1,5 +1,6 @@
use crate::{apub::ActorType, LemmyError}; use crate::{apub::ActorType, LemmyError};
use activitystreams::ext::Extension; use activitystreams_ext::UnparsedExtension;
use activitystreams_new::unparsed::UnparsedMutExt;
use actix_web::{client::ClientRequest, HttpRequest}; use actix_web::{client::ClientRequest, HttpRequest};
use http_signature_normalization_actix::{ use http_signature_normalization_actix::{
digest::{DigestClient, SignExt}, digest::{DigestClient, SignExt},
@ -24,7 +25,7 @@ pub async fn sign(
actor: &dyn ActorType, actor: &dyn ActorType,
activity: String, activity: String,
) -> Result<DigestClient<String>, LemmyError> { ) -> Result<DigestClient<String>, LemmyError> {
let signing_key_id = format!("{}#main-key", actor.actor_id()); let signing_key_id = format!("{}#main-key", actor.actor_id()?);
let private_key = actor.private_key(); let private_key = actor.private_key();
let digest_client = request let digest_client = request
@ -98,4 +99,20 @@ impl PublicKey {
} }
} }
impl<T> Extension<T> for PublicKeyExtension where T: activitystreams::Actor {} impl<U> UnparsedExtension<U> for PublicKeyExtension
where
U: UnparsedMutExt,
{
type Error = serde_json::Error;
fn try_from_unparsed(unparsed_mut: &mut U) -> Result<Self, Self::Error> {
Ok(PublicKeyExtension {
public_key: unparsed_mut.remove("publicKey")?,
})
}
fn try_into_unparsed(self, unparsed_mut: &mut U) -> Result<(), Self::Error> {
unparsed_mut.insert("publicKey", self.public_key)?;
Ok(())
}
}

View file

@ -6,7 +6,7 @@ use crate::{
routes::nodeinfo::{NodeInfo, NodeInfoWellKnown}, routes::nodeinfo::{NodeInfo, NodeInfoWellKnown},
DbPool, LemmyError, DbPool, LemmyError,
}; };
use activitystreams_new::{base::BaseExt, object::Note, prelude::*, primitives::XsdAnyUri}; use activitystreams_new::{base::BaseExt, object::Note, prelude::*};
use actix_web::client::Client; use actix_web::client::Client;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use diesel::{result::Error::NotFound, PgConnection}; use diesel::{result::Error::NotFound, PgConnection};
@ -133,9 +133,10 @@ pub async fn search_by_apub_id(
users: vec![], users: vec![],
}; };
let domain = query_url.domain().unwrap();
let response = match fetch_remote_object::<SearchAcceptedObjects>(client, &query_url).await? { let response = match fetch_remote_object::<SearchAcceptedObjects>(client, &query_url).await? {
SearchAcceptedObjects::Person(p) => { SearchAcceptedObjects::Person(p) => {
let user_uri = p.inner.id().unwrap(); let user_uri = p.inner.id(domain)?.unwrap();
let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?;
@ -144,10 +145,9 @@ pub async fn search_by_apub_id(
response response
} }
SearchAcceptedObjects::Group(g) => { SearchAcceptedObjects::Group(g) => {
let community_uri = g.inner.id().unwrap().to_string(); let community_uri = g.inner.id(domain)?.unwrap();
let community = let community = get_or_fetch_and_upsert_remote_community(community_uri, client, pool).await?;
get_or_fetch_and_upsert_remote_community(&community_uri, client, pool).await?;
// TODO Maybe at some point in the future, fetch all the history of a community // TODO Maybe at some point in the future, fetch all the history of a community
// fetch_community_outbox(&c, conn)?; // fetch_community_outbox(&c, conn)?;
@ -161,7 +161,7 @@ pub async fn search_by_apub_id(
response response
} }
SearchAcceptedObjects::Page(p) => { SearchAcceptedObjects::Page(p) => {
let post_form = PostForm::from_apub(&p, client, pool).await?; let post_form = PostForm::from_apub(&p, client, pool, &query_url).await?;
let p = blocking(pool, move |conn| upsert_post(&post_form, conn)).await??; let p = blocking(pool, move |conn| upsert_post(&post_form, conn)).await??;
response.posts = vec![blocking(pool, move |conn| PostView::read(conn, p.id, None)).await??]; response.posts = vec![blocking(pool, move |conn| PostView::read(conn, p.id, None)).await??];
@ -169,13 +169,13 @@ pub async fn search_by_apub_id(
response response
} }
SearchAcceptedObjects::Comment(c) => { SearchAcceptedObjects::Comment(c) => {
let post_url = c.in_reply_to.as_ref().unwrap().as_many().unwrap(); let post_url = c.in_reply_to().as_ref().unwrap().as_many().unwrap();
// TODO: also fetch parent comments if any // TODO: also fetch parent comments if any
let x = post_url.first().unwrap().as_xsd_any_uri().unwrap(); let x = post_url.first().unwrap().as_xsd_any_uri().unwrap();
let post = fetch_remote_object(client, x.as_url()).await?; let post = fetch_remote_object(client, x).await?;
let post_form = PostForm::from_apub(&post, client, pool).await?; let post_form = PostForm::from_apub(&post, client, pool, &query_url).await?;
let comment_form = CommentForm::from_apub(&c, client, pool).await?; let comment_form = CommentForm::from_apub(&c, client, pool, &query_url).await?;
blocking(pool, move |conn| upsert_post(&post_form, conn)).await??; blocking(pool, move |conn| upsert_post(&post_form, conn)).await??;
let c = blocking(pool, move |conn| upsert_comment(&comment_form, conn)).await??; let c = blocking(pool, move |conn| upsert_comment(&comment_form, conn)).await??;
@ -191,7 +191,7 @@ pub async fn search_by_apub_id(
/// Check if a remote user exists, create if not found, if its too old update it.Fetch a user, insert/update it in the database and return the user. /// Check if a remote user exists, create if not found, if its too old update it.Fetch a user, insert/update it in the database and return the user.
pub async fn get_or_fetch_and_upsert_remote_user( pub async fn get_or_fetch_and_upsert_remote_user(
apub_id: &XsdAnyUri, apub_id: &Url,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<User_, LemmyError> { ) -> Result<User_, LemmyError> {
@ -205,9 +205,9 @@ pub async fn get_or_fetch_and_upsert_remote_user(
// If its older than a day, re-fetch it // If its older than a day, re-fetch it
Ok(u) if !u.local && should_refetch_actor(u.last_refreshed_at) => { Ok(u) if !u.local && should_refetch_actor(u.last_refreshed_at) => {
debug!("Fetching and updating from remote user: {}", apub_id); debug!("Fetching and updating from remote user: {}", apub_id);
let person = fetch_remote_object::<PersonExt>(client, apub_id.as_url()).await?; let person = fetch_remote_object::<PersonExt>(client, apub_id).await?;
let mut uf = UserForm::from_apub(&person, client, pool).await?; let mut uf = UserForm::from_apub(&person, client, pool, apub_id).await?;
uf.last_refreshed_at = Some(naive_now()); uf.last_refreshed_at = Some(naive_now());
let user = blocking(pool, move |conn| User_::update(conn, u.id, &uf)).await??; let user = blocking(pool, move |conn| User_::update(conn, u.id, &uf)).await??;
@ -216,9 +216,9 @@ pub async fn get_or_fetch_and_upsert_remote_user(
Ok(u) => Ok(u), Ok(u) => Ok(u),
Err(NotFound {}) => { Err(NotFound {}) => {
debug!("Fetching and creating remote user: {}", apub_id); debug!("Fetching and creating remote user: {}", apub_id);
let person = fetch_remote_object::<PersonExt>(client, apub_id.as_url()).await?; let person = fetch_remote_object::<PersonExt>(client, apub_id).await?;
let uf = UserForm::from_apub(&person, client, pool).await?; let uf = UserForm::from_apub(&person, client, pool, apub_id).await?;
let user = blocking(pool, move |conn| User_::create(conn, &uf)).await??; let user = blocking(pool, move |conn| User_::create(conn, &uf)).await??;
Ok(user) Ok(user)
@ -243,22 +243,22 @@ fn should_refetch_actor(last_refreshed: NaiveDateTime) -> bool {
/// Check if a remote community exists, create if not found, if its too old update it.Fetch a community, insert/update it in the database and return the community. /// Check if a remote community exists, create if not found, if its too old update it.Fetch a community, insert/update it in the database and return the community.
pub async fn get_or_fetch_and_upsert_remote_community( pub async fn get_or_fetch_and_upsert_remote_community(
apub_id: &str, apub_id: &Url,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<Community, LemmyError> { ) -> Result<Community, LemmyError> {
let apub_id_owned = apub_id.to_owned(); let apub_id_owned = apub_id.to_owned();
let community = blocking(pool, move |conn| { let community = blocking(pool, move |conn| {
Community::read_from_actor_id(conn, &apub_id_owned) Community::read_from_actor_id(conn, apub_id_owned.as_str())
}) })
.await?; .await?;
match community { match community {
Ok(c) if !c.local && should_refetch_actor(c.last_refreshed_at) => { Ok(c) if !c.local && should_refetch_actor(c.last_refreshed_at) => {
debug!("Fetching and updating from remote community: {}", apub_id); debug!("Fetching and updating from remote community: {}", apub_id);
let group = fetch_remote_object::<GroupExt>(client, &Url::parse(apub_id)?).await?; let group = fetch_remote_object::<GroupExt>(client, apub_id).await?;
let mut cf = CommunityForm::from_apub(&group, client, pool).await?; let mut cf = CommunityForm::from_apub(&group, client, pool, apub_id).await?;
cf.last_refreshed_at = Some(naive_now()); cf.last_refreshed_at = Some(naive_now());
let community = blocking(pool, move |conn| Community::update(conn, c.id, &cf)).await??; let community = blocking(pool, move |conn| Community::update(conn, c.id, &cf)).await??;
@ -267,14 +267,14 @@ pub async fn get_or_fetch_and_upsert_remote_community(
Ok(c) => Ok(c), Ok(c) => Ok(c),
Err(NotFound {}) => { Err(NotFound {}) => {
debug!("Fetching and creating remote community: {}", apub_id); debug!("Fetching and creating remote community: {}", apub_id);
let group = fetch_remote_object::<GroupExt>(client, &Url::parse(apub_id)?).await?; let group = fetch_remote_object::<GroupExt>(client, apub_id).await?;
let cf = CommunityForm::from_apub(&group, client, pool).await?; let cf = CommunityForm::from_apub(&group, client, pool, apub_id).await?;
let community = blocking(pool, move |conn| Community::create(conn, &cf)).await??; let community = blocking(pool, move |conn| Community::create(conn, &cf)).await??;
// Also add the community moderators too // Also add the community moderators too
let attributed_to = group.inner.attributed_to().unwrap(); let attributed_to = group.inner.attributed_to().unwrap();
let creator_and_moderator_uris: Vec<&XsdAnyUri> = attributed_to let creator_and_moderator_uris: Vec<&Url> = attributed_to
.as_many() .as_many()
.unwrap() .unwrap()
.iter() .iter()
@ -319,13 +319,13 @@ fn upsert_post(post_form: &PostForm, conn: &PgConnection) -> Result<Post, LemmyE
} }
pub async fn get_or_fetch_and_insert_remote_post( pub async fn get_or_fetch_and_insert_remote_post(
post_ap_id: &str, post_ap_id: &Url,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<Post, LemmyError> { ) -> Result<Post, LemmyError> {
let post_ap_id_owned = post_ap_id.to_owned(); let post_ap_id_owned = post_ap_id.to_owned();
let post = blocking(pool, move |conn| { let post = blocking(pool, move |conn| {
Post::read_from_apub_id(conn, &post_ap_id_owned) Post::read_from_apub_id(conn, post_ap_id_owned.as_str())
}) })
.await?; .await?;
@ -333,8 +333,8 @@ pub async fn get_or_fetch_and_insert_remote_post(
Ok(p) => Ok(p), Ok(p) => Ok(p),
Err(NotFound {}) => { Err(NotFound {}) => {
debug!("Fetching and creating remote post: {}", post_ap_id); debug!("Fetching and creating remote post: {}", post_ap_id);
let post = fetch_remote_object::<PageExt>(client, &Url::parse(post_ap_id)?).await?; let post = fetch_remote_object::<PageExt>(client, post_ap_id).await?;
let post_form = PostForm::from_apub(&post, client, pool).await?; let post_form = PostForm::from_apub(&post, client, pool, post_ap_id).await?;
let post = blocking(pool, move |conn| Post::create(conn, &post_form)).await??; let post = blocking(pool, move |conn| Post::create(conn, &post_form)).await??;
@ -354,13 +354,13 @@ fn upsert_comment(comment_form: &CommentForm, conn: &PgConnection) -> Result<Com
} }
pub async fn get_or_fetch_and_insert_remote_comment( pub async fn get_or_fetch_and_insert_remote_comment(
comment_ap_id: &str, comment_ap_id: &Url,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<Comment, LemmyError> { ) -> Result<Comment, LemmyError> {
let comment_ap_id_owned = comment_ap_id.to_owned(); let comment_ap_id_owned = comment_ap_id.to_owned();
let comment = blocking(pool, move |conn| { let comment = blocking(pool, move |conn| {
Comment::read_from_apub_id(conn, &comment_ap_id_owned) Comment::read_from_apub_id(conn, comment_ap_id_owned.as_str())
}) })
.await?; .await?;
@ -371,8 +371,8 @@ pub async fn get_or_fetch_and_insert_remote_comment(
"Fetching and creating remote comment and its parents: {}", "Fetching and creating remote comment and its parents: {}",
comment_ap_id comment_ap_id
); );
let comment = fetch_remote_object::<Note>(client, &Url::parse(comment_ap_id)?).await?; let comment = fetch_remote_object::<Note>(client, comment_ap_id).await?;
let comment_form = CommentForm::from_apub(&comment, client, pool).await?; let comment_form = CommentForm::from_apub(&comment, client, pool, comment_ap_id).await?;
let comment = blocking(pool, move |conn| Comment::create(conn, &comment_form)).await??; let comment = blocking(pool, move |conn| Comment::create(conn, &comment_form)).await??;

View file

@ -27,7 +27,6 @@ use activitystreams_new::{
actor::{ApActor, Group, Person}, actor::{ApActor, Group, Person},
object::{Page, Tombstone}, object::{Page, Tombstone},
prelude::*, prelude::*,
primitives::XsdAnyUri,
}; };
use actix_web::{body::Body, client::Client, HttpResponse}; use actix_web::{body::Body, client::Client, HttpResponse};
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
@ -36,8 +35,7 @@ use lemmy_db::{activity::do_insert_activity, user::User_};
use lemmy_utils::{convert_datetime, get_apub_protocol_string, settings::Settings, MentionData}; use lemmy_utils::{convert_datetime, get_apub_protocol_string, settings::Settings, MentionData};
use log::debug; use log::debug;
use serde::Serialize; use serde::Serialize;
use std::str::FromStr; use url::{ParseError, Url};
use url::Url;
type GroupExt = Ext2<ApActor<Group>, GroupExtension, PublicKeyExtension>; type GroupExt = Ext2<ApActor<Group>, GroupExtension, PublicKeyExtension>;
type PersonExt = Ext1<ApActor<Person>, PublicKeyExtension>; type PersonExt = Ext1<ApActor<Person>, PublicKeyExtension>;
@ -115,7 +113,7 @@ fn create_tombstone(
let mut tombstone = Tombstone::new(); let mut tombstone = Tombstone::new();
tombstone.set_id(object_id.parse()?); tombstone.set_id(object_id.parse()?);
tombstone.set_former_type(former_type); tombstone.set_former_type(former_type);
tombstone.set_deleted(convert_datetime(updated).into()); tombstone.set_deleted(convert_datetime(updated));
Ok(tombstone) Ok(tombstone)
} else { } else {
Err(format_err!("Cant convert to tombstone because updated time was None.").into()) Err(format_err!("Cant convert to tombstone because updated time was None.").into())
@ -132,6 +130,7 @@ pub trait FromApub {
apub: &Self::ApubType, apub: &Self::ApubType,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
actor_id: &Url,
) -> Result<Self, LemmyError> ) -> Result<Self, LemmyError>
where where
Self: Sized; Self: Sized;
@ -199,13 +198,12 @@ pub trait ApubLikeableType {
) -> Result<(), LemmyError>; ) -> Result<(), LemmyError>;
} }
pub fn get_shared_inbox(actor_id: &str) -> String { pub fn get_shared_inbox(actor_id: &Url) -> String {
let url = Url::parse(actor_id).unwrap();
format!( format!(
"{}://{}{}/inbox", "{}://{}{}/inbox",
&url.scheme(), &actor_id.scheme(),
&url.host_str().unwrap(), &actor_id.host_str().unwrap(),
if let Some(port) = url.port() { if let Some(port) = actor_id.port() {
format!(":{}", port) format!(":{}", port)
} else { } else {
"".to_string() "".to_string()
@ -215,7 +213,7 @@ pub fn get_shared_inbox(actor_id: &str) -> String {
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
pub trait ActorType { pub trait ActorType {
fn actor_id(&self) -> String; fn actor_id_str(&self) -> String;
fn public_key(&self) -> String; fn public_key(&self) -> String;
fn private_key(&self) -> String; fn private_key(&self) -> String;
@ -239,7 +237,7 @@ pub trait ActorType {
#[allow(unused_variables)] #[allow(unused_variables)]
async fn send_accept_follow( async fn send_accept_follow(
&self, &self,
follow: &Follow, follow: Follow,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<(), LemmyError>; ) -> Result<(), LemmyError>;
@ -273,35 +271,40 @@ pub trait ActorType {
/// For a given community, returns the inboxes of all followers. /// For a given community, returns the inboxes of all followers.
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<String>, LemmyError>; async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<String>, LemmyError>;
// TODO move these to the db rows fn actor_id(&self) -> Result<Url, ParseError> {
fn get_inbox_url(&self) -> String { Url::parse(&self.actor_id_str())
format!("{}/inbox", &self.actor_id())
} }
// TODO move these to the db rows
fn get_inbox_url(&self) -> String {
format!("{}/inbox", &self.actor_id_str())
}
// TODO: make this return `Result<Url, ParseError>
fn get_shared_inbox_url(&self) -> String { fn get_shared_inbox_url(&self) -> String {
get_shared_inbox(&self.actor_id()) get_shared_inbox(&self.actor_id().unwrap())
} }
fn get_outbox_url(&self) -> String { fn get_outbox_url(&self) -> String {
format!("{}/outbox", &self.actor_id()) format!("{}/outbox", &self.actor_id_str())
} }
fn get_followers_url(&self) -> String { fn get_followers_url(&self) -> String {
format!("{}/followers", &self.actor_id()) format!("{}/followers", &self.actor_id_str())
} }
fn get_following_url(&self) -> String { fn get_following_url(&self) -> String {
format!("{}/following", &self.actor_id()) format!("{}/following", &self.actor_id_str())
} }
fn get_liked_url(&self) -> String { fn get_liked_url(&self) -> String {
format!("{}/liked", &self.actor_id()) format!("{}/liked", &self.actor_id_str())
} }
fn get_public_key_ext(&self) -> PublicKeyExtension { fn get_public_key_ext(&self) -> PublicKeyExtension {
PublicKey { PublicKey {
id: format!("{}#main-key", self.actor_id()), id: format!("{}#main-key", self.actor_id_str()),
owner: self.actor_id(), owner: self.actor_id_str(),
public_key_pem: self.public_key(), public_key_pem: self.public_key(),
} }
.to_ext() .to_ext()
@ -311,7 +314,7 @@ pub trait ActorType {
pub async fn fetch_webfinger_url( pub async fn fetch_webfinger_url(
mention: &MentionData, mention: &MentionData,
client: &Client, client: &Client,
) -> Result<XsdAnyUri, LemmyError> { ) -> Result<Url, LemmyError> {
let fetch_url = format!( let fetch_url = format!(
"{}://{}/.well-known/webfinger?resource=acct:{}@{}", "{}://{}/.well-known/webfinger?resource=acct:{}@{}",
get_apub_protocol_string(), get_apub_protocol_string(),
@ -336,7 +339,7 @@ pub async fn fetch_webfinger_url(
link link
.href .href
.to_owned() .to_owned()
.map(|u| XsdAnyUri::from_str(&u)) .map(|u| Url::parse(&u))
.transpose()? .transpose()?
.ok_or_else(|| format_err!("No href found.").into()) .ok_or_else(|| format_err!("No href found.").into())
} }

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
apub::{ apub::{
activities::{populate_object_props, send_activity_to_community}, activities::send_activity_to_community,
create_apub_response, create_apub_tombstone_response, create_tombstone, create_apub_response, create_apub_tombstone_response, create_tombstone,
extensions::page_extension::PageExtension, extensions::page_extension::PageExtension,
fetcher::{get_or_fetch_and_upsert_remote_community, get_or_fetch_and_upsert_remote_user}, fetcher::{get_or_fetch_and_upsert_remote_community, get_or_fetch_and_upsert_remote_user},
@ -10,16 +10,13 @@ use crate::{
routes::DbPoolParam, routes::DbPoolParam,
DbPool, LemmyError, DbPool, LemmyError,
}; };
use activitystreams::{
activity::{Create, Delete, Dislike, Like, Remove, Undo, Update},
BaseBox,
};
use activitystreams_ext::Ext1; use activitystreams_ext::Ext1;
use activitystreams_new::{ use activitystreams_new::{
activity::{Create, Delete, Dislike, Like, Remove, Undo, Update},
context, context,
object::{kind::PageType, Image, Page, Tombstone}, object::{kind::PageType, Image, Page, Tombstone},
prelude::*, prelude::*,
primitives::{XsdAnyUri, XsdDateTime}, public,
}; };
use actix_web::{body::Body, client::Client, web, HttpResponse}; use actix_web::{body::Body, client::Client, web, HttpResponse};
use lemmy_db::{ use lemmy_db::{
@ -30,6 +27,7 @@ use lemmy_db::{
}; };
use lemmy_utils::{convert_datetime, get_apub_protocol_string, settings::Settings}; use lemmy_utils::{convert_datetime, get_apub_protocol_string, settings::Settings};
use serde::Deserialize; use serde::Deserialize;
use url::Url;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct PostQuery { pub struct PostQuery {
@ -70,11 +68,11 @@ impl ToApub for Post {
// TODO: need to set proper context defining sensitive/commentsEnabled fields // TODO: need to set proper context defining sensitive/commentsEnabled fields
// https://git.asonix.dog/Aardwolf/activitystreams/issues/5 // https://git.asonix.dog/Aardwolf/activitystreams/issues/5
.set_context(context()) .set_context(context())
.set_id(self.ap_id.parse::<XsdAnyUri>()?) .set_id(self.ap_id.parse::<Url>()?)
// Use summary field to be consistent with mastodon content warning. // Use summary field to be consistent with mastodon content warning.
// https://mastodon.xyz/@Louisa/103987265222901387.json // https://mastodon.xyz/@Louisa/103987265222901387.json
.set_summary(self.name.to_owned()) .set_summary(self.name.to_owned())
.set_published(convert_datetime(self.published).into()) .set_published(convert_datetime(self.published))
.set_to(community.actor_id) .set_to(community.actor_id)
.set_attributed_to(creator.actor_id); .set_attributed_to(creator.actor_id);
@ -121,7 +119,7 @@ impl ToApub for Post {
} }
if let Some(u) = self.updated { if let Some(u) = self.updated {
page.set_updated(XsdDateTime::from(convert_datetime(u))); page.set_updated(convert_datetime(u));
} }
let ext = PageExtension { let ext = PageExtension {
@ -136,7 +134,7 @@ impl ToApub for Post {
self.deleted, self.deleted,
&self.ap_id, &self.ap_id,
self.updated, self.updated,
PageType.to_string(), PageType::Page.to_string(),
) )
} }
} }
@ -150,11 +148,12 @@ impl FromApub for PostForm {
page: &PageExt, page: &PageExt,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
actor_id: &Url,
) -> Result<PostForm, LemmyError> { ) -> Result<PostForm, LemmyError> {
let ext = &page.ext_one; let ext = &page.ext_one;
let creator_actor_id = page let creator_actor_id = page
.inner .inner
.attributed_to .attributed_to()
.as_ref() .as_ref()
.unwrap() .unwrap()
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
@ -164,20 +163,19 @@ impl FromApub for PostForm {
let community_actor_id = page let community_actor_id = page
.inner .inner
.to .to()
.as_ref() .as_ref()
.unwrap() .unwrap()
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.unwrap() .unwrap();
.as_str();
let community = let community =
get_or_fetch_and_upsert_remote_community(community_actor_id, client, pool).await?; get_or_fetch_and_upsert_remote_community(community_actor_id, client, pool).await?;
let thumbnail_url = match &page.inner.image { let thumbnail_url = match &page.inner.image() {
Some(any_image) => Image::from_any_base(any_image.to_owned().as_one().unwrap().to_owned())? Some(any_image) => Image::from_any_base(any_image.to_owned().as_one().unwrap().to_owned())?
.unwrap() .unwrap()
.url .url()
.unwrap() .unwrap()
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.map(|u| u.to_string()), .map(|u| u.to_string()),
@ -186,10 +184,10 @@ impl FromApub for PostForm {
let (embed_title, embed_description, embed_html) = match page.inner.preview() { let (embed_title, embed_description, embed_html) = match page.inner.preview() {
Some(preview) => { Some(preview) => {
let preview_page = Page::from_any_base(preview.as_one().unwrap().to_owned())?.unwrap(); let preview_page = Page::from_any_base(preview.one().unwrap().to_owned())?.unwrap();
let name = preview_page let name = preview_page
.name() .name()
.map(|n| n.as_single_xsd_string().unwrap().to_string()); .map(|n| n.as_one().unwrap().as_xsd_string().unwrap().to_string());
let summary = preview_page let summary = preview_page
.summary() .summary()
.map(|s| s.as_single_xsd_string().unwrap().to_string()); .map(|s| s.as_single_xsd_string().unwrap().to_string());
@ -203,18 +201,18 @@ impl FromApub for PostForm {
let url = page let url = page
.inner .inner
.url .url()
.as_ref() .as_ref()
.map(|u| u.as_single_xsd_string().unwrap().to_string()); .map(|u| u.as_single_xsd_string().unwrap().to_string());
let body = page let body = page
.inner .inner
.content .content()
.as_ref() .as_ref()
.map(|c| c.as_single_xsd_string().unwrap().to_string()); .map(|c| c.as_single_xsd_string().unwrap().to_string());
Ok(PostForm { Ok(PostForm {
name: page name: page
.inner .inner
.summary .summary()
.as_ref() .as_ref()
.unwrap() .unwrap()
.as_single_xsd_string() .as_single_xsd_string()
@ -228,14 +226,14 @@ impl FromApub for PostForm {
locked: Some(!ext.comments_enabled), locked: Some(!ext.comments_enabled),
published: page published: page
.inner .inner
.published .published()
.as_ref() .as_ref()
.map(|u| u.as_ref().to_owned().naive_local()), .map(|u| u.to_owned().naive_local()),
updated: page updated: page
.inner .inner
.updated .updated()
.as_ref() .as_ref()
.map(|u| u.as_ref().to_owned().naive_local()), .map(|u| u.to_owned().naive_local()),
deleted: None, deleted: None,
nsfw: ext.sensitive, nsfw: ext.sensitive,
stickied: None, // -> put it in "featured" collection of the community stickied: None, // -> put it in "featured" collection of the community
@ -243,7 +241,11 @@ impl FromApub for PostForm {
embed_description, embed_description,
embed_html, embed_html,
thumbnail_url, thumbnail_url,
ap_id: page.inner.id().unwrap().to_string(), ap_id: page
.inner
.id(actor_id.domain().unwrap())?
.unwrap()
.to_string(),
local: false, local: false,
}) })
} }
@ -265,22 +267,18 @@ impl ApubObjectType for Post {
let id = format!("{}/create/{}", self.ap_id, uuid::Uuid::new_v4()); let id = format!("{}/create/{}", self.ap_id, uuid::Uuid::new_v4());
let mut create = Create::new(); let mut create = Create::new(creator.actor_id.to_owned(), page.into_any_base()?);
populate_object_props(
&mut create.object_props,
vec![community.get_followers_url()],
&id,
)?;
create create
.create_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(page)?)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
send_activity_to_community( send_activity_to_community(
creator, creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
create, create.into_any_base()?,
client, client,
pool, pool,
) )
@ -302,22 +300,18 @@ impl ApubObjectType for Post {
let id = format!("{}/update/{}", self.ap_id, uuid::Uuid::new_v4()); let id = format!("{}/update/{}", self.ap_id, uuid::Uuid::new_v4());
let mut update = Update::new(); let mut update = Update::new(creator.actor_id.to_owned(), page.into_any_base()?);
populate_object_props(
&mut update.object_props,
vec![community.get_followers_url()],
&id,
)?;
update update
.update_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(page)?)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
send_activity_to_community( send_activity_to_community(
creator, creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
update, update.into_any_base()?,
client, client,
pool, pool,
) )
@ -337,24 +331,18 @@ impl ApubObjectType for Post {
let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??;
let id = format!("{}/delete/{}", self.ap_id, uuid::Uuid::new_v4()); let id = format!("{}/delete/{}", self.ap_id, uuid::Uuid::new_v4());
let mut delete = Delete::default(); let mut delete = Delete::new(creator.actor_id.to_owned(), page.into_any_base()?);
populate_object_props(
&mut delete.object_props,
vec![community.get_followers_url()],
&id,
)?;
delete delete
.delete_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(page)?)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
send_activity_to_community( send_activity_to_community(
creator, creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
delete, delete.into_any_base()?,
client, client,
pool, pool,
) )
@ -374,40 +362,28 @@ impl ApubObjectType for Post {
let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??;
let id = format!("{}/delete/{}", self.ap_id, uuid::Uuid::new_v4()); let id = format!("{}/delete/{}", self.ap_id, uuid::Uuid::new_v4());
let mut delete = Delete::default(); let mut delete = Delete::new(creator.actor_id.to_owned(), page.into_any_base()?);
populate_object_props(
&mut delete.object_props,
vec![community.get_followers_url()],
&id,
)?;
delete delete
.delete_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(page)?)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
// TODO // TODO
// Undo that fake activity // Undo that fake activity
let undo_id = format!("{}/undo/delete/{}", self.ap_id, uuid::Uuid::new_v4()); let undo_id = format!("{}/undo/delete/{}", self.ap_id, uuid::Uuid::new_v4());
let mut undo = Undo::default(); let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?);
populate_object_props(
&mut undo.object_props,
vec![community.get_followers_url()],
&undo_id,
)?;
undo undo
.undo_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&undo_id)?)
.set_object_base_box(delete)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
send_activity_to_community( send_activity_to_community(
creator, creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
undo, undo.into_any_base()?,
client, client,
pool, pool,
) )
@ -427,24 +403,18 @@ impl ApubObjectType for Post {
let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??;
let id = format!("{}/remove/{}", self.ap_id, uuid::Uuid::new_v4()); let id = format!("{}/remove/{}", self.ap_id, uuid::Uuid::new_v4());
let mut remove = Remove::default(); let mut remove = Remove::new(mod_.actor_id.to_owned(), page.into_any_base()?);
populate_object_props(
&mut remove.object_props,
vec![community.get_followers_url()],
&id,
)?;
remove remove
.remove_props .set_context(context())
.set_actor_xsd_any_uri(mod_.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(page)?)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
send_activity_to_community( send_activity_to_community(
mod_, mod_,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
remove, remove.into_any_base()?,
client, client,
pool, pool,
) )
@ -464,39 +434,27 @@ impl ApubObjectType for Post {
let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??; let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??;
let id = format!("{}/remove/{}", self.ap_id, uuid::Uuid::new_v4()); let id = format!("{}/remove/{}", self.ap_id, uuid::Uuid::new_v4());
let mut remove = Remove::default(); let mut remove = Remove::new(mod_.actor_id.to_owned(), page.into_any_base()?);
populate_object_props(
&mut remove.object_props,
vec![community.get_followers_url()],
&id,
)?;
remove remove
.remove_props .set_context(context())
.set_actor_xsd_any_uri(mod_.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(page)?)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
// Undo that fake activity // Undo that fake activity
let undo_id = format!("{}/undo/remove/{}", self.ap_id, uuid::Uuid::new_v4()); let undo_id = format!("{}/undo/remove/{}", self.ap_id, uuid::Uuid::new_v4());
let mut undo = Undo::default(); let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?);
populate_object_props(
&mut undo.object_props,
vec![community.get_followers_url()],
&undo_id,
)?;
undo undo
.undo_props .set_context(context())
.set_actor_xsd_any_uri(mod_.actor_id.to_owned())? .set_id(Url::parse(&undo_id)?)
.set_object_base_box(remove)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
send_activity_to_community( send_activity_to_community(
mod_, mod_,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
undo, undo.into_any_base()?,
client, client,
pool, pool,
) )
@ -520,22 +478,18 @@ impl ApubLikeableType for Post {
let id = format!("{}/like/{}", self.ap_id, uuid::Uuid::new_v4()); let id = format!("{}/like/{}", self.ap_id, uuid::Uuid::new_v4());
let mut like = Like::new(); let mut like = Like::new(creator.actor_id.to_owned(), page.into_any_base()?);
populate_object_props(
&mut like.object_props,
vec![community.get_followers_url()],
&id,
)?;
like like
.like_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(page)?)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
send_activity_to_community( send_activity_to_community(
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
like, like.into_any_base()?,
client, client,
pool, pool,
) )
@ -556,22 +510,18 @@ impl ApubLikeableType for Post {
let id = format!("{}/dislike/{}", self.ap_id, uuid::Uuid::new_v4()); let id = format!("{}/dislike/{}", self.ap_id, uuid::Uuid::new_v4());
let mut dislike = Dislike::new(); let mut dislike = Dislike::new(creator.actor_id.to_owned(), page.into_any_base()?);
populate_object_props(
&mut dislike.object_props,
vec![community.get_followers_url()],
&id,
)?;
dislike dislike
.dislike_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(page)?)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
send_activity_to_community( send_activity_to_community(
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
dislike, dislike.into_any_base()?,
client, client,
pool, pool,
) )
@ -592,38 +542,28 @@ impl ApubLikeableType for Post {
let id = format!("{}/like/{}", self.ap_id, uuid::Uuid::new_v4()); let id = format!("{}/like/{}", self.ap_id, uuid::Uuid::new_v4());
let mut like = Like::new(); let mut like = Like::new(creator.actor_id.to_owned(), page.into_any_base()?);
populate_object_props(
&mut like.object_props,
vec![community.get_followers_url()],
&id,
)?;
like like
.like_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(BaseBox::from_concrete(page)?)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
// TODO // TODO
// Undo that fake activity // Undo that fake activity
let undo_id = format!("{}/undo/like/{}", self.ap_id, uuid::Uuid::new_v4()); let undo_id = format!("{}/undo/like/{}", self.ap_id, uuid::Uuid::new_v4());
let mut undo = Undo::default(); let mut undo = Undo::new(creator.actor_id.to_owned(), like.into_any_base()?);
populate_object_props(
&mut undo.object_props,
vec![community.get_followers_url()],
&undo_id,
)?;
undo undo
.undo_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&undo_id)?)
.set_object_base_box(like)?; .set_to(public())
.set_many_ccs(vec![community.get_followers_url()]);
send_activity_to_community( send_activity_to_community(
&creator, &creator,
&community, &community,
vec![community.get_shared_inbox_url()], vec![community.get_shared_inbox_url()],
undo, undo.into_any_base()?,
client, client,
pool, pool,
) )

View file

@ -5,12 +5,12 @@ use crate::{
}, },
blocking, DbPool, LemmyError, blocking, DbPool, LemmyError,
}; };
use activitystreams::{ use activitystreams_new::{
activity::{Create, Delete, Undo, Update}, activity::{Create, Delete, Undo, Update},
context, context,
object::{kind::NoteType, properties::ObjectProperties, Note}, object::{kind::NoteType, Note, Tombstone},
prelude::*,
}; };
use activitystreams_new::object::Tombstone;
use actix_web::client::Client; use actix_web::client::Client;
use lemmy_db::{ use lemmy_db::{
private_message::{PrivateMessage, PrivateMessageForm}, private_message::{PrivateMessage, PrivateMessageForm},
@ -18,14 +18,14 @@ use lemmy_db::{
Crud, Crud,
}; };
use lemmy_utils::convert_datetime; use lemmy_utils::convert_datetime;
use url::Url;
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl ToApub for PrivateMessage { impl ToApub for PrivateMessage {
type Response = Note; type Response = Note;
async fn to_apub(&self, pool: &DbPool) -> Result<Note, LemmyError> { async fn to_apub(&self, pool: &DbPool) -> Result<Note, LemmyError> {
let mut private_message = Note::default(); let mut private_message = Note::new();
let oprops: &mut ObjectProperties = private_message.as_mut();
let creator_id = self.creator_id; let creator_id = self.creator_id;
let creator = blocking(pool, move |conn| User_::read(conn, creator_id)).await??; let creator = blocking(pool, move |conn| User_::read(conn, creator_id)).await??;
@ -33,16 +33,16 @@ impl ToApub for PrivateMessage {
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
oprops private_message
.set_context_xsd_any_uri(context())? .set_context(context())
.set_id(self.ap_id.to_owned())? .set_id(Url::parse(&self.ap_id.to_owned())?)
.set_published(convert_datetime(self.published))? .set_published(convert_datetime(self.published))
.set_content_xsd_string(self.content.to_owned())? .set_content(self.content.to_owned())
.set_to_xsd_any_uri(recipient.actor_id)? .set_to(recipient.actor_id)
.set_attributed_to_xsd_any_uri(creator.actor_id)?; .set_attributed_to(creator.actor_id);
if let Some(u) = self.updated { if let Some(u) = self.updated {
oprops.set_updated(convert_datetime(u))?; private_message.set_updated(convert_datetime(u));
} }
Ok(private_message) Ok(private_message)
@ -53,7 +53,7 @@ impl ToApub for PrivateMessage {
self.deleted, self.deleted,
&self.ap_id, &self.ap_id,
self.updated, self.updated,
NoteType.to_string(), NoteType::Note.to_string(),
) )
} }
} }
@ -67,32 +67,35 @@ impl FromApub for PrivateMessageForm {
note: &Note, note: &Note,
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
actor_id: &Url,
) -> Result<PrivateMessageForm, LemmyError> { ) -> Result<PrivateMessageForm, LemmyError> {
let oprops = &note.object_props; let creator_actor_id = note
let creator_actor_id = &oprops.get_attributed_to_xsd_any_uri().unwrap(); .attributed_to()
.unwrap()
.clone()
.single_xsd_any_uri()
.unwrap();
let creator = get_or_fetch_and_upsert_remote_user(&creator_actor_id, client, pool).await?; let creator = get_or_fetch_and_upsert_remote_user(&creator_actor_id, client, pool).await?;
let recipient_actor_id = &oprops.get_to_xsd_any_uri().unwrap(); let recipient_actor_id = note.to().unwrap().clone().single_xsd_any_uri().unwrap();
let recipient = get_or_fetch_and_upsert_remote_user(&recipient_actor_id, client, pool).await?; let recipient = get_or_fetch_and_upsert_remote_user(&recipient_actor_id, client, pool).await?;
Ok(PrivateMessageForm { Ok(PrivateMessageForm {
creator_id: creator.id, creator_id: creator.id,
recipient_id: recipient.id, recipient_id: recipient.id,
content: oprops content: note
.get_content_xsd_string() .content()
.map(|c| c.to_string()) .unwrap()
.unwrap(), .as_single_xsd_string()
published: oprops .unwrap()
.get_published() .to_string(),
.map(|u| u.as_ref().to_owned().naive_local()), published: note.published().map(|u| u.to_owned().naive_local()),
updated: oprops updated: note.updated().map(|u| u.to_owned().naive_local()),
.get_updated()
.map(|u| u.as_ref().to_owned().naive_local()),
deleted: None, deleted: None,
read: None, read: None,
ap_id: oprops.get_id().unwrap().to_string(), ap_id: note.id(actor_id.domain().unwrap())?.unwrap().to_string(),
local: false, local: false,
}) })
} }
@ -113,21 +116,16 @@ impl ApubObjectType for PrivateMessage {
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
let mut create = Create::new(); let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?);
create
.object_props
.set_context_xsd_any_uri(context())?
.set_id(id)?;
let to = format!("{}/inbox", recipient.actor_id); let to = format!("{}/inbox", recipient.actor_id);
create create
.create_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(note)?; .set_to(to.clone());
insert_activity(creator.id, create.clone(), true, pool).await?; insert_activity(creator.id, create.clone(), true, pool).await?;
send_activity(client, &create, creator, vec![to]).await?; send_activity(client, &create.into_any_base()?, creator, vec![to]).await?;
Ok(()) Ok(())
} }
@ -144,21 +142,16 @@ impl ApubObjectType for PrivateMessage {
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
let mut update = Update::new(); let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?);
update
.object_props
.set_context_xsd_any_uri(context())?
.set_id(id)?;
let to = format!("{}/inbox", recipient.actor_id); let to = format!("{}/inbox", recipient.actor_id);
update update
.update_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(note)?; .set_to(to.clone());
insert_activity(creator.id, update.clone(), true, pool).await?; insert_activity(creator.id, update.clone(), true, pool).await?;
send_activity(client, &update, creator, vec![to]).await?; send_activity(client, &update.into_any_base()?, creator, vec![to]).await?;
Ok(()) Ok(())
} }
@ -174,21 +167,16 @@ impl ApubObjectType for PrivateMessage {
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
let mut delete = Delete::new(); let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
delete
.object_props
.set_context_xsd_any_uri(context())?
.set_id(id)?;
let to = format!("{}/inbox", recipient.actor_id); let to = format!("{}/inbox", recipient.actor_id);
delete delete
.delete_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(note)?; .set_to(to.clone());
insert_activity(creator.id, delete.clone(), true, pool).await?; insert_activity(creator.id, delete.clone(), true, pool).await?;
send_activity(client, &delete, creator, vec![to]).await?; send_activity(client, &delete.into_any_base()?, creator, vec![to]).await?;
Ok(()) Ok(())
} }
@ -204,36 +192,25 @@ impl ApubObjectType for PrivateMessage {
let recipient_id = self.recipient_id; let recipient_id = self.recipient_id;
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
let mut delete = Delete::new(); let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
delete
.object_props
.set_context_xsd_any_uri(context())?
.set_id(id)?;
let to = format!("{}/inbox", recipient.actor_id); let to = format!("{}/inbox", recipient.actor_id);
delete delete
.delete_props .set_context(context())
.set_actor_xsd_any_uri(creator.actor_id.to_owned())? .set_id(Url::parse(&id)?)
.set_object_base_box(note)?; .set_to(to.clone());
// TODO // TODO
// Undo that fake activity // Undo that fake activity
let undo_id = format!("{}/undo/delete/{}", self.ap_id, uuid::Uuid::new_v4()); let undo_id = format!("{}/undo/delete/{}", self.ap_id, uuid::Uuid::new_v4());
let mut undo = Undo::default(); let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?);
undo undo
.object_props .set_context(context())
.set_context_xsd_any_uri(context())? .set_id(Url::parse(&undo_id)?)
.set_id(undo_id)?; .set_to(to.clone());
undo
.undo_props
.set_actor_xsd_any_uri(creator.actor_id.to_owned())?
.set_object_base_box(delete)?;
insert_activity(creator.id, undo.clone(), true, pool).await?; insert_activity(creator.id, undo.clone(), true, pool).await?;
send_activity(client, &undo, creator, vec![to]).await?; send_activity(client, &undo.into_any_base()?, creator, vec![to]).await?;
Ok(()) Ok(())
} }

File diff suppressed because it is too large Load diff

View file

@ -15,16 +15,15 @@ use activitystreams_new::{
context, context,
object::{Image, Tombstone}, object::{Image, Tombstone},
prelude::*, prelude::*,
primitives::{XsdAnyUri, XsdDateTime},
}; };
use actix_web::{body::Body, client::Client, web, HttpResponse}; use actix_web::{body::Body, client::Client, web, HttpResponse};
use failure::_core::str::FromStr;
use lemmy_db::{ use lemmy_db::{
naive_now, naive_now,
user::{UserForm, User_}, user::{UserForm, User_},
}; };
use lemmy_utils::convert_datetime; use lemmy_utils::convert_datetime;
use serde::Deserialize; use serde::Deserialize;
use url::Url;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct UserQuery { pub struct UserQuery {
@ -41,12 +40,12 @@ impl ToApub for User_ {
let mut person = Person::new(); let mut person = Person::new();
person person
.set_context(context()) .set_context(context())
.set_id(XsdAnyUri::from_str(&self.actor_id)?) .set_id(Url::parse(&self.actor_id)?)
.set_name(self.name.to_owned()) .set_name(self.name.to_owned())
.set_published(XsdDateTime::from(convert_datetime(self.published))); .set_published(convert_datetime(self.published));
if let Some(u) = self.updated { if let Some(u) = self.updated {
person.set_updated(XsdDateTime::from(convert_datetime(u))); person.set_updated(convert_datetime(u));
} }
if let Some(avatar_url) = &self.avatar { if let Some(avatar_url) = &self.avatar {
@ -79,7 +78,7 @@ impl ToApub for User_ {
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl ActorType for User_ { impl ActorType for User_ {
fn actor_id(&self) -> String { fn actor_id_str(&self) -> String {
self.actor_id.to_owned() self.actor_id.to_owned()
} }
@ -105,7 +104,7 @@ impl ActorType for User_ {
insert_activity(self.id, follow.clone(), true, pool).await?; insert_activity(self.id, follow.clone(), true, pool).await?;
send_activity(client, &follow, self, vec![to]).await?; send_activity(client, &follow.into_any_base()?, self, vec![to]).await?;
Ok(()) Ok(())
} }
@ -124,12 +123,12 @@ impl ActorType for User_ {
// TODO // TODO
// Undo that fake activity // Undo that fake activity
let undo_id = format!("{}/undo/follow/{}", self.actor_id, uuid::Uuid::new_v4()); let undo_id = format!("{}/undo/follow/{}", self.actor_id, uuid::Uuid::new_v4());
let mut undo = Undo::new(self.actor_id.parse::<XsdAnyUri>()?, follow.into_any_base()?); let mut undo = Undo::new(Url::parse(&self.actor_id)?, follow.into_any_base()?);
undo.set_context(context()).set_id(undo_id.parse()?); undo.set_context(context()).set_id(undo_id.parse()?);
insert_activity(self.id, undo.clone(), true, pool).await?; insert_activity(self.id, undo.clone(), true, pool).await?;
send_activity(client, &undo, self, vec![to]).await?; send_activity(client, &undo.into_any_base()?, self, vec![to]).await?;
Ok(()) Ok(())
} }
@ -171,7 +170,7 @@ impl ActorType for User_ {
async fn send_accept_follow( async fn send_accept_follow(
&self, &self,
_follow: &Follow, _follow: Follow,
_client: &Client, _client: &Client,
_pool: &DbPool, _pool: &DbPool,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
@ -187,12 +186,17 @@ impl ActorType for User_ {
impl FromApub for UserForm { impl FromApub for UserForm {
type ApubType = PersonExt; type ApubType = PersonExt;
/// Parse an ActivityPub person received from another instance into a Lemmy user. /// Parse an ActivityPub person received from another instance into a Lemmy user.
async fn from_apub(person: &PersonExt, _: &Client, _: &DbPool) -> Result<Self, LemmyError> { async fn from_apub(
person: &PersonExt,
_: &Client,
_: &DbPool,
actor_id: &Url,
) -> Result<Self, LemmyError> {
let avatar = match person.icon() { let avatar = match person.icon() {
Some(any_image) => Image::from_any_base(any_image.as_one().unwrap().clone()) Some(any_image) => Image::from_any_base(any_image.as_one().unwrap().clone())
.unwrap() .unwrap()
.unwrap() .unwrap()
.url .url()
.unwrap() .unwrap()
.as_single_xsd_any_uri() .as_single_xsd_any_uri()
.map(|u| u.to_string()), .map(|u| u.to_string()),
@ -203,18 +207,18 @@ impl FromApub for UserForm {
name: person name: person
.name() .name()
.unwrap() .unwrap()
.as_single_xsd_string() .one()
.unwrap() .unwrap()
.into(), .as_xsd_string()
.unwrap()
.to_string(),
preferred_username: person.inner.preferred_username().map(|u| u.to_string()), preferred_username: person.inner.preferred_username().map(|u| u.to_string()),
password_encrypted: "".to_string(), password_encrypted: "".to_string(),
admin: false, admin: false,
banned: false, banned: false,
email: None, email: None,
avatar, avatar,
updated: person updated: person.updated().map(|u| u.to_owned().naive_local()),
.updated()
.map(|u| u.as_ref().to_owned().naive_local()),
show_nsfw: false, show_nsfw: false,
theme: "".to_string(), theme: "".to_string(),
default_sort_type: 0, default_sort_type: 0,
@ -223,8 +227,9 @@ impl FromApub for UserForm {
show_avatars: false, show_avatars: false,
send_notifications_to_email: false, send_notifications_to_email: false,
matrix_user_id: None, matrix_user_id: None,
actor_id: person.id().unwrap().to_string(), actor_id: person.id(actor_id.domain().unwrap())?.unwrap().to_string(),
bio: person bio: person
.inner
.summary() .summary()
.map(|s| s.as_single_xsd_string().unwrap().into()), .map(|s| s.as_single_xsd_string().unwrap().into()),
local: false, local: false,

View file

@ -10,9 +10,10 @@ use crate::{
websocket::{server::SendUserRoomMessage, UserOperation}, websocket::{server::SendUserRoomMessage, UserOperation},
DbPool, LemmyError, DbPool, LemmyError,
}; };
use activitystreams::{ use activitystreams_new::{
activity::{Accept, Create, Delete, Undo, Update}, activity::{Accept, Create, Delete, Undo, Update},
object::Note, object::Note,
prelude::*,
}; };
use actix_web::{client::Client, web, HttpRequest, HttpResponse}; use actix_web::{client::Client, web, HttpRequest, HttpResponse};
use lemmy_db::{ use lemmy_db::{
@ -76,11 +77,7 @@ async fn receive_accept(
client: &Client, client: &Client,
pool: &DbPool, pool: &DbPool,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let community_uri = accept let community_uri = accept.actor()?.to_owned().single_xsd_any_uri().unwrap();
.accept_props
.get_actor_xsd_any_uri()
.unwrap()
.to_string();
let community = get_or_fetch_and_upsert_remote_community(&community_uri, client, pool).await?; let community = get_or_fetch_and_upsert_remote_community(&community_uri, client, pool).await?;
verify(request, &community)?; verify(request, &community)?;
@ -113,22 +110,15 @@ async fn receive_create_private_message(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let note = create let user_uri = &create.actor()?.to_owned().single_xsd_any_uri().unwrap();
.create_props let note = Note::from_any_base(create.object().as_one().unwrap().to_owned())?.unwrap();
.get_object_base_box()
.to_owned()
.unwrap()
.to_owned()
.into_concrete::<Note>()?;
let user_uri = create.create_props.get_actor_xsd_any_uri().unwrap(); let user = get_or_fetch_and_upsert_remote_user(user_uri, client, pool).await?;
let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?;
verify(request, &user)?; verify(request, &user)?;
insert_activity(user.id, create, false, pool).await?; insert_activity(user.id, create, false, pool).await?;
let private_message = PrivateMessageForm::from_apub(&note, client, pool).await?; let private_message = PrivateMessageForm::from_apub(&note, client, pool, user_uri).await?;
let inserted_private_message = blocking(pool, move |conn| { let inserted_private_message = blocking(pool, move |conn| {
PrivateMessage::create(conn, &private_message) PrivateMessage::create(conn, &private_message)
@ -161,22 +151,15 @@ async fn receive_update_private_message(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let note = update let user_uri = &update.actor()?.to_owned().single_xsd_any_uri().unwrap();
.update_props let note = Note::from_any_base(update.object().as_one().unwrap().to_owned())?.unwrap();
.get_object_base_box()
.to_owned()
.unwrap()
.to_owned()
.into_concrete::<Note>()?;
let user_uri = update.update_props.get_actor_xsd_any_uri().unwrap();
let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?;
verify(request, &user)?; verify(request, &user)?;
insert_activity(user.id, update, false, pool).await?; insert_activity(user.id, update, false, pool).await?;
let private_message_form = PrivateMessageForm::from_apub(&note, client, pool).await?; let private_message_form = PrivateMessageForm::from_apub(&note, client, pool, user_uri).await?;
let private_message_ap_id = private_message_form.ap_id.clone(); let private_message_ap_id = private_message_form.ap_id.clone();
let private_message = blocking(pool, move |conn| { let private_message = blocking(pool, move |conn| {
@ -217,22 +200,15 @@ async fn receive_delete_private_message(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let note = delete let user_uri = &delete.actor()?.to_owned().single_xsd_any_uri().unwrap();
.delete_props let note = Note::from_any_base(delete.object().as_one().unwrap().to_owned())?.unwrap();
.get_object_base_box()
.to_owned()
.unwrap()
.to_owned()
.into_concrete::<Note>()?;
let user_uri = delete.delete_props.get_actor_xsd_any_uri().unwrap();
let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?;
verify(request, &user)?; verify(request, &user)?;
insert_activity(user.id, delete, false, pool).await?; insert_activity(user.id, delete, false, pool).await?;
let private_message_form = PrivateMessageForm::from_apub(&note, client, pool).await?; let private_message_form = PrivateMessageForm::from_apub(&note, client, pool, user_uri).await?;
let private_message_ap_id = private_message_form.ap_id; let private_message_ap_id = private_message_form.ap_id;
let private_message = blocking(pool, move |conn| { let private_message = blocking(pool, move |conn| {
@ -285,30 +261,16 @@ async fn receive_undo_delete_private_message(
pool: &DbPool, pool: &DbPool,
chat_server: ChatServerParam, chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> { ) -> Result<HttpResponse, LemmyError> {
let delete = undo let delete = Delete::from_any_base(undo.object().as_one().unwrap().to_owned())?.unwrap();
.undo_props let note = Note::from_any_base(delete.object().as_one().unwrap().to_owned())?.unwrap();
.get_object_base_box() let user_uri = &delete.actor()?.to_owned().single_xsd_any_uri().unwrap();
.to_owned()
.unwrap()
.to_owned()
.into_concrete::<Delete>()?;
let note = delete
.delete_props
.get_object_base_box()
.to_owned()
.unwrap()
.to_owned()
.into_concrete::<Note>()?;
let user_uri = delete.delete_props.get_actor_xsd_any_uri().unwrap();
let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?; let user = get_or_fetch_and_upsert_remote_user(&user_uri, client, pool).await?;
verify(request, &user)?; verify(request, &user)?;
insert_activity(user.id, delete, false, pool).await?; insert_activity(user.id, delete, false, pool).await?;
let private_message = PrivateMessageForm::from_apub(&note, client, pool).await?; let private_message = PrivateMessageForm::from_apub(&note, client, pool, user_uri).await?;
let private_message_ap_id = private_message.ap_id.clone(); let private_message_ap_id = private_message.ap_id.clone();
let private_message_id = blocking(pool, move |conn| { let private_message_id = blocking(pool, move |conn| {