]> Untitled Git - lemmy.git/commitdiff
Extract Activitypub logic into separate library (#2288)
authorNutomic <me@nutomic.com>
Thu, 2 Jun 2022 14:33:41 +0000 (14:33 +0000)
committerGitHub <noreply@github.com>
Thu, 2 Jun 2022 14:33:41 +0000 (16:33 +0200)
* Create example for apub lib

* some rewriting of apub lib

* Add LocalInstance struct for apub lib to avoid using Lemmy Settings

* Move ActorType trait to lemmy_apub, because its not needed in library

* Use reqwest_retry instead of custom impl, dont specify timeout on every send()

* Some improvements to example

* Moved inbox handling to library

* bug fixes

* Move context and serde helpers into library

* wip: example changes

* Add lemmy_utils feature to build only LemmyError

* Rename to activitypub_federation

* Remove lemmy_utils dep from activitypub_federation using generic error type

* Finish activitypub example

* Cleanup and fix tests

* Reorganize library files

* Remove ApubObject.to_tombstone()

* Extract activitypub library into separate git repository

199 files changed:
Cargo.lock
Cargo.toml
api_tests/src/comment.spec.ts
api_tests/src/post.spec.ts
crates/api/Cargo.toml
crates/api/src/comment/like.rs
crates/api/src/comment/mark_as_read.rs
crates/api/src/comment/save.rs
crates/api/src/comment_report/create.rs
crates/api/src/comment_report/list.rs
crates/api/src/comment_report/resolve.rs
crates/api/src/community/add_mod.rs
crates/api/src/community/ban.rs
crates/api/src/community/block.rs
crates/api/src/community/follow.rs
crates/api/src/community/hide.rs
crates/api/src/community/transfer.rs
crates/api/src/lib.rs
crates/api/src/local_user/add_admin.rs
crates/api/src/local_user/ban_person.rs
crates/api/src/local_user/block.rs
crates/api/src/local_user/change_password.rs
crates/api/src/local_user/change_password_after_reset.rs
crates/api/src/local_user/get_captcha.rs
crates/api/src/local_user/list_banned.rs
crates/api/src/local_user/login.rs
crates/api/src/local_user/notifications/list_mentions.rs
crates/api/src/local_user/notifications/list_replies.rs
crates/api/src/local_user/notifications/mark_all_read.rs
crates/api/src/local_user/notifications/mark_mention_read.rs
crates/api/src/local_user/notifications/unread_count.rs
crates/api/src/local_user/report_count.rs
crates/api/src/local_user/reset_password.rs
crates/api/src/local_user/save_settings.rs
crates/api/src/local_user/verify_email.rs
crates/api/src/post/get_link_metadata.rs
crates/api/src/post/like.rs
crates/api/src/post/lock.rs
crates/api/src/post/mark_read.rs
crates/api/src/post/save.rs
crates/api/src/post/sticky.rs
crates/api/src/post_report/create.rs
crates/api/src/post_report/list.rs
crates/api/src/post_report/resolve.rs
crates/api/src/private_message/mark_read.rs
crates/api/src/site/config/read.rs
crates/api/src/site/config/update.rs
crates/api/src/site/leave_admin.rs
crates/api/src/site/mod_log.rs
crates/api/src/site/registration_applications/approve.rs
crates/api/src/site/registration_applications/list.rs
crates/api/src/site/registration_applications/unread_count.rs
crates/api/src/site/resolve_object.rs
crates/api/src/site/search.rs
crates/api/src/websocket.rs
crates/api_common/src/request.rs
crates/api_common/src/utils.rs
crates/api_crud/Cargo.toml
crates/api_crud/src/comment/create.rs
crates/api_crud/src/comment/delete.rs
crates/api_crud/src/comment/list.rs
crates/api_crud/src/comment/read.rs
crates/api_crud/src/comment/remove.rs
crates/api_crud/src/comment/update.rs
crates/api_crud/src/community/create.rs
crates/api_crud/src/community/delete.rs
crates/api_crud/src/community/list.rs
crates/api_crud/src/community/read.rs
crates/api_crud/src/community/remove.rs
crates/api_crud/src/community/update.rs
crates/api_crud/src/lib.rs
crates/api_crud/src/post/create.rs
crates/api_crud/src/post/delete.rs
crates/api_crud/src/post/list.rs
crates/api_crud/src/post/read.rs
crates/api_crud/src/post/remove.rs
crates/api_crud/src/post/update.rs
crates/api_crud/src/private_message/create.rs
crates/api_crud/src/private_message/delete.rs
crates/api_crud/src/private_message/read.rs
crates/api_crud/src/private_message/update.rs
crates/api_crud/src/site/create.rs
crates/api_crud/src/site/read.rs
crates/api_crud/src/site/update.rs
crates/api_crud/src/user/create.rs
crates/api_crud/src/user/delete.rs
crates/api_crud/src/user/read.rs
crates/apub/Cargo.toml
crates/apub/assets/lemmy/activities/community/report_page.json
crates/apub/assets/lemmy/activities/create_or_update/create_private_message.json
crates/apub/assets/lemmy/objects/chat_message.json
crates/apub/src/activities/block/block_user.rs
crates/apub/src/activities/block/mod.rs
crates/apub/src/activities/block/undo_block_user.rs
crates/apub/src/activities/community/add_mod.rs
crates/apub/src/activities/community/announce.rs
crates/apub/src/activities/community/mod.rs
crates/apub/src/activities/community/remove_mod.rs
crates/apub/src/activities/community/report.rs
crates/apub/src/activities/community/update.rs
crates/apub/src/activities/create_or_update/comment.rs
crates/apub/src/activities/create_or_update/mod.rs
crates/apub/src/activities/create_or_update/post.rs
crates/apub/src/activities/create_or_update/private_message.rs
crates/apub/src/activities/deletion/delete.rs
crates/apub/src/activities/deletion/delete_user.rs
crates/apub/src/activities/deletion/mod.rs
crates/apub/src/activities/deletion/undo_delete.rs
crates/apub/src/activities/following/accept.rs
crates/apub/src/activities/following/follow.rs
crates/apub/src/activities/following/undo_follow.rs
crates/apub/src/activities/mod.rs
crates/apub/src/activities/voting/mod.rs
crates/apub/src/activities/voting/undo_vote.rs
crates/apub/src/activities/voting/vote.rs
crates/apub/src/activity_lists.rs
crates/apub/src/collections/community_moderators.rs
crates/apub/src/collections/community_outbox.rs
crates/apub/src/context.rs [deleted file]
crates/apub/src/fetcher/mod.rs
crates/apub/src/fetcher/post_or_comment.rs
crates/apub/src/fetcher/search.rs
crates/apub/src/fetcher/user_or_community.rs
crates/apub/src/fetcher/webfinger.rs
crates/apub/src/http/comment.rs
crates/apub/src/http/community.rs
crates/apub/src/http/mod.rs
crates/apub/src/http/person.rs
crates/apub/src/http/post.rs
crates/apub/src/http/site.rs
crates/apub/src/lib.rs
crates/apub/src/mentions.rs
crates/apub/src/objects/comment.rs
crates/apub/src/objects/community.rs
crates/apub/src/objects/instance.rs
crates/apub/src/objects/mod.rs
crates/apub/src/objects/person.rs
crates/apub/src/objects/post.rs
crates/apub/src/objects/private_message.rs
crates/apub/src/protocol/activities/block/block_user.rs
crates/apub/src/protocol/activities/block/undo_block_user.rs
crates/apub/src/protocol/activities/community/add_mod.rs
crates/apub/src/protocol/activities/community/announce.rs
crates/apub/src/protocol/activities/community/remove_mod.rs
crates/apub/src/protocol/activities/community/report.rs
crates/apub/src/protocol/activities/community/update.rs
crates/apub/src/protocol/activities/create_or_update/comment.rs
crates/apub/src/protocol/activities/create_or_update/post.rs
crates/apub/src/protocol/activities/create_or_update/private_message.rs
crates/apub/src/protocol/activities/deletion/delete.rs
crates/apub/src/protocol/activities/deletion/delete_user.rs
crates/apub/src/protocol/activities/deletion/undo_delete.rs
crates/apub/src/protocol/activities/following/accept.rs
crates/apub/src/protocol/activities/following/follow.rs
crates/apub/src/protocol/activities/following/undo_follow.rs
crates/apub/src/protocol/activities/voting/undo_vote.rs
crates/apub/src/protocol/activities/voting/vote.rs
crates/apub/src/protocol/collections/empty_outbox.rs
crates/apub/src/protocol/collections/group_followers.rs
crates/apub/src/protocol/collections/group_moderators.rs
crates/apub/src/protocol/mod.rs
crates/apub/src/protocol/objects/chat_message.rs
crates/apub/src/protocol/objects/group.rs
crates/apub/src/protocol/objects/instance.rs
crates/apub/src/protocol/objects/note.rs
crates/apub/src/protocol/objects/page.rs
crates/apub/src/protocol/objects/person.rs
crates/apub/src/protocol/objects/tombstone.rs
crates/apub_lib/src/activity_queue.rs [deleted file]
crates/apub_lib/src/data.rs [deleted file]
crates/apub_lib/src/lib.rs [deleted file]
crates/apub_lib/src/object_id.rs [deleted file]
crates/apub_lib/src/signatures.rs [deleted file]
crates/apub_lib/src/traits.rs [deleted file]
crates/apub_lib/src/utils.rs [deleted file]
crates/apub_lib/src/values.rs [deleted file]
crates/apub_lib/src/verify.rs [deleted file]
crates/apub_lib_derive/src/lib.rs [deleted file]
crates/db_schema/Cargo.toml
crates/db_schema/src/impls/private_message.rs
crates/db_schema/src/utils.rs
crates/routes/src/feeds.rs
crates/routes/src/images.rs
crates/routes/src/nodeinfo.rs
crates/routes/src/webfinger.rs
crates/utils/src/claims.rs
crates/utils/src/email.rs
crates/utils/src/error.rs [new file with mode: 0644]
crates/utils/src/lib.rs
crates/utils/src/settings/mod.rs
crates/utils/src/utils.rs
crates/websocket/src/chat_server.rs
crates/websocket/src/lib.rs
crates/websocket/src/send.rs
src/code_migrations.rs
src/lib.rs
src/main.rs
src/scheduled_tasks.rs
src/telemetry.rs

index d03721847a314bc33bcad79f1652bdbbf02c6d40..887fae193666b0c724820a979caeb5deab5ae3a0 100644 (file)
@@ -2,6 +2,46 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "activitypub_federation"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78b34a144dc98c419543690aa8f182d8675ebe0610775982b8fdee84a00f70fe"
+dependencies = [
+ "activitypub_federation_derive",
+ "actix-web",
+ "anyhow",
+ "async-trait",
+ "background-jobs",
+ "base64",
+ "chrono",
+ "derive_builder 0.11.2",
+ "http",
+ "http-signature-normalization-actix",
+ "http-signature-normalization-reqwest",
+ "once_cell",
+ "openssl",
+ "reqwest",
+ "reqwest-middleware",
+ "serde",
+ "serde_json",
+ "sha2",
+ "thiserror",
+ "tracing",
+ "url",
+]
+
+[[package]]
+name = "activitypub_federation_derive"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a2aaf58676b669d3b0dedf6bbb44fa518b5a6657b2959561d77899c668dec2a"
+dependencies = [
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
+]
+
 [[package]]
 name = "activitystreams-kinds"
 version = "0.2.1"
@@ -94,8 +134,8 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6"
 dependencies = [
- "quote 1.0.17",
- "syn 1.0.90",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -245,9 +285,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7525bedf54704abb1d469e88d7e7e9226df73778798a69cea5022d53b2ae91bc"
 dependencies = [
  "actix-router",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -256,9 +296,9 @@ version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6d44b8fee1ced9671ba043476deddef739dd0959bf77030b26b738cc591737a7"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -349,9 +389,9 @@ version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -360,9 +400,9 @@ version = "0.1.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -372,7 +412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "21fb6a0b39c6517edafe46f8137e53c51742425a4dae1c73ee12264a37ad7541"
 dependencies = [
  "chrono",
- "derive_builder",
+ "derive_builder 0.10.2",
  "diligent-date-parser",
  "never",
  "quick-xml",
@@ -801,6 +841,16 @@ dependencies = [
  "darling_macro 0.13.1",
 ]
 
+[[package]]
+name = "darling"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02"
+dependencies = [
+ "darling_core 0.14.1",
+ "darling_macro 0.14.1",
+]
+
 [[package]]
 name = "darling_core"
 version = "0.12.4"
@@ -809,10 +859,10 @@ checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36"
 dependencies = [
  "fnv",
  "ident_case",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
  "strsim",
- "syn 1.0.90",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -823,10 +873,24 @@ checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324"
 dependencies = [
  "fnv",
  "ident_case",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "strsim",
+ "syn 1.0.95",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
  "strsim",
- "syn 1.0.90",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -836,8 +900,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a"
 dependencies = [
  "darling_core 0.12.4",
- "quote 1.0.17",
- "syn 1.0.90",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -847,8 +911,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b"
 dependencies = [
  "darling_core 0.13.1",
- "quote 1.0.17",
- "syn 1.0.90",
+ "quote 1.0.18",
+ "syn 1.0.95",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5"
+dependencies = [
+ "darling_core 0.14.1",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -866,7 +941,16 @@ version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d13202debe11181040ae9063d739fa32cfcaaebe2275fe387703460ae2365b30"
 dependencies = [
- "derive_builder_macro",
+ "derive_builder_macro 0.10.2",
+]
+
+[[package]]
+name = "derive_builder"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d07adf7be193b71cc36b193d0f5fe60b918a3a9db4dad0449f57bcfd519704a3"
+dependencies = [
+ "derive_builder_macro 0.11.2",
 ]
 
 [[package]]
@@ -876,9 +960,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5"
 dependencies = [
  "darling 0.12.4",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
+]
+
+[[package]]
+name = "derive_builder_core"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4"
+dependencies = [
+ "darling 0.14.1",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -887,8 +983,18 @@ version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73"
 dependencies = [
- "derive_builder_core",
- "syn 1.0.90",
+ "derive_builder_core 0.10.2",
+ "syn 1.0.95",
+]
+
+[[package]]
+name = "derive_builder_macro"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68"
+dependencies = [
+ "derive_builder_core 0.11.2",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -898,10 +1004,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
 dependencies = [
  "convert_case",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
  "rustc_version",
- "syn 1.0.90",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -946,9 +1052,9 @@ version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -1009,12 +1115,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "dissimilar"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31ad93652f40969dead8d4bf897a41e9462095152eb21c56e5830537e41179dd"
-
 [[package]]
 name = "doku"
 version = "0.11.0"
@@ -1032,9 +1132,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "603fe9f91b4d0e11036df029aeaeffa90b8f97e700104d5d24abb053bf9ba858"
 dependencies = [
  "darling 0.13.1",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -1286,9 +1386,9 @@ version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -1362,12 +1462,6 @@ dependencies = [
  "wasi 0.10.0+wasi-snapshot-preview1",
 ]
 
-[[package]]
-name = "glob"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
-
 [[package]]
 name = "h2"
 version = "0.3.12"
@@ -1484,9 +1578,9 @@ dependencies = [
  "log",
  "mac",
  "markup5ever",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -1764,6 +1858,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 name = "lemmy_api"
 version = "0.16.5"
 dependencies = [
+ "activitypub_federation",
  "actix-web",
  "anyhow",
  "async-trait",
@@ -1774,7 +1869,6 @@ dependencies = [
  "diesel",
  "lemmy_api_common",
  "lemmy_apub",
- "lemmy_apub_lib",
  "lemmy_db_schema",
  "lemmy_db_views",
  "lemmy_db_views_actor",
@@ -1815,12 +1909,12 @@ dependencies = [
 name = "lemmy_api_crud"
 version = "0.16.5"
 dependencies = [
+ "activitypub_federation",
  "actix-web",
  "async-trait",
  "bcrypt",
  "lemmy_api_common",
  "lemmy_apub",
- "lemmy_apub_lib",
  "lemmy_db_schema",
  "lemmy_db_views",
  "lemmy_db_views_actor",
@@ -1837,6 +1931,7 @@ dependencies = [
 name = "lemmy_apub"
 version = "0.16.5"
 dependencies = [
+ "activitypub_federation",
  "activitystreams-kinds",
  "actix",
  "actix-rt",
@@ -1852,7 +1947,6 @@ dependencies = [
  "http-signature-normalization-actix",
  "itertools",
  "lemmy_api_common",
- "lemmy_apub_lib",
  "lemmy_db_schema",
  "lemmy_db_views",
  "lemmy_db_views_actor",
@@ -1873,53 +1967,16 @@ dependencies = [
  "uuid",
 ]
 
-[[package]]
-name = "lemmy_apub_lib"
-version = "0.16.5"
-dependencies = [
- "actix-web",
- "anyhow",
- "async-trait",
- "background-jobs",
- "base64",
- "chrono",
- "diesel",
- "http",
- "http-signature-normalization-actix",
- "http-signature-normalization-reqwest",
- "lemmy_apub_lib_derive",
- "lemmy_utils",
- "once_cell",
- "openssl",
- "reqwest",
- "reqwest-middleware",
- "serde",
- "serde_json",
- "sha2",
- "tracing",
- "url",
-]
-
-[[package]]
-name = "lemmy_apub_lib_derive"
-version = "0.16.5"
-dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
- "trybuild",
-]
-
 [[package]]
 name = "lemmy_db_schema"
 version = "0.16.5"
 dependencies = [
+ "activitypub_federation",
  "bcrypt",
  "chrono",
  "diesel",
  "diesel-derive-newtype",
  "diesel_migrations",
- "lemmy_apub_lib",
  "lemmy_utils",
  "once_cell",
  "regex",
@@ -1992,6 +2049,7 @@ dependencies = [
 name = "lemmy_server"
 version = "0.16.5"
 dependencies = [
+ "activitypub_federation",
  "actix",
  "actix-web",
  "clokwerk",
@@ -2003,7 +2061,6 @@ dependencies = [
  "lemmy_api_common",
  "lemmy_api_crud",
  "lemmy_apub",
- "lemmy_apub_lib",
  "lemmy_db_schema",
  "lemmy_routes",
  "lemmy_utils",
@@ -2013,6 +2070,7 @@ dependencies = [
  "parking_lot 0.12.0",
  "reqwest",
  "reqwest-middleware",
+ "reqwest-retry",
  "reqwest-tracing",
  "serde",
  "tracing",
@@ -2258,9 +2316,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c"
 dependencies = [
  "migrations_internals",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -2663,9 +2721,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
 dependencies = [
  "pest",
  "pest_meta",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -2761,9 +2819,9 @@ version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -2824,9 +2882,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
 dependencies = [
  "proc-macro-error-attr",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
  "version_check",
 ]
 
@@ -2836,8 +2894,8 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
  "version_check",
 ]
 
@@ -2847,16 +2905,16 @@ version = "0.4.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
 dependencies = [
- "unicode-xid 0.1.0",
+ "unicode-xid",
 ]
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.36"
+version = "1.0.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
+checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
 dependencies = [
- "unicode-xid 0.2.2",
+ "unicode-ident",
 ]
 
 [[package]]
@@ -2897,9 +2955,9 @@ checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
 dependencies = [
  "anyhow",
  "itertools",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -2942,11 +3000,11 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.17"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58"
+checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
 dependencies = [
- "proc-macro2 1.0.36",
+ "proc-macro2 1.0.39",
 ]
 
 [[package]]
@@ -3148,9 +3206,9 @@ dependencies = [
 
 [[package]]
 name = "reqwest-middleware"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b58621b8223cfc85b63d38b8d335c69b96a666d9b7561aa30a3b070ce1df31c"
+checksum = "69539cea4148dce683bec9dc95be3f0397a9bb2c248a49c8296a9d21659a8cdd"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -3162,6 +3220,26 @@ dependencies = [
  "thiserror",
 ]
 
+[[package]]
+name = "reqwest-retry"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce246a729eaa6aff5e215aee42845bf5fed9893cc6cd51aeeb712f34e04dd9f3"
+dependencies = [
+ "anyhow",
+ "async-trait",
+ "chrono",
+ "futures",
+ "http",
+ "hyper",
+ "reqwest",
+ "reqwest-middleware",
+ "retry-policies",
+ "task-local-extensions",
+ "tokio",
+ "tracing",
+]
+
 [[package]]
 name = "reqwest-tracing"
 version = "0.2.1"
@@ -3178,6 +3256,17 @@ dependencies = [
  "tracing-opentelemetry 0.16.0",
 ]
 
+[[package]]
+name = "retry-policies"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47f9e19b18c6cdd796cc70aea8a9ea5ee7b813be611c6589e3624fcdbfd05f9d"
+dependencies = [
+ "anyhow",
+ "chrono",
+ "rand 0.8.5",
+]
+
 [[package]]
 name = "rgb"
 version = "0.8.32"
@@ -3210,8 +3299,8 @@ checksum = "6f697b8b3f19bee20f30dc87213d05ce091c43bc733ab1bfc98b0e5cdd9943f3"
 dependencies = [
  "convert_case",
  "lazy_static",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
  "regex",
  "tinyjson",
 ]
@@ -3229,7 +3318,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "36e19e299f301be17927a7c05b8fa1c621e3227e6c3a0da65492701642901ff7"
 dependencies = [
  "atom_syndication",
- "derive_builder",
+ "derive_builder 0.10.2",
  "never",
  "quick-xml",
 ]
@@ -3366,9 +3455,9 @@ version = "1.0.136"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -3413,9 +3502,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "12e47be9471c72889ebafb5e14d5ff930d89ae7a67bbdb5f8abb564f845a927e"
 dependencies = [
  "darling 0.13.1",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -3436,10 +3525,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2881bccd7d60fb32dfa3d7b3136385312f8ad75e2674aab2852867a09790cae8"
 dependencies = [
  "proc-macro-error",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
  "rustversion",
- "syn 1.0.90",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -3536,9 +3625,9 @@ version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -3585,8 +3674,8 @@ checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
 dependencies = [
  "phf_generator 0.10.0",
  "phf_shared 0.10.0",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
 ]
 
 [[package]]
@@ -3608,10 +3697,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef"
 dependencies = [
  "heck 0.4.0",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
  "rustversion",
- "syn 1.0.90",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -3622,18 +3711,18 @@ checksum = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
 dependencies = [
  "proc-macro2 0.4.30",
  "quote 0.6.13",
- "unicode-xid 0.1.0",
+ "unicode-xid",
 ]
 
 [[package]]
 name = "syn"
-version = "1.0.90"
+version = "1.0.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f"
+checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "unicode-xid 0.2.2",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "unicode-ident",
 ]
 
 [[package]]
@@ -3676,33 +3765,24 @@ dependencies = [
  "utf-8",
 ]
 
-[[package]]
-name = "termcolor"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
-dependencies = [
- "winapi-util",
-]
-
 [[package]]
 name = "thiserror"
-version = "1.0.30"
+version = "1.0.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
+checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.30"
+version = "1.0.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
+checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -3768,9 +3848,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
 
 [[package]]
 name = "tokio"
-version = "1.17.0"
+version = "1.18.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
+checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395"
 dependencies = [
  "bytes",
  "libc",
@@ -3803,9 +3883,9 @@ version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -3868,15 +3948,6 @@ dependencies = [
  "tracing",
 ]
 
-[[package]]
-name = "toml"
-version = "0.5.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
-dependencies = [
- "serde",
-]
-
 [[package]]
 name = "tonic"
 version = "0.6.2"
@@ -3914,10 +3985,10 @@ version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757"
 dependencies = [
- "proc-macro2 1.0.36",
+ "proc-macro2 1.0.39",
  "prost-build",
- "quote 1.0.17",
- "syn 1.0.90",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -3984,9 +4055,9 @@ version = "0.1.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
 ]
 
 [[package]]
@@ -4080,22 +4151,6 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
 
-[[package]]
-name = "trybuild"
-version = "1.0.57"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ae8c4cee9b97b861a6e3be1d5acb6f50a86bbb68b1f3a896db8342fb6d0f94c"
-dependencies = [
- "dissimilar",
- "glob",
- "once_cell",
- "serde",
- "serde_derive",
- "serde_json",
- "termcolor",
- "toml",
-]
-
 [[package]]
 name = "twoway"
 version = "0.2.2"
@@ -4145,6 +4200,12 @@ version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
 
+[[package]]
+name = "unicode-ident"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
+
 [[package]]
 name = "unicode-normalization"
 version = "0.1.19"
@@ -4172,12 +4233,6 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 
-[[package]]
-name = "unicode-xid"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
-
 [[package]]
 name = "unicode_categories"
 version = "0.1.1"
@@ -4295,9 +4350,9 @@ dependencies = [
  "bumpalo",
  "lazy_static",
  "log",
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
  "wasm-bindgen-shared",
 ]
 
@@ -4319,7 +4374,7 @@ version = "0.2.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
 dependencies = [
- "quote 1.0.17",
+ "quote 1.0.18",
  "wasm-bindgen-macro-support",
 ]
 
@@ -4329,9 +4384,9 @@ version = "0.2.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
 dependencies = [
- "proc-macro2 1.0.36",
- "quote 1.0.17",
- "syn 1.0.90",
+ "proc-macro2 1.0.39",
+ "quote 1.0.18",
+ "syn 1.0.95",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
index f4eceaf340d5fffc5f08dd524646f18a229a776d..f74a0ba3595bb09fcb99f6ac51d4a2c191fdefab 100644 (file)
@@ -23,8 +23,6 @@ members = [
     "crates/api",
     "crates/api_crud",
     "crates/api_common",
-    "crates/apub_lib",
-    "crates/apub_lib_derive",
     "crates/apub",
     "crates/utils",
     "crates/db_schema",
@@ -39,12 +37,12 @@ members = [
 lemmy_api = { version = "=0.16.5", path = "./crates/api" }
 lemmy_api_crud = { version = "=0.16.5", path = "./crates/api_crud" }
 lemmy_apub = { version = "=0.16.5", path = "./crates/apub" }
-lemmy_apub_lib = { version = "=0.16.5", path = "./crates/apub_lib" }
 lemmy_utils = { version = "=0.16.5", path = "./crates/utils" }
 lemmy_db_schema = { version = "=0.16.5", path = "./crates/db_schema" }
 lemmy_api_common = { version = "=0.16.5", path = "crates/api_common" }
 lemmy_websocket = { version = "=0.16.5", path = "./crates/websocket" }
 lemmy_routes = { version = "=0.16.5", path = "./crates/routes" }
+activitypub_federation = "0.1.0"
 diesel = "1.4.8"
 diesel_migrations = "1.4.0"
 serde = { version = "1.0.136", features = ["derive"] }
@@ -62,6 +60,7 @@ reqwest-tracing = "0.2.1"
 clokwerk = "0.3.5"
 doku = "0.11.0"
 parking_lot = "0.12.0"
+reqwest-retry = "0.1.5"
 console-subscriber = { version = "0.1.3", optional = true }
 opentelemetry = { version = "0.17.0", features = ["rt-tokio"], optional = true }
 opentelemetry-otlp = { version = "0.10.0", optional = true }
index 314f18ecc5b06885587c2285e979674819ca6348..6de268542f3ae4089df99de4bbb6327eef781743 100644 (file)
@@ -170,10 +170,10 @@ test('Remove a comment from admin and community on the same instance', async ()
 });
 
 test('Remove a comment from admin and community on different instance', async () => {
-  let alphaUser = await registerUser(alpha);
+  let alpha_user = await registerUser(alpha);
   let newAlphaApi: API = {
     client: alpha.client,
-    auth: alphaUser.jwt,
+    auth: alpha_user.jwt,
   };
 
   // New alpha user creates a community, post, and comment.
index b2f12298c309b7ae960e79bc8b2b23e85ec791fc..023309b4fd1b80d524881211e0ba87329b2871a3 100644 (file)
@@ -290,17 +290,17 @@ test('Enforce site ban for federated user', async () => {
   // create a test user
   let alphaUserJwt = await registerUser(alpha);
   expect(alphaUserJwt).toBeDefined();
-  let alphaUser: API = {
+  let alpha_user: API = {
       client: alpha.client,
       auth: alphaUserJwt.jwt,
   };
-  let alphaUserActorId = (await getSite(alphaUser)).my_user.local_user_view.person.actor_id;
+  let alphaUserActorId = (await getSite(alpha_user)).my_user.local_user_view.person.actor_id;
   expect(alphaUserActorId).toBeDefined();
-  let alphaPerson = (await resolvePerson(alphaUser, alphaUserActorId)).person;
+  let alphaPerson = (await resolvePerson(alpha_user, alphaUserActorId)).person;
   expect(alphaPerson).toBeDefined();
 
   // alpha makes post in beta community, it federates to beta instance
-  let postRes1 = await createPost(alphaUser, betaCommunity.community.id);
+  let postRes1 = await createPost(alpha_user, betaCommunity.community.id);
   let searchBeta1 = await searchPostLocal(beta, postRes1.post_view.post);
   expect(searchBeta1.posts[0]).toBeDefined();
 
@@ -321,7 +321,7 @@ test('Enforce site ban for federated user', async () => {
   expect(unBanAlpha.banned).toBe(false);
 
   // alpha makes new post in beta community, it federates
-  let postRes2 = await createPost(alphaUser, betaCommunity.community.id);
+  let postRes2 = await createPost(alpha_user, betaCommunity.community.id);
   let searchBeta3 = await searchPostLocal(beta, postRes2.post_view.post);
   expect(searchBeta3.posts[0]).toBeDefined();
 
index b81ea8e3284c454b51361a4086fa7b33b64f5411..0ef120e67c4858e2f9b7ded8729208a0a7b9e16b 100644 (file)
@@ -14,7 +14,6 @@ doctest = false
 
 [dependencies]
 lemmy_apub = { version = "=0.16.5", path = "../apub" }
-lemmy_apub_lib = { version = "=0.16.5", path = "../apub_lib" }
 lemmy_utils = { version = "=0.16.5", path = "../utils" }
 lemmy_db_schema = { version = "=0.16.5", path = "../db_schema", features = ["full"] }
 lemmy_db_views = { version = "=0.16.5", path = "../db_views", features = ["full"] }
@@ -22,6 +21,7 @@ lemmy_db_views_moderator = { version = "=0.16.5", path = "../db_views_moderator"
 lemmy_db_views_actor = { version = "=0.16.5", path = "../db_views_actor", features = ["full"] }
 lemmy_api_common = { version = "=0.16.5", path = "../api_common", features = ["full"] }
 lemmy_websocket = { version = "=0.16.5", path = "../websocket" }
+activitypub_federation = "0.1.0"
 diesel = "1.4.8"
 bcrypt = "0.12.1"
 chrono = { version = "0.4.19", features = ["serde"], default-features = false }
index cc97ebc485ab467dc16cbd1bb3234e17c910b590..48302ac6509ce955df10e0334899a262434a5a49 100644 (file)
@@ -17,7 +17,7 @@ use lemmy_db_schema::{
   traits::Likeable,
 };
 use lemmy_db_views::structs::{CommentView, LocalUserView};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperation};
 use std::convert::TryInto;
 
index a0dc6dd74e9b3f956eed7059f600d310deb39e61..85881f1ca2c325ef5c951415891363f100b49129 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_api_common::{
 };
 use lemmy_db_schema::source::comment::Comment;
 use lemmy_db_views::structs::CommentView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 1ece524a8a41080e19c742996c9e2c431de62155..4d599739a254560d8a990968de7d3cf45b6b1e70 100644 (file)
@@ -9,7 +9,7 @@ use lemmy_db_schema::{
   traits::Saveable,
 };
 use lemmy_db_views::structs::CommentView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 75e1323ab0c5a779b04ba7914787d1e6656d5a10..6a1c2287e154ebf8b40bc1270e48b5f4cf175d34 100644 (file)
@@ -1,17 +1,17 @@
 use crate::Perform;
+use activitypub_federation::core::object_id::ObjectId;
 use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{CommentReportResponse, CreateCommentReport},
   utils::{blocking, check_community_ban, get_local_user_view_from_jwt},
 };
 use lemmy_apub::protocol::activities::community::report::Report;
-use lemmy_apub_lib::object_id::ObjectId;
 use lemmy_db_schema::{
   source::comment_report::{CommentReport, CommentReportForm},
   traits::Reportable,
 };
 use lemmy_db_views::structs::{CommentReportView, CommentView};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
 
 /// Creates a comment report and notifies the moderators of the community
index 296cb8322facf4a58a8af020dd15873d1df7ba88..c8678425535538b42bb7daed28ac3233a8cf0ed9 100644 (file)
@@ -5,7 +5,7 @@ use lemmy_api_common::{
   utils::{blocking, get_local_user_view_from_jwt},
 };
 use lemmy_db_views::comment_report_view::CommentReportQueryBuilder;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 /// Lists comment reports for a community if an id is supplied
index 95481ace7e70ae2896a67344c78589dffc10e95d..2c016b95e4b9e8ec61b2c104a2b98ef37bb16764 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_api_common::{
 };
 use lemmy_db_schema::{source::comment_report::CommentReport, traits::Reportable};
 use lemmy_db_views::structs::CommentReportView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
 
 /// Resolves or unresolves a comment report and notifies the moderators of the community
index 9ea9361a9c87954048bad0937f6c84d0e492828e..b8999e4b71f4d77352a8ccd5433f1fda7861bc53 100644 (file)
@@ -17,7 +17,7 @@ use lemmy_db_schema::{
   traits::{Crud, Joinable},
 };
 use lemmy_db_views_actor::structs::CommunityModeratorView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{messages::SendCommunityRoomMessage, LemmyContext, UserOperation};
 
 #[async_trait::async_trait(?Send)]
index 60fd32270f76ae7db7022ea0fa32bbe2e2ba4477..07e287835427a2193989682a927a5499b4f3f7f2 100644 (file)
@@ -24,7 +24,7 @@ use lemmy_db_schema::{
   traits::{Bannable, Crud, Followable},
 };
 use lemmy_db_views_actor::structs::PersonViewSafe;
-use lemmy_utils::{utils::naive_from_unix, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, utils::naive_from_unix, ConnectionId};
 use lemmy_websocket::{messages::SendCommunityRoomMessage, LemmyContext, UserOperation};
 
 #[async_trait::async_trait(?Send)]
index 4f740c916971182931600786dcfcbb24f000a5e2..2f5f5f904b48149afcbe0ef76d222c7881480e27 100644 (file)
@@ -13,7 +13,7 @@ use lemmy_db_schema::{
   traits::{Blockable, Crud, Followable},
 };
 use lemmy_db_views_actor::structs::CommunityView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index aab21a9c217a7361daa0f6395ba2ceebaa2f2cf0..53da4f2ef6ae161c92fdb966ecfc7a79cd11c855 100644 (file)
@@ -21,7 +21,7 @@ use lemmy_db_schema::{
   traits::{Crud, Followable},
 };
 use lemmy_db_views_actor::structs::CommunityView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index ddf4f49a152fa460422ec2b47117c01955709f10..6a562f1c0a2b4dbf1c4613b3d2f18105e387bde6 100644 (file)
@@ -13,7 +13,7 @@ use lemmy_db_schema::{
   traits::Crud,
   utils::naive_now,
 };
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
 
 #[async_trait::async_trait(?Send)]
index 9d8044e3d8394951329b0b43978abd7e69ae7c90..fe34bbfa4f4f4b21cb7a44c05ac461490bb2c609 100644 (file)
@@ -13,7 +13,7 @@ use lemmy_db_schema::{
   traits::{Crud, Joinable},
 };
 use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView, PersonViewSafe};
-use lemmy_utils::{location_info, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, location_info, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 // TODO: we dont do anything for federation here, it should be updated the next time the community
index 0c36890bc6c6c1f9c1e4a86028580342b1b49166..6e2bb4f0e6851588d9ac24203fa50654c2651e14 100644 (file)
@@ -1,7 +1,7 @@
 use actix_web::{web, web::Data};
 use captcha::Captcha;
 use lemmy_api_common::{comment::*, community::*, person::*, post::*, site::*, websocket::*};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperation};
 use serde::Deserialize;
 
index 3834dbbef3b5946b700eeb310ce7554941fb21ab..b44b210b7bb18fa9287ab81392235ac6ab81ca5b 100644 (file)
@@ -12,7 +12,7 @@ use lemmy_db_schema::{
   traits::Crud,
 };
 use lemmy_db_views_actor::structs::PersonViewSafe;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{messages::SendAllMessage, LemmyContext, UserOperation};
 
 #[async_trait::async_trait(?Send)]
index d357e8eb9e466ac0bdc6443907cfd678e0e40371..6de826dca1ec06c3cac38bd08dcb48ae57c2f0ed 100644 (file)
@@ -17,7 +17,7 @@ use lemmy_db_schema::{
   traits::Crud,
 };
 use lemmy_db_views_actor::structs::PersonViewSafe;
-use lemmy_utils::{utils::naive_from_unix, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, utils::naive_from_unix, ConnectionId};
 use lemmy_websocket::{messages::SendAllMessage, LemmyContext, UserOperation};
 
 #[async_trait::async_trait(?Send)]
index d0812fd970e29e3f685f081f4396faea96b3a087..4878cb02045d1ae49bcf292379fa3ac5b6ef791d 100644 (file)
@@ -9,7 +9,7 @@ use lemmy_db_schema::{
   traits::Blockable,
 };
 use lemmy_db_views_actor::structs::PersonViewSafe;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 714659980a77f67c71088b85cae6a035054bb262..6143fc4fa2ab6be113d9c55b6c4157ea0c3a3f5d 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_api_common::{
   utils::{blocking, get_local_user_view_from_jwt, password_length_check},
 };
 use lemmy_db_schema::source::local_user::LocalUser;
-use lemmy_utils::{claims::Claims, ConnectionId, LemmyError};
+use lemmy_utils::{claims::Claims, error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 92e4f6ba544b595baf87f9adee96dace5b312c30..cc4c7400e4080d91e00e7553b19d81ccc476cbbb 100644 (file)
@@ -8,7 +8,7 @@ use lemmy_db_schema::source::{
   local_user::LocalUser,
   password_reset_request::PasswordResetRequest,
 };
-use lemmy_utils::{claims::Claims, ConnectionId, LemmyError};
+use lemmy_utils::{claims::Claims, error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 5c691b8ca1c7badcf5bbe19a71e765497291c46b..2740036c7ae660b556e495c9b789edf83a68247d 100644 (file)
@@ -4,7 +4,7 @@ use captcha::{gen, Difficulty};
 use chrono::Duration;
 use lemmy_api_common::person::{CaptchaResponse, GetCaptcha, GetCaptchaResponse};
 use lemmy_db_schema::utils::naive_now;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{messages::CaptchaItem, LemmyContext};
 
 #[async_trait::async_trait(?Send)]
index 4c39d0cd20aff2a5268f6c624911799821f4ca39..5423bdbe92fbef32b5bd4c318c0beb7eab281d21 100644 (file)
@@ -5,7 +5,7 @@ use lemmy_api_common::{
   utils::{blocking, get_local_user_view_from_jwt, is_admin},
 };
 use lemmy_db_views_actor::structs::PersonViewSafe;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index e1931d5a479026e301f1b361faa08a27a59edb9f..cd17d61ab711d79693f9fe8548de5ef377fc2c9a 100644 (file)
@@ -7,7 +7,7 @@ use lemmy_api_common::{
 };
 use lemmy_db_schema::source::site::Site;
 use lemmy_db_views::structs::LocalUserView;
-use lemmy_utils::{claims::Claims, ConnectionId, LemmyError};
+use lemmy_utils::{claims::Claims, error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 6e786841012150ca3aa4a3c392c2269a11f0b0c3..048bef959c57577fca8d8c81720a6d6c671f74cf 100644 (file)
@@ -5,7 +5,7 @@ use lemmy_api_common::{
   utils::{blocking, get_local_user_view_from_jwt},
 };
 use lemmy_db_views_actor::person_mention_view::PersonMentionQueryBuilder;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 643a1c9a867f1f7b8adc853a559e1a11218f76a8..ba7cbb8e963e289241a628b15330d81623d126e0 100644 (file)
@@ -5,7 +5,7 @@ use lemmy_api_common::{
   utils::{blocking, get_local_user_view_from_jwt},
 };
 use lemmy_db_views::comment_view::CommentQueryBuilder;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index d5caa02d5365cc2efe4eac07b36a54d4bd04fefb..3925e7913f45076445633381bb6df4e56ceb599e 100644 (file)
@@ -10,7 +10,7 @@ use lemmy_db_schema::source::{
   private_message::PrivateMessage,
 };
 use lemmy_db_views::comment_view::CommentQueryBuilder;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 4c9d06014fd34cfc44326494ef255745e7dc09a7..b097ddc41b73026e4b9d7fcdcd9b29d81e6bd414 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_api_common::{
 };
 use lemmy_db_schema::{source::person_mention::PersonMention, traits::Crud};
 use lemmy_db_views_actor::structs::PersonMentionView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index a9c06ffc73ef83203f960aa076c241b9cdaa2eed..cdab17bdefbfb83db326da5ff2d8827cea97e3db 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_api_common::{
 };
 use lemmy_db_views::structs::{CommentView, PrivateMessageView};
 use lemmy_db_views_actor::structs::PersonMentionView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index a07f8c055fa903f0a166da06f059747ba647dd4f..774b2fbbdaf8f8de09dfa26658a4360e6eb0e1bf 100644 (file)
@@ -5,7 +5,7 @@ use lemmy_api_common::{
   utils::{blocking, get_local_user_view_from_jwt},
 };
 use lemmy_db_views::structs::{CommentReportView, PostReportView};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 6903a8b8e770bdba55f8f80910ab9cd42ff71afe..98112b70be137f684d2a26f8c0c9d0e960da1b4b 100644 (file)
@@ -5,7 +5,7 @@ use lemmy_api_common::{
   utils::{blocking, send_password_reset_email},
 };
 use lemmy_db_views::structs::LocalUserView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 5e37470a9053a97d884ab7fb9f0c929c3c1510a9..eba76907e2627ffb6180a9f78f180e9fe6e8d0d1 100644 (file)
@@ -15,9 +15,9 @@ use lemmy_db_schema::{
 };
 use lemmy_utils::{
   claims::Claims,
+  error::LemmyError,
   utils::{is_valid_display_name, is_valid_matrix_id},
   ConnectionId,
-  LemmyError,
 };
 use lemmy_websocket::LemmyContext;
 
index c4af8e34ebaf63cfdc88eab33dbdd8df141bab7e..7f1797262eec2d6835cdb62b8e6a6e9f7f149f80 100644 (file)
@@ -12,7 +12,7 @@ use lemmy_db_schema::{
   traits::Crud,
 };
 use lemmy_db_views::structs::LocalUserView;
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index db1213324166e5be77309936b81e36f6618ad1bb..54e2cfe7ca4d2301359ef66b985093c1aabbecf0 100644 (file)
@@ -4,7 +4,7 @@ use lemmy_api_common::{
   post::{GetSiteMetadata, GetSiteMetadataResponse},
   request::fetch_site_metadata,
 };
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 24d9337c279037ce05fd94d28f2820be3716bf8b..5197225602bc290fd5f86f275d47e6e33ba872bf 100644 (file)
@@ -23,7 +23,7 @@ use lemmy_db_schema::{
   source::post::{Post, PostLike, PostLikeForm},
   traits::{Crud, Likeable},
 };
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperation};
 
 #[async_trait::async_trait(?Send)]
index 965e506fc7dbda51affa9956521c885fedc15873..1e11117f2f2703619db49acce7954fbf22230480 100644 (file)
@@ -21,7 +21,7 @@ use lemmy_db_schema::{
   },
   traits::Crud,
 };
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperation};
 
 #[async_trait::async_trait(?Send)]
index 8777ebced832a1f9b15be2046e03b1ce5907aa65..07659ea83597880c4fd2e9347060beecc9da9427 100644 (file)
@@ -5,7 +5,7 @@ use lemmy_api_common::{
   utils::{blocking, get_local_user_view_from_jwt, mark_post_as_read, mark_post_as_unread},
 };
 use lemmy_db_views::structs::PostView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 09baec988355db340c655514b06759fba45e704a..25bb6c3cec13246af84380105df485915d0d29a1 100644 (file)
@@ -9,7 +9,7 @@ use lemmy_db_schema::{
   traits::Saveable,
 };
 use lemmy_db_views::structs::PostView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index dffe67e3394fe8344cf9fa55d4eece84bdfdf8b8..952eed6f711bae3318cebbde500ac39d1e13ca70 100644 (file)
@@ -21,7 +21,7 @@ use lemmy_db_schema::{
   },
   traits::Crud,
 };
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperation};
 
 #[async_trait::async_trait(?Send)]
index a960e2c5332c977ca9e583b216b51bce192c6f9e..28915f01ab03315ef25a902b4ca09ae6d2c749e1 100644 (file)
@@ -1,17 +1,17 @@
 use crate::Perform;
+use activitypub_federation::core::object_id::ObjectId;
 use actix_web::web::Data;
 use lemmy_api_common::{
   post::{CreatePostReport, PostReportResponse},
   utils::{blocking, check_community_ban, get_local_user_view_from_jwt},
 };
 use lemmy_apub::protocol::activities::community::report::Report;
-use lemmy_apub_lib::object_id::ObjectId;
 use lemmy_db_schema::{
   source::post_report::{PostReport, PostReportForm},
   traits::Reportable,
 };
 use lemmy_db_views::structs::{PostReportView, PostView};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
 
 /// Creates a post report and notifies the moderators of the community
index 7ae0a5ee978a16c7e25da4bd13acce9f1b3f809e..71cde96aae03d03e723bb00ff1479e4b62557f9f 100644 (file)
@@ -5,7 +5,7 @@ use lemmy_api_common::{
   utils::{blocking, get_local_user_view_from_jwt},
 };
 use lemmy_db_views::post_report_view::PostReportQueryBuilder;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 /// Lists post reports for a community if an id is supplied
index 0b50999d261849a6035f875782622c1a0ba20181..469f96b359139173b7fc522edf90ae7bd4aff698 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_api_common::{
 };
 use lemmy_db_schema::{source::post_report::PostReport, traits::Reportable};
 use lemmy_db_views::structs::PostReportView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
 
 /// Resolves or unresolves a post report and notifies the moderators of the community
index 5789678365d9990a8512edd0c27bccf7386147d6..fa25060100da441b6631858fe277f3817f18c021 100644 (file)
@@ -5,7 +5,7 @@ use lemmy_api_common::{
   utils::{blocking, get_local_user_view_from_jwt},
 };
 use lemmy_db_schema::{source::private_message::PrivateMessage, traits::Crud};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperation};
 
 #[async_trait::async_trait(?Send)]
index 8626fd5f49f511b1d2ff693b6ef25ff74ce2aea4..4f82e1255a5cc0ef8b2a8cf8d349c118b64e6b92 100644 (file)
@@ -4,7 +4,7 @@ use lemmy_api_common::{
   site::{GetSiteConfig, GetSiteConfigResponse},
   utils::{get_local_user_view_from_jwt, is_admin},
 };
-use lemmy_utils::{settings::structs::Settings, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, settings::structs::Settings, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 98f2b1f349cd1de5dff508ed2603867ff3ab502a..4d4f064e270b11fe2e3b2fcc463db0311701646d 100644 (file)
@@ -4,7 +4,7 @@ use lemmy_api_common::{
   site::{GetSiteConfigResponse, SaveSiteConfig},
   utils::{get_local_user_view_from_jwt, is_admin},
 };
-use lemmy_utils::{settings::structs::Settings, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, settings::structs::Settings, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 10a3adc4718d734df9f2ab03d32111b707d6b633..55b49fc7d0754f2b897f944b9ee2336a4445665e 100644 (file)
@@ -13,7 +13,7 @@ use lemmy_db_schema::{
 };
 use lemmy_db_views::structs::SiteView;
 use lemmy_db_views_actor::structs::PersonViewSafe;
-use lemmy_utils::{version, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, version, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 45335d5d383140f169281998d7034bd6d1a737e9..acb5e827e7dd46aadd83085d3b9b67a12817aee1 100644 (file)
@@ -17,7 +17,7 @@ use lemmy_db_views_moderator::structs::{
   ModStickyPostView,
   ModTransferCommunityView,
 };
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 2e3577de082a6929e69950d57ec39b94952c807b..04000b63ad2066a4c5e32ba70409dc05bbc2ef8a 100644 (file)
@@ -13,7 +13,7 @@ use lemmy_db_schema::{
   utils::diesel_option_overwrite,
 };
 use lemmy_db_views::structs::{LocalUserView, RegistrationApplicationView};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 27633aa64abdbe6763aabf5e33886898c045ef11..60dfd446d7999252bab8cb56cc80688fdcea4dfd 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_api_common::{
 };
 use lemmy_db_schema::source::site::Site;
 use lemmy_db_views::registration_application_view::RegistrationApplicationQueryBuilder;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 /// Lists registration applications, filterable by undenied only.
index 06f995234958ed5f302b44b436685c8cd29c7179..fbaecf40fd7068d4f6660f163c87200120d5795b 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_api_common::{
 };
 use lemmy_db_schema::source::site::Site;
 use lemmy_db_views::structs::RegistrationApplicationView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 4e84e162f3be6340670e12c47d8d8cc0b4be0349..1048101d60ea38b39cf93b0874f8f887ec993176 100644 (file)
@@ -9,7 +9,7 @@ use lemmy_apub::fetcher::search::{search_by_apub_id, SearchableObjects};
 use lemmy_db_schema::{newtypes::PersonId, utils::DbPool};
 use lemmy_db_views::structs::{CommentView, PostView};
 use lemmy_db_views_actor::structs::{CommunityView, PersonViewSafe};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 5e1474238e03132e6a9f7d14824d9be167a9a7f6..fef467000e075e6e47ddb11f2745f9d28197a0c7 100644 (file)
@@ -11,7 +11,7 @@ use lemmy_db_views_actor::{
   community_view::CommunityQueryBuilder,
   person_view::PersonQueryBuilder,
 };
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index aea443a96d57825b27cfb23ef8fcfc427d704db4..13319dc23b235275fa563cee4e1331e34977d9e9 100644 (file)
@@ -1,7 +1,7 @@
 use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{utils::get_local_user_view_from_jwt, websocket::*};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{
   messages::{JoinCommunityRoom, JoinModRoom, JoinPostRoom, JoinUserRoom},
   LemmyContext,
index fa48e8703b51722cf15acfa9f482f2808a40712a..c5f750115a7ca9495ae4327ccac24cfc326574b0 100644 (file)
@@ -1,6 +1,6 @@
 use crate::post::SiteMetadata;
 use encoding::{all::encodings, DecoderTrap};
-use lemmy_utils::{settings::structs::Settings, version::VERSION, LemmyError, REQWEST_TIMEOUT};
+use lemmy_utils::{error::LemmyError, settings::structs::Settings, version::VERSION};
 use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
 use reqwest_middleware::ClientWithMiddleware;
 use serde::Deserialize;
@@ -15,11 +15,7 @@ pub async fn fetch_site_metadata(
   url: &Url,
 ) -> Result<SiteMetadata, LemmyError> {
   info!("Fetching site metadata for url: {}", url);
-  let response = client
-    .get(url.as_str())
-    .timeout(REQWEST_TIMEOUT)
-    .send()
-    .await?;
+  let response = client.get(url.as_str()).send().await?;
 
   // Can't use .text() here, because it only checks the content header, not the actual bytes
   // https://github.com/LemmyNet/lemmy/issues/1964
@@ -122,11 +118,7 @@ pub(crate) async fn fetch_pictrs(
       utf8_percent_encode(image_url.as_str(), NON_ALPHANUMERIC) // TODO this might not be needed
     );
 
-    let response = client
-      .get(&fetch_url)
-      .timeout(REQWEST_TIMEOUT)
-      .send()
-      .await?;
+    let response = client.get(&fetch_url).send().await?;
 
     let response: PictrsResponse = response.json().await.map_err(LemmyError::from)?;
 
@@ -195,11 +187,7 @@ pub async fn fetch_site_data(
 
 #[tracing::instrument(skip_all)]
 async fn is_image_content_type(client: &ClientWithMiddleware, url: &Url) -> Result<(), LemmyError> {
-  let response = client
-    .get(url.as_str())
-    .timeout(REQWEST_TIMEOUT)
-    .send()
-    .await?;
+  let response = client.get(url.as_str()).send().await?;
   if response
     .headers()
     .get("Content-Type")
index 94a9c3318a3e48577b8e51d9ff0b873ef4c580c9..f8a25251f95e6dcefb9cbcc506e940ac26e09f7d 100644 (file)
@@ -28,9 +28,9 @@ use lemmy_db_views_actor::structs::{
 use lemmy_utils::{
   claims::Claims,
   email::{send_email, translations::Lang},
+  error::LemmyError,
   settings::structs::Settings,
   utils::generate_random_string,
-  LemmyError,
 };
 use rosetta_i18n::{Language, LanguageId};
 use tracing::warn;
index 595dba25eb5712ed8f52d2782193cedbc2caad61..e61a37f7737160144de18486e17fc861d02ae355 100644 (file)
@@ -9,13 +9,13 @@ documentation = "https://join-lemmy.org/docs/en/index.html"
 
 [dependencies]
 lemmy_apub = { version = "=0.16.5", path = "../apub" }
-lemmy_apub_lib = { version = "=0.16.5", path = "../apub_lib" }
 lemmy_utils = { version = "=0.16.5", path = "../utils" }
 lemmy_db_schema = { version = "=0.16.5", path = "../db_schema", features = ["full"] }
 lemmy_db_views = { version = "=0.16.5", path = "../db_views", features = ["full"] }
 lemmy_db_views_actor = { version = "=0.16.5", path = "../db_views_actor", features = ["full"] }
 lemmy_api_common = { version = "=0.16.5", path = "../api_common", features = ["full"] }
 lemmy_websocket = { version = "=0.16.5", path = "../websocket" }
+activitypub_federation = "0.1.0"
 bcrypt = "0.12.1"
 serde_json = { version = "1.0.79", features = ["preserve_order"] }
 serde = { version = "1.0.136", features = ["derive"] }
index 12e208e8c7f97096622df40075a308cba181e745..f550c0535cccb05d078f8bd98725c854490a48b1 100644 (file)
@@ -26,9 +26,9 @@ use lemmy_db_schema::{
 };
 use lemmy_db_views::structs::CommentView;
 use lemmy_utils::{
+  error::LemmyError,
   utils::{remove_slurs, scrape_text_for_mentions},
   ConnectionId,
-  LemmyError,
 };
 use lemmy_websocket::{
   send::{send_comment_ws_message, send_local_notifs},
index f4fb5d405aecd58f48d96f6c0934f9e9ab0f8e21..a674ed2c3a82170d7d62682cdb6c1ccb1af0f49f 100644 (file)
@@ -10,7 +10,7 @@ use lemmy_db_schema::{
   traits::Crud,
 };
 use lemmy_db_views::structs::CommentView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{
   send::{send_comment_ws_message, send_local_notifs},
   LemmyContext,
index f9c37de4821df3090f7484b9a219b943e4ede568..6b949ab6abcdd20d83d9c2bf706409ecd526a04c 100644 (file)
@@ -7,7 +7,7 @@ use lemmy_api_common::{
 use lemmy_apub::{fetcher::resolve_actor_identifier, objects::community::ApubCommunity};
 use lemmy_db_schema::{source::community::Community, traits::DeleteableOrRemoveable};
 use lemmy_db_views::comment_view::CommentQueryBuilder;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index fd248cafe6ffe8800063a6a157be9f96f2de5112..f5013c9882c148e29b8bce2bba98247e855b449c 100644 (file)
@@ -5,7 +5,7 @@ use lemmy_api_common::{
   utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
 };
 use lemmy_db_views::structs::CommentView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 837407c56a560d91849c361e45f6dde7079c518b..fe664d80f7cc3e325203149c22e83d8dcb09c4f6 100644 (file)
@@ -15,7 +15,7 @@ use lemmy_db_schema::{
   traits::Crud,
 };
 use lemmy_db_views::structs::CommentView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{
   send::{send_comment_ws_message, send_local_notifs},
   LemmyContext,
index 06065c89ad521f77b2b9cacb2a0532600f702cf8..2a769277a5017ae676a5ce09477d8c84719beda4 100644 (file)
@@ -16,9 +16,9 @@ use lemmy_apub::protocol::activities::{
 use lemmy_db_schema::source::comment::Comment;
 use lemmy_db_views::structs::CommentView;
 use lemmy_utils::{
+  error::LemmyError,
   utils::{remove_slurs, scrape_text_for_mentions},
   ConnectionId,
-  LemmyError,
 };
 use lemmy_websocket::{
   send::{send_comment_ws_message, send_local_notifs},
index a7582d2ec5bbbf138512bd9850f5b8fd2ece64d1..1181afc39b71c47b827d58cbdd8292e1cc92b9d4 100644 (file)
@@ -1,4 +1,5 @@
 use crate::PerformCrud;
+use activitypub_federation::core::{object_id::ObjectId, signatures::generate_actor_keypair};
 use actix_web::web::Data;
 use lemmy_api_common::{
   community::{CommunityResponse, CreateCommunity},
@@ -12,7 +13,6 @@ use lemmy_apub::{
   objects::community::ApubCommunity,
   EndpointType,
 };
-use lemmy_apub_lib::object_id::ObjectId;
 use lemmy_db_schema::{
   source::{
     community::{
@@ -30,10 +30,9 @@ use lemmy_db_schema::{
 };
 use lemmy_db_views_actor::structs::CommunityView;
 use lemmy_utils::{
-  apub::generate_actor_keypair,
+  error::LemmyError,
   utils::{check_slurs, check_slurs_opt, is_valid_actor_name},
   ConnectionId,
-  LemmyError,
 };
 use lemmy_websocket::LemmyContext;
 
@@ -77,7 +76,9 @@ impl PerformCrud for CreateCommunity {
       &context.settings().get_protocol_and_hostname(),
     )?;
     let community_actor_id_wrapped = ObjectId::<ApubCommunity>::new(community_actor_id.clone());
-    let community_dupe = community_actor_id_wrapped.dereference_local(context).await;
+    let community_dupe = community_actor_id_wrapped
+      .dereference_local::<LemmyError>(context)
+      .await;
     if community_dupe.is_ok() {
       return Err(LemmyError::from_message("community_already_exists"));
     }
index f42e9b01da83c8b2f732d7c8399f06960592249b..441f45811c29c3709190dec20fa1870e1a1b29fc 100644 (file)
@@ -7,7 +7,7 @@ use lemmy_api_common::{
 use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
 use lemmy_db_schema::source::community::Community;
 use lemmy_db_views_actor::structs::CommunityModeratorView;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
 
 #[async_trait::async_trait(?Send)]
index af41b83e22219e477c171003789bdd9a190d7d90..7afb61783061078af6c639ffe2c7a47142afb3c4 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_api_common::{
 };
 use lemmy_db_schema::traits::DeleteableOrRemoveable;
 use lemmy_db_views_actor::community_view::CommunityQueryBuilder;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index 16eee46920f653d4f483441808230f3e916d20d5..8b9c1bdb55674e7321af4a19fca3aba46dc62e69 100644 (file)
@@ -13,7 +13,7 @@ use lemmy_db_schema::{
   traits::DeleteableOrRemoveable,
 };
 use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{messages::GetCommunityUsersOnline, LemmyContext};
 
 #[async_trait::async_trait(?Send)]
index 7ca9b73fa1e714ac9373714978f7706f27a8c1b9..5895a6cbc7e69ae6a2a5f2293e8997614b3f9834 100644 (file)
@@ -12,7 +12,7 @@ use lemmy_db_schema::{
   },
   traits::Crud,
 };
-use lemmy_utils::{utils::naive_from_unix, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, utils::naive_from_unix, ConnectionId};
 use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
 
 #[async_trait::async_trait(?Send)]
index d933c9d8865d46713e92bd946dcb954b00a8411e..d8aaef0e50443ae3d9dcc2eb47f5c331c536219f 100644 (file)
@@ -12,7 +12,7 @@ use lemmy_db_schema::{
   utils::{diesel_option_overwrite_to_url, naive_now},
 };
 use lemmy_db_views_actor::structs::CommunityModeratorView;
-use lemmy_utils::{utils::check_slurs_opt, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, utils::check_slurs_opt, ConnectionId};
 use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
 
 #[async_trait::async_trait(?Send)]
index 9f1553ee16b0edc4d006545de30eea8664dcce11..e29c8fa4f94d8ded43d4d2dbe7dfff06bba830b7 100644 (file)
@@ -1,6 +1,6 @@
 use actix_web::{web, web::Data};
 use lemmy_api_common::{comment::*, community::*, person::*, post::*, site::*};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperationCrud};
 use serde::Deserialize;
 
index 353e186add69ea4919462815b80e66a567cdd5ed..6ef706d0a2513d66ae1ac8c6b1f655a719375480 100644 (file)
@@ -27,6 +27,7 @@ use lemmy_db_schema::{
 };
 use lemmy_db_views_actor::structs::CommunityView;
 use lemmy_utils::{
+  error::LemmyError,
   utils::{
     check_slurs,
     check_slurs_opt,
@@ -35,7 +36,6 @@ use lemmy_utils::{
     is_valid_post_title,
   },
   ConnectionId,
-  LemmyError,
 };
 use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
 use tracing::{warn, Instrument};
index f880b4b5d22c228eb7e542ad775898716445dd07..734a0246131f904ec03bf28a9dac69587df7c209 100644 (file)
@@ -14,7 +14,7 @@ use lemmy_db_schema::{
   source::{community::Community, post::Post},
   traits::Crud,
 };
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
 
 #[async_trait::async_trait(?Send)]
index 574efeba81bfd3985012cf2873077abfee7fd74b..90806cf204ad6509335e50ab0d59cc6fb2c9b95a 100644 (file)
@@ -11,7 +11,7 @@ use lemmy_db_schema::{
   ListingType,
 };
 use lemmy_db_views::post_view::PostQueryBuilder;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 use std::str::FromStr;
 
index a5ca262fa9eb0860d17fc47ef8199618dd439844..36a0b290b294429d855007686d9f8021ee65da74 100644 (file)
@@ -7,7 +7,7 @@ use lemmy_api_common::{
 use lemmy_db_schema::traits::DeleteableOrRemoveable;
 use lemmy_db_views::{comment_view::CommentQueryBuilder, structs::PostView};
 use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{messages::GetPostUsersOnline, LemmyContext};
 
 #[async_trait::async_trait(?Send)]
index 7e50159c9e36e26d92c6ef44f5ab57b25fcdeb53..9ba29158ba862a7cfaf8d8b26b615f4d1211f6fa 100644 (file)
@@ -13,7 +13,7 @@ use lemmy_db_schema::{
   },
   traits::Crud,
 };
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
 
 #[async_trait::async_trait(?Send)]
index 16f2fea40dd8cda9f7667785ce8da0cc4e17c526..285a08b55277cfc178912f4cc5ff71d3bc48ff20 100644 (file)
@@ -19,9 +19,9 @@ use lemmy_db_schema::{
   utils::naive_now,
 };
 use lemmy_utils::{
+  error::LemmyError,
   utils::{check_slurs_opt, clean_optional_text, clean_url_params, is_valid_post_title},
   ConnectionId,
-  LemmyError,
 };
 use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
 
index 894c178b56883ef1c28de1c4f458780a05c0ba5b..a368e3a5387a35a4168cf61d84fc2966a9d2f12b 100644 (file)
@@ -23,7 +23,7 @@ use lemmy_db_schema::{
   traits::Crud,
 };
 use lemmy_db_views::structs::LocalUserView;
-use lemmy_utils::{utils::remove_slurs, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, utils::remove_slurs, ConnectionId};
 use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
 
 #[async_trait::async_trait(?Send)]
index af06094eb59a2ac5ed92d91e2cfd4cf172a6c7cc..ef200f485ad3cd8b6bc810e0dc71c36ed91f211c 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_api_common::{
 };
 use lemmy_apub::activities::deletion::send_apub_delete_private_message;
 use lemmy_db_schema::{source::private_message::PrivateMessage, traits::Crud};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
 
 #[async_trait::async_trait(?Send)]
index ce03200c6e817f348e6fa2f5355e73afbde8fb1f..bb09be2dce68c9568b92ef8b4e75a7d7483ba50e 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_api_common::{
 };
 use lemmy_db_schema::traits::DeleteableOrRemoveable;
 use lemmy_db_views::private_message_view::PrivateMessageQueryBuilder;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index aebd5b8be13a8baf489db4393790903eaf6edf59..2c4cba5e1672eb41dfcab3efbb86b295df096352 100644 (file)
@@ -9,7 +9,7 @@ use lemmy_apub::protocol::activities::{
   CreateOrUpdateType,
 };
 use lemmy_db_schema::{source::private_message::PrivateMessage, traits::Crud};
-use lemmy_utils::{utils::remove_slurs, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, utils::remove_slurs, ConnectionId};
 use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
 
 #[async_trait::async_trait(?Send)]
index 49550d66823c6964332516f20d7a0fdbf39123d9..57301e1081beb2699edcb00f0243da8d2619da5e 100644 (file)
@@ -1,4 +1,5 @@
 use crate::PerformCrud;
+use activitypub_federation::core::signatures::generate_actor_keypair;
 use actix_web::web::Data;
 use lemmy_api_common::{
   site::{CreateSite, SiteResponse},
@@ -13,11 +14,10 @@ use lemmy_db_schema::{
 };
 use lemmy_db_views::structs::SiteView;
 use lemmy_utils::{
-  apub::generate_actor_keypair,
+  error::LemmyError,
   settings::structs::Settings,
   utils::{check_slurs, check_slurs_opt},
   ConnectionId,
-  LemmyError,
 };
 use lemmy_websocket::LemmyContext;
 use url::Url;
index f9fe75c73b1237bbbf246b3f985fbe86d62b44d9..808dcf7d98ec3a7d8458c10baf6a1e0422e2e9e6 100644 (file)
@@ -13,7 +13,7 @@ use lemmy_db_views_actor::structs::{
   PersonBlockView,
   PersonViewSafe,
 };
-use lemmy_utils::{version, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, version, ConnectionId};
 use lemmy_websocket::{messages::GetUsersOnline, LemmyContext};
 use tracing::info;
 
index ba09305412a3966f0bc57ee160a2d8913de77550..6e88e42ec9d6c0d43a996530716205d2df9241c0 100644 (file)
@@ -14,7 +14,7 @@ use lemmy_db_schema::{
   ListingType,
 };
 use lemmy_db_views::structs::SiteView;
-use lemmy_utils::{utils::check_slurs_opt, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, utils::check_slurs_opt, ConnectionId};
 use lemmy_websocket::{messages::SendAllMessage, LemmyContext, UserOperationCrud};
 use std::{default::Default, str::FromStr};
 
index 456617043d7675bb7ae67723d3a008302f575258..44e5b88204d1f477a9cac6d46503645d742bd232 100644 (file)
@@ -1,4 +1,5 @@
 use crate::PerformCrud;
+use activitypub_federation::core::signatures::generate_actor_keypair;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{LoginResponse, Register},
@@ -33,11 +34,10 @@ use lemmy_db_schema::{
 use lemmy_db_views::structs::LocalUserView;
 use lemmy_db_views_actor::structs::PersonViewSafe;
 use lemmy_utils::{
-  apub::generate_actor_keypair,
   claims::Claims,
+  error::LemmyError,
   utils::{check_slurs, is_valid_actor_name},
   ConnectionId,
-  LemmyError,
 };
 use lemmy_websocket::{messages::CheckCaptcha, LemmyContext};
 
index c5e0e2197eeb25577beee8458b07bba3b023246b..bde403a5610dcc015b71753dfe1a2d7ec159667c 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_api_common::{
   utils::{delete_user_account, get_local_user_view_from_jwt},
 };
 use lemmy_apub::protocol::activities::deletion::delete_user::DeleteUser;
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index e00f602759ffc104be80ff9c9f4a38bdd8430f93..ecfd45e093c23d6dfb265082ea5e5be7bd1ff302 100644 (file)
@@ -8,7 +8,7 @@ use lemmy_apub::{fetcher::resolve_actor_identifier, objects::person::ApubPerson}
 use lemmy_db_schema::source::person::Person;
 use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder};
 use lemmy_db_views_actor::structs::{CommunityModeratorView, PersonViewSafe};
-use lemmy_utils::{ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::LemmyContext;
 
 #[async_trait::async_trait(?Send)]
index c584610bd104fc33306116434d160535bc050e9b..f8320c28006ea7739ecccf427fb84d008bc03133 100644 (file)
@@ -14,12 +14,12 @@ doctest = false
 
 [dependencies]
 lemmy_utils = { version = "=0.16.5", path = "../utils" }
-lemmy_apub_lib = { version = "=0.16.5", path = "../apub_lib" }
 lemmy_db_schema = { version = "=0.16.5", path = "../db_schema", features = ["full"] }
 lemmy_db_views = { version = "=0.16.5", path = "../db_views", features = ["full"] }
 lemmy_db_views_actor = { version = "=0.16.5", path = "../db_views_actor", features = ["full"] }
 lemmy_api_common = { version = "=0.16.5", path = "../api_common", features = ["full"] }
 lemmy_websocket = { version = "=0.16.5", path = "../websocket" }
+activitypub_federation = "0.1.0"
 diesel = "1.4.8"
 activitystreams-kinds = "0.2.1"
 chrono = { version = "0.4.19", features = ["serde"], default-features = false }
index bd1691b57b437eaad1cbf5f74dfda3b29a9bde67..724beb43ab32cca2b4591dffb6434991c34ec8d5 100644 (file)
@@ -1,8 +1,6 @@
 {
   "actor": "http://ds9.lemmy.ml/u/lemmy_alpha",
-  "to": [
-    "http://enterprise.lemmy.ml/c/main"
-  ],
+  "to": "http://enterprise.lemmy.ml/c/main",
   "object": "http://enterprise.lemmy.ml/post/7",
   "summary": "report this post",
   "type": "Flag",
index de080a8f9ccfef67f1f168987f6c6fc01f4b097d..85291bc06a3c9471ebfde03ee01e3fd18d5a2978 100644 (file)
@@ -1,16 +1,12 @@
 {
   "id": "http://enterprise.lemmy.ml/activities/create/987d05fa-f637-46d7-85be-13d112bc269f",
   "actor": "http://enterprise.lemmy.ml/u/lemmy_beta",
-  "to": [
-    "http://ds9.lemmy.ml/u/lemmy_alpha"
-  ],
+  "to": "http://ds9.lemmy.ml/u/lemmy_alpha",
   "object": {
     "type": "ChatMessage",
     "id": "http://enterprise.lemmy.ml/private_message/1",
     "attributedTo": "http://enterprise.lemmy.ml/u/lemmy_beta",
-    "to": [
-      "http://ds9.lemmy.ml/u/lemmy_alpha"
-    ],
+    "to": "http://ds9.lemmy.ml/u/lemmy_alpha",
     "content": "hello",
     "mediaType": "text/html",
     "source": {
index c639aef92af7f09f34e1c20c25b34a86ad5bc533..e21312fc60b97210f02996f4e15bbd824f2e5441 100644 (file)
@@ -2,9 +2,7 @@
   "id": "https://enterprise.lemmy.ml/private_message/1621",
   "type": "ChatMessage",
   "attributedTo": "https://enterprise.lemmy.ml/u/picard",
-  "to": [
-    "https://queer.hacktivis.me/users/lanodan"
-  ],
+  "to": "https://queer.hacktivis.me/users/lanodan",
   "content": "<p>Hello hello, testing</p>\n",
   "mediaType": "text/html",
   "source": {
index bcab3148ac8b594b0e0e87180a7c28663d00ef44..6e07fcd8cadda140f450b6cd58e4a0b883461c4f 100644 (file)
@@ -4,25 +4,26 @@ use crate::{
     community::{announce::GetCommunity, send_activity_in_community},
     generate_activity_id,
     send_lemmy_activity,
-    verify_activity,
     verify_is_public,
     verify_mod_action,
     verify_person_in_community,
   },
   activity_lists::AnnouncableActivities,
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::activities::block::block_user::BlockUser,
+  ActorType,
+};
+use activitypub_federation::{
+  core::object_id::ObjectId,
+  data::Data,
+  traits::ActivityHandler,
+  utils::verify_domains_match,
 };
 use activitystreams_kinds::{activity::BlockType, public};
 use anyhow::anyhow;
 use chrono::NaiveDateTime;
 use lemmy_api_common::utils::{blocking, remove_user_data, remove_user_data_in_community};
-use lemmy_apub_lib::{
-  data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType},
-  verify::verify_domains_match,
-};
 use lemmy_db_schema::{
   source::{
     community::{
@@ -36,8 +37,9 @@ use lemmy_db_schema::{
   },
   traits::{Bannable, Crud, Followable},
 };
-use lemmy_utils::{settings::structs::Settings, utils::convert_datetime, LemmyError};
+use lemmy_utils::{error::LemmyError, settings::structs::Settings, utils::convert_datetime};
 use lemmy_websocket::LemmyContext;
+use url::Url;
 
 impl BlockUser {
   pub(in crate::activities::block) async fn new(
@@ -106,6 +108,15 @@ impl BlockUser {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for BlockUser {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -114,10 +125,9 @@ impl ActivityHandler for BlockUser {
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     verify_is_public(&self.to, &self.cc)?;
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     match self
       .target
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?
     {
       SiteOrCommunity::Site(site) => {
@@ -155,15 +165,15 @@ impl ActivityHandler for BlockUser {
     let expires = self.expires.map(|u| u.naive_local());
     let mod_person = self
       .actor
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let blocked_person = self
       .object
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let target = self
       .target
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     match target {
       SiteOrCommunity::Site(_site) => {
@@ -242,7 +252,7 @@ impl GetCommunity for BlockUser {
   ) -> Result<ApubCommunity, LemmyError> {
     let target = self
       .target
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     match target {
       SiteOrCommunity::Community(c) => Ok(c),
index bb35d7d211621d2492a493f8eacb89a477cd7b6c..dec16cf3d313a179fc3d932256e129e4102c68ec 100644 (file)
@@ -1,15 +1,13 @@
 use crate::{
   objects::{community::ApubCommunity, instance::ApubSite, person::ApubPerson},
   protocol::objects::{group::Group, instance::Instance},
+  ActorType,
 };
+use activitypub_federation::{core::object_id::ObjectId, traits::ApubObject};
 use chrono::NaiveDateTime;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  object_id::ObjectId,
-  traits::{ActorType, ApubObject},
-};
 use lemmy_db_schema::{source::site::Site, utils::DbPool};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
 use url::Url;
@@ -35,7 +33,7 @@ impl ApubObject for SiteOrCommunity {
   type DataType = LemmyContext;
   type ApubType = InstanceOrGroup;
   type DbType = ();
-  type TombstoneType = ();
+  type Error = LemmyError;
 
   #[tracing::instrument(skip_all)]
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
@@ -70,10 +68,6 @@ impl ApubObject for SiteOrCommunity {
     unimplemented!()
   }
 
-  fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError> {
-    unimplemented!()
-  }
-
   #[tracing::instrument(skip_all)]
   async fn verify(
     apub: &Self::ApubType,
index 130b1eb506d796b7ffd60dc2713fee3ec94bfe22..a6865303821204ba02b99d7e87fba1c3ecf16d5b 100644 (file)
@@ -4,21 +4,22 @@ use crate::{
     community::{announce::GetCommunity, send_activity_in_community},
     generate_activity_id,
     send_lemmy_activity,
-    verify_activity,
     verify_is_public,
   },
   activity_lists::AnnouncableActivities,
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
+  ActorType,
 };
-use activitystreams_kinds::{activity::UndoType, public};
-use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
+use activitypub_federation::{
+  core::object_id::ObjectId,
   data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType},
-  verify::verify_domains_match,
+  traits::ActivityHandler,
+  utils::verify_domains_match,
 };
+use activitystreams_kinds::{activity::UndoType, public};
+use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{
     community::{CommunityPersonBan, CommunityPersonBanForm},
@@ -27,8 +28,9 @@ use lemmy_db_schema::{
   },
   traits::{Bannable, Crud},
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
+use url::Url;
 
 impl UndoBlockUser {
   #[tracing::instrument(skip_all)]
@@ -72,6 +74,15 @@ impl UndoBlockUser {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for UndoBlockUser {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -80,7 +91,6 @@ impl ActivityHandler for UndoBlockUser {
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     verify_is_public(&self.to, &self.cc)?;
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     verify_domains_match(self.actor.inner(), self.object.actor.inner())?;
     self.object.verify(context, request_counter).await?;
     Ok(())
@@ -92,20 +102,21 @@ impl ActivityHandler for UndoBlockUser {
     context: &Data<LemmyContext>,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
+    let instance = local_instance(context);
     let expires = self.object.expires.map(|u| u.naive_local());
     let mod_person = self
       .actor
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, instance, request_counter)
       .await?;
     let blocked_person = self
       .object
       .object
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, instance, request_counter)
       .await?;
     match self
       .object
       .target
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, instance, request_counter)
       .await?
     {
       SiteOrCommunity::Site(_site) => {
index 2aa7989ee177398f62080d3682fc0075a8cedbc7..58d1006c8b636f024df5e574fbe538c38a292dc4 100644 (file)
@@ -6,7 +6,6 @@ use crate::{
       send_activity_in_community,
     },
     generate_activity_id,
-    verify_activity,
     verify_add_remove_moderator_target,
     verify_is_public,
     verify_mod_action,
@@ -14,16 +13,14 @@ use crate::{
   },
   activity_lists::AnnouncableActivities,
   generate_moderators_url,
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::activities::community::add_mod::AddMod,
+  ActorType,
 };
+use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
 use activitystreams_kinds::{activity::AddType, public};
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType},
-};
 use lemmy_db_schema::{
   source::{
     community::{CommunityModerator, CommunityModeratorForm},
@@ -31,8 +28,9 @@ use lemmy_db_schema::{
   },
   traits::{Crud, Joinable},
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
+use url::Url;
 
 impl AddMod {
   #[tracing::instrument(skip_all)]
@@ -66,6 +64,15 @@ impl AddMod {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for AddMod {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -74,7 +81,6 @@ impl ActivityHandler for AddMod {
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     verify_is_public(&self.to, &self.cc)?;
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     let community = self.get_community(context, request_counter).await?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
     verify_mod_action(
@@ -98,7 +104,7 @@ impl ActivityHandler for AddMod {
     let community = self.get_community(context, request_counter).await?;
     let new_mod = self
       .object
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
 
     // If we had to refetch the community while parsing the activity, then the new mod has already
@@ -121,7 +127,7 @@ impl ActivityHandler for AddMod {
       // write mod log
       let actor = self
         .actor
-        .dereference(context, context.client(), request_counter)
+        .dereference::<LemmyError>(context, local_instance(context), request_counter)
         .await?;
       let form = ModAddCommunityForm {
         mod_person_id: actor.id,
index a6612ca1cba3a85769fdf379127576292b6ea20d..a2e00c786d3bebade51ef4c75b7f02574aca5b31 100644 (file)
@@ -1,23 +1,20 @@
 use crate::{
-  activities::{generate_activity_id, send_lemmy_activity, verify_activity, verify_is_public},
+  activities::{generate_activity_id, send_lemmy_activity, verify_is_public},
   activity_lists::AnnouncableActivities,
-  http::ActivityCommonFields,
   insert_activity,
   objects::community::ApubCommunity,
   protocol::{
     activities::{community::announce::AnnounceActivity, CreateOrUpdateType},
     IdOrNestedObject,
   },
+  ActorType,
 };
+use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
 use activitystreams_kinds::{activity::AnnounceType, public};
-use lemmy_apub_lib::{
-  data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType},
-};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use tracing::debug;
+use url::Url;
 
 #[async_trait::async_trait(?Send)]
 pub(crate) trait GetCommunity {
@@ -90,15 +87,23 @@ impl AnnounceActivity {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for AnnounceActivity {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
     &self,
-    context: &Data<LemmyContext>,
+    _context: &Data<LemmyContext>,
     _request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     verify_is_public(&self.to, &self.cc)?;
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     Ok(())
   }
 
@@ -118,14 +123,12 @@ impl ActivityHandler for AnnounceActivity {
       AnnouncableActivities::Page(_) => {}
       _ => {
         let object_value = serde_json::to_value(&object)?;
-        let object_data: ActivityCommonFields = serde_json::from_value(object_value.to_owned())?;
-
         let insert =
-          insert_activity(&object_data.id, object_value, false, true, context.pool()).await?;
+          insert_activity(object.id(), object_value, false, true, context.pool()).await?;
         if !insert {
           debug!(
             "Received duplicate activity in announce {}",
-            object_data.id.to_string()
+            object.id().to_string()
           );
           return Ok(());
         }
index d8d8097ebc8c0280422fe6027ecd7bcb50aa743c..fe2aaf784d7552bf13d08c63a1c43f5f8a4fe82b 100644 (file)
@@ -1,11 +1,13 @@
 use crate::{
   activities::send_lemmy_activity,
   activity_lists::AnnouncableActivities,
+  local_instance,
   objects::community::ApubCommunity,
   protocol::activities::community::announce::AnnounceActivity,
+  ActorType,
 };
-use lemmy_apub_lib::{object_id::ObjectId, traits::ActorType};
-use lemmy_utils::LemmyError;
+use activitypub_federation::core::object_id::ObjectId;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use url::Url;
 
@@ -42,6 +44,6 @@ async fn get_community_from_moderators_url(
 ) -> Result<ApubCommunity, LemmyError> {
   let community_id = Url::parse(&moderators.to_string().replace("/moderators", ""))?;
   ObjectId::new(community_id)
-    .dereference(context, context.client(), request_counter)
+    .dereference::<LemmyError>(context, local_instance(context), request_counter)
     .await
 }
index f42d47f63dc630e21d1b08968598c3319588b181..6af0e722d81442eaea01e347e9ec946d5980e89b 100644 (file)
@@ -6,7 +6,6 @@ use crate::{
       send_activity_in_community,
     },
     generate_activity_id,
-    verify_activity,
     verify_add_remove_moderator_target,
     verify_is_public,
     verify_mod_action,
@@ -14,16 +13,14 @@ use crate::{
   },
   activity_lists::AnnouncableActivities,
   generate_moderators_url,
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::activities::community::remove_mod::RemoveMod,
+  ActorType,
 };
+use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
 use activitystreams_kinds::{activity::RemoveType, public};
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType},
-};
 use lemmy_db_schema::{
   source::{
     community::{CommunityModerator, CommunityModeratorForm},
@@ -31,8 +28,9 @@ use lemmy_db_schema::{
   },
   traits::{Crud, Joinable},
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
+use url::Url;
 
 impl RemoveMod {
   #[tracing::instrument(skip_all)]
@@ -66,6 +64,15 @@ impl RemoveMod {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for RemoveMod {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -74,7 +81,6 @@ impl ActivityHandler for RemoveMod {
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     verify_is_public(&self.to, &self.cc)?;
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     let community = self.get_community(context, request_counter).await?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
     verify_mod_action(
@@ -98,7 +104,7 @@ impl ActivityHandler for RemoveMod {
     let community = self.get_community(context, request_counter).await?;
     let remove_mod = self
       .object
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
 
     let form = CommunityModeratorForm {
@@ -113,7 +119,7 @@ impl ActivityHandler for RemoveMod {
     // write mod log
     let actor = self
       .actor
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let form = ModAddCommunityForm {
       mod_person_id: actor.id,
index 0069aa6e663257214de9ada592e2e76c8bcb2108..b3f129e3710e84dda9a0268a0931dd40bca07380 100644 (file)
@@ -1,21 +1,14 @@
 use crate::{
-  activities::{
-    generate_activity_id,
-    send_lemmy_activity,
-    verify_activity,
-    verify_person_in_community,
-  },
+  activities::{generate_activity_id, send_lemmy_activity, verify_person_in_community},
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::activities::community::report::Report,
+  ActorType,
   PostOrComment,
 };
+use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
 use activitystreams_kinds::activity::FlagType;
 use lemmy_api_common::{comment::CommentReportResponse, post::PostReportResponse, utils::blocking};
-use lemmy_apub_lib::{
-  data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType},
-};
 use lemmy_db_schema::{
   source::{
     comment_report::{CommentReport, CommentReportForm},
@@ -24,8 +17,9 @@ use lemmy_db_schema::{
   traits::Reportable,
 };
 use lemmy_db_views::structs::{CommentReportView, PostReportView};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
+use url::Url;
 
 impl Report {
   #[tracing::instrument(skip_all)]
@@ -36,7 +30,9 @@ impl Report {
     reason: String,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
-    let community = community_id.dereference_local(context).await?;
+    let community = community_id
+      .dereference_local::<LemmyError>(context)
+      .await?;
     let kind = FlagType::Flag;
     let id = generate_activity_id(
       kind.clone(),
@@ -44,7 +40,7 @@ impl Report {
     )?;
     let report = Report {
       actor: ObjectId::new(actor.actor_id()),
-      to: [ObjectId::new(community.actor_id())],
+      to: ObjectId::new(community.actor_id()),
       object: object_id,
       summary: reason,
       kind,
@@ -66,6 +62,15 @@ impl Report {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for Report {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -73,9 +78,9 @@ impl ActivityHandler for Report {
     context: &Data<LemmyContext>,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
-    let community = self.to[0]
-      .dereference(context, context.client(), request_counter)
+    let community = self
+      .to
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
     Ok(())
@@ -89,11 +94,11 @@ impl ActivityHandler for Report {
   ) -> Result<(), LemmyError> {
     let actor = self
       .actor
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     match self
       .object
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?
     {
       PostOrComment::Post(post) => {
index e6676b8bf3b40426e5d17d09f40b5c1ce30b39d7..538838a23a1093912ebc178ede0e6647bf674393 100644 (file)
@@ -2,28 +2,30 @@ use crate::{
   activities::{
     community::{announce::GetCommunity, send_activity_in_community},
     generate_activity_id,
-    verify_activity,
     verify_is_public,
     verify_mod_action,
     verify_person_in_community,
   },
   activity_lists::AnnouncableActivities,
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::activities::community::update::UpdateCommunity,
+  ActorType,
 };
-use activitystreams_kinds::{activity::UpdateType, public};
-use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
+use activitypub_federation::{
+  core::object_id::ObjectId,
   data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType, ApubObject},
+  traits::{ActivityHandler, ApubObject},
 };
+use activitystreams_kinds::{activity::UpdateType, public};
+use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::community::{Community, CommunityForm},
   traits::Crud,
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
+use url::Url;
 
 impl UpdateCommunity {
   #[tracing::instrument(skip_all)]
@@ -54,6 +56,15 @@ impl UpdateCommunity {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for UpdateCommunity {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -62,7 +73,6 @@ impl ActivityHandler for UpdateCommunity {
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     verify_is_public(&self.to, &self.cc)?;
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     let community = self.get_community(context, request_counter).await?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
     verify_mod_action(
@@ -129,7 +139,7 @@ impl GetCommunity for UpdateCommunity {
   ) -> Result<ApubCommunity, LemmyError> {
     let cid = ObjectId::new(self.object.id.clone());
     cid
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await
   }
 }
index c0e53a6075eafc46d928a72c114eebe23f49be3c..456cbb6b012f4de30caa293226378acf8532cf89 100644 (file)
@@ -4,23 +4,24 @@ use crate::{
     community::{announce::GetCommunity, send_activity_in_community},
     create_or_update::get_comment_notif_recipients,
     generate_activity_id,
-    verify_activity,
     verify_is_public,
     verify_person_in_community,
   },
   activity_lists::AnnouncableActivities,
+  local_instance,
   mentions::MentionOrValue,
   objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson},
   protocol::activities::{create_or_update::comment::CreateOrUpdateComment, CreateOrUpdateType},
+  ActorType,
 };
-use activitystreams_kinds::public;
-use lemmy_api_common::utils::{blocking, check_post_deleted_or_removed};
-use lemmy_apub_lib::{
+use activitypub_federation::{
+  core::object_id::ObjectId,
   data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType, ApubObject},
-  verify::verify_domains_match,
+  traits::{ActivityHandler, ApubObject},
+  utils::verify_domains_match,
 };
+use activitystreams_kinds::public;
+use lemmy_api_common::utils::{blocking, check_post_deleted_or_removed};
 use lemmy_db_schema::{
   source::{
     comment::{CommentLike, CommentLikeForm},
@@ -29,8 +30,9 @@ use lemmy_db_schema::{
   },
   traits::{Crud, Likeable},
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
+use url::Url;
 
 impl CreateOrUpdateComment {
   #[tracing::instrument(skip(comment, actor, kind, context))]
@@ -84,7 +86,7 @@ impl CreateOrUpdateComment {
     let mut inboxes = vec![];
     for t in tagged_users {
       let person = t
-        .dereference(context, context.client(), request_counter)
+        .dereference::<LemmyError>(context, local_instance(context), request_counter)
         .await?;
       inboxes.push(person.shared_inbox_or_inbox_url());
     }
@@ -97,6 +99,15 @@ impl CreateOrUpdateComment {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for CreateOrUpdateComment {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -108,7 +119,6 @@ impl ActivityHandler for CreateOrUpdateComment {
     let post = self.object.get_parents(context, request_counter).await?.0;
     let community = self.get_community(context, request_counter).await?;
 
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
     verify_domains_match(self.actor.inner(), self.object.id.inner())?;
     check_community_deleted_or_removed(&community)?;
index 99305f24cd65026c6a8d7ae8827051664597b79b..b0e0bf36af413729c8ad767c36327d251af2a7c3 100644 (file)
@@ -1,12 +1,12 @@
-use crate::objects::person::ApubPerson;
+use crate::{local_instance, objects::person::ApubPerson};
+use activitypub_federation::core::object_id::ObjectId;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::object_id::ObjectId;
 use lemmy_db_schema::{
   newtypes::LocalUserId,
   source::{comment::Comment, post::Post},
   traits::Crud,
 };
-use lemmy_utils::{utils::scrape_text_for_mentions, LemmyError};
+use lemmy_utils::{error::LemmyError, utils::scrape_text_for_mentions};
 use lemmy_websocket::{send::send_local_notifs, LemmyContext};
 
 pub mod comment;
@@ -24,7 +24,7 @@ async fn get_comment_notif_recipients(
   let post_id = comment.post_id;
   let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
   let actor = actor
-    .dereference(context, context.client(), request_counter)
+    .dereference::<LemmyError>(context, local_instance(context), request_counter)
     .await?;
 
   // Note:
index 286001828ecbc03791303a76a30f1416b4ca9faf..a0d8ce6f44c48ed793ada69cac95c44080500c01 100644 (file)
@@ -3,7 +3,6 @@ use crate::{
     check_community_deleted_or_removed,
     community::{announce::GetCommunity, send_activity_in_community},
     generate_activity_id,
-    verify_activity,
     verify_is_public,
     verify_mod_action,
     verify_person_in_community,
@@ -11,15 +10,16 @@ use crate::{
   activity_lists::AnnouncableActivities,
   objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost},
   protocol::activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType},
+  ActorType,
 };
-use activitystreams_kinds::public;
-use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
+use activitypub_federation::{
+  core::object_id::ObjectId,
   data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType, ApubObject},
-  verify::{verify_domains_match, verify_urls_match},
+  traits::{ActivityHandler, ApubObject},
+  utils::{verify_domains_match, verify_urls_match},
 };
+use activitystreams_kinds::public;
+use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{
     community::Community,
@@ -27,8 +27,9 @@ use lemmy_db_schema::{
   },
   traits::{Crud, Likeable},
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
+use url::Url;
 
 impl CreateOrUpdatePost {
   pub(crate) async fn new(
@@ -77,6 +78,15 @@ impl CreateOrUpdatePost {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for CreateOrUpdatePost {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -85,7 +95,6 @@ impl ActivityHandler for CreateOrUpdatePost {
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     verify_is_public(&self.to, &self.cc)?;
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     let community = self.get_community(context, request_counter).await?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
     check_community_deleted_or_removed(&community)?;
index 295e5b4f16269ed719760f5d5bf0a332744bdaa2..acd50a1aa18705a5a6201f97f93696e7fbe508ff 100644 (file)
@@ -1,21 +1,23 @@
 use crate::{
-  activities::{generate_activity_id, send_lemmy_activity, verify_activity, verify_person},
+  activities::{generate_activity_id, send_lemmy_activity, verify_person},
   objects::{person::ApubPerson, private_message::ApubPrivateMessage},
   protocol::activities::{
     create_or_update::private_message::CreateOrUpdatePrivateMessage,
     CreateOrUpdateType,
   },
+  ActorType,
 };
-use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
+use activitypub_federation::{
+  core::object_id::ObjectId,
   data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType, ApubObject},
-  verify::verify_domains_match,
+  traits::{ActivityHandler, ApubObject},
+  utils::verify_domains_match,
 };
+use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{source::person::Person, traits::Crud};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
+use url::Url;
 
 impl CreateOrUpdatePrivateMessage {
   #[tracing::instrument(skip_all)]
@@ -38,7 +40,7 @@ impl CreateOrUpdatePrivateMessage {
     let create_or_update = CreateOrUpdatePrivateMessage {
       id: id.clone(),
       actor: ObjectId::new(actor.actor_id()),
-      to: [ObjectId::new(recipient.actor_id())],
+      to: ObjectId::new(recipient.actor_id()),
       object: private_message.into_apub(context).await?,
       kind,
       unparsed: Default::default(),
@@ -51,6 +53,15 @@ impl CreateOrUpdatePrivateMessage {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for CreateOrUpdatePrivateMessage {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -58,9 +69,9 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage {
     context: &Data<LemmyContext>,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     verify_person(&self.actor, context, request_counter).await?;
     verify_domains_match(self.actor.inner(), self.object.id.inner())?;
+    verify_domains_match(self.to.inner(), self.object.to.inner())?;
     ApubPrivateMessage::verify(&self.object, self.actor.inner(), context, request_counter).await?;
     Ok(())
   }
index f442494ad3db803a7268aa1bfdc54105b3f0900b..eb3de179a3a8e3dfae455622ca0dba2b7058cf8d 100644 (file)
@@ -3,8 +3,8 @@ use crate::{
     community::announce::GetCommunity,
     deletion::{receive_delete_action, verify_delete_activity, DeletableObjects},
     generate_activity_id,
-    verify_activity,
   },
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::{
     activities::deletion::delete::Delete,
@@ -12,10 +12,10 @@ use crate::{
     IdOrNestedObject,
   },
 };
+use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
 use activitystreams_kinds::activity::DeleteType;
 use anyhow::anyhow;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{data::Data, object_id::ObjectId, traits::ActivityHandler};
 use lemmy_db_schema::{
   source::{
     comment::Comment,
@@ -33,7 +33,7 @@ use lemmy_db_schema::{
   },
   traits::Crud,
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::{
   send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
   LemmyContext,
@@ -44,6 +44,15 @@ use url::Url;
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for Delete {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -51,7 +60,6 @@ impl ActivityHandler for Delete {
     context: &Data<LemmyContext>,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     verify_delete_activity(self, self.summary.is_some(), context, request_counter).await?;
     Ok(())
   }
@@ -73,7 +81,7 @@ impl ActivityHandler for Delete {
       receive_remove_action(
         &self
           .actor
-          .dereference(context, context.client(), request_counter)
+          .dereference::<LemmyError>(context, local_instance(context), request_counter)
           .await?,
         self.object.id(),
         reason,
index a96333d5e315363b9e5f2297230dc7792eedb7e9..d29139858530fbc79cd447896cdd12bfed872eb4 100644 (file)
@@ -1,25 +1,36 @@
 use crate::{
   activities::{generate_activity_id, send_lemmy_activity, verify_is_public, verify_person},
+  local_instance,
   objects::person::ApubPerson,
   protocol::activities::deletion::delete_user::DeleteUser,
 };
-use activitystreams_kinds::{activity::DeleteType, public};
-use lemmy_api_common::utils::{blocking, delete_user_account};
-use lemmy_apub_lib::{
+use activitypub_federation::{
+  core::object_id::ObjectId,
   data::Data,
-  object_id::ObjectId,
   traits::ActivityHandler,
-  verify::verify_urls_match,
+  utils::verify_urls_match,
 };
+use activitystreams_kinds::{activity::DeleteType, public};
+use lemmy_api_common::utils::{blocking, delete_user_account};
 use lemmy_db_schema::source::site::Site;
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
+use url::Url;
 
 /// This can be separate from Delete activity because it doesn't need to be handled in shared inbox
 /// (cause instance actor doesn't have shared inbox).
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for DeleteUser {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   async fn verify(
     &self,
@@ -39,7 +50,7 @@ impl ActivityHandler for DeleteUser {
   ) -> Result<(), LemmyError> {
     let actor = self
       .actor
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     delete_user_account(actor.id, context.pool()).await?;
     Ok(())
index 123e87fbd551565462cfce13b905d469022f5129..6283ffe0aa2693a7c88f59f4190ad4ee96b6c0d8 100644 (file)
@@ -8,6 +8,7 @@ use crate::{
     verify_person_in_community,
   },
   activity_lists::AnnouncableActivities,
+  local_instance,
   objects::{
     comment::ApubComment,
     community::ApubCommunity,
@@ -16,14 +17,15 @@ use crate::{
     private_message::ApubPrivateMessage,
   },
   protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
+  ActorType,
+};
+use activitypub_federation::{
+  core::object_id::ObjectId,
+  traits::ApubObject,
+  utils::verify_domains_match,
 };
 use activitystreams_kinds::public;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  object_id::ObjectId,
-  traits::{ActorType, ApubObject},
-  verify::verify_domains_match,
-};
 use lemmy_db_schema::{
   source::{
     comment::Comment,
@@ -34,7 +36,7 @@ use lemmy_db_schema::{
   },
   traits::Crud,
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::{
   send::{
     send_comment_ws_message_simple,
@@ -236,7 +238,7 @@ async fn receive_delete_action(
     DeletableObjects::Community(community) => {
       if community.local {
         let mod_: Person = actor
-          .dereference(context, context.client(), request_counter)
+          .dereference::<LemmyError>(context, local_instance(context), request_counter)
           .await?
           .deref()
           .clone();
index 34e8974796649c0db4de151ead24aad96079f64d..0854c46e61d97c76bea568e28ac5b2d7c9b2d5d3 100644 (file)
@@ -3,14 +3,14 @@ use crate::{
     community::announce::GetCommunity,
     deletion::{receive_delete_action, verify_delete_activity, DeletableObjects},
     generate_activity_id,
-    verify_activity,
   },
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
 };
+use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
 use activitystreams_kinds::activity::UndoType;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{data::Data, object_id::ObjectId, traits::ActivityHandler};
 use lemmy_db_schema::{
   source::{
     comment::Comment,
@@ -28,7 +28,7 @@ use lemmy_db_schema::{
   },
   traits::Crud,
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::{
   send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
   LemmyContext,
@@ -39,6 +39,15 @@ use url::Url;
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for UndoDelete {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -46,7 +55,6 @@ impl ActivityHandler for UndoDelete {
     context: &Data<LemmyContext>,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     self.object.verify(context, request_counter).await?;
     verify_delete_activity(
       &self.object,
@@ -68,7 +76,7 @@ impl ActivityHandler for UndoDelete {
       UndoDelete::receive_undo_remove_action(
         &self
           .actor
-          .dereference(context, context.client(), request_counter)
+          .dereference::<LemmyError>(context, local_instance(context), request_counter)
           .await?,
         self.object.object.id(),
         context,
index dfc008a94e489f3cb6f078e3c800c3598cd3e23d..410b678e73cdefa8f786ec0fb8c4175aa2dd4ef2 100644 (file)
@@ -1,18 +1,21 @@
 use crate::{
-  activities::{generate_activity_id, send_lemmy_activity, verify_activity},
+  activities::{generate_activity_id, send_lemmy_activity},
+  local_instance,
   protocol::activities::following::{accept::AcceptFollowCommunity, follow::FollowCommunity},
+  ActorType,
 };
-use activitystreams_kinds::activity::AcceptType;
-use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
+use activitypub_federation::{
+  core::object_id::ObjectId,
   data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType},
-  verify::verify_urls_match,
+  traits::ActivityHandler,
+  utils::verify_urls_match,
 };
+use activitystreams_kinds::activity::AcceptType;
+use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{source::community::CommunityFollower, traits::Followable};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
+use url::Url;
 
 impl AcceptFollowCommunity {
   #[tracing::instrument(skip_all)]
@@ -21,11 +24,14 @@ impl AcceptFollowCommunity {
     context: &LemmyContext,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    let community = follow.object.dereference_local(context).await?;
+    let community = follow
+      .object
+      .dereference_local::<LemmyError>(context)
+      .await?;
     let person = follow
       .actor
       .clone()
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let accept = AcceptFollowCommunity {
       actor: ObjectId::new(community.actor_id()),
@@ -46,6 +52,15 @@ impl AcceptFollowCommunity {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for AcceptFollowCommunity {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -53,7 +68,6 @@ impl ActivityHandler for AcceptFollowCommunity {
     context: &Data<LemmyContext>,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     verify_urls_match(self.actor.inner(), self.object.object.inner())?;
     self.object.verify(context, request_counter).await?;
     Ok(())
@@ -67,12 +81,12 @@ impl ActivityHandler for AcceptFollowCommunity {
   ) -> Result<(), LemmyError> {
     let person = self
       .actor
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let community = self
       .object
       .actor
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     // This will throw an error if no follow was requested
     blocking(context.pool(), move |conn| {
index d46b3dc20f130049faa1ff97259d05bc0dae7a7b..f78fadff0a9e010fa862e2ba1b6237e414892a04 100644 (file)
@@ -2,26 +2,24 @@ use crate::{
   activities::{
     generate_activity_id,
     send_lemmy_activity,
-    verify_activity,
     verify_person,
     verify_person_in_community,
   },
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::activities::following::{accept::AcceptFollowCommunity, follow::FollowCommunity},
+  ActorType,
 };
+use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
 use activitystreams_kinds::activity::FollowType;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType},
-};
 use lemmy_db_schema::{
   source::community::{CommunityFollower, CommunityFollowerForm},
   traits::Followable,
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
+use url::Url;
 
 impl FollowCommunity {
   pub(in crate::activities::following) fn new(
@@ -66,6 +64,15 @@ impl FollowCommunity {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for FollowCommunity {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -73,11 +80,10 @@ impl ActivityHandler for FollowCommunity {
     context: &Data<LemmyContext>,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     verify_person(&self.actor, context, request_counter).await?;
     let community = self
       .object
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
     Ok(())
@@ -91,11 +97,11 @@ impl ActivityHandler for FollowCommunity {
   ) -> Result<(), LemmyError> {
     let person = self
       .actor
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let community = self
       .object
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let community_follower_form = CommunityFollowerForm {
       community_id: community.id,
index f70acdf2725912ebd57cbf041bd3b20ee13accb6..fd178dab2022dd05188a0ee3d8f66590cc4e772b 100644 (file)
@@ -1,22 +1,25 @@
 use crate::{
-  activities::{generate_activity_id, send_lemmy_activity, verify_activity, verify_person},
+  activities::{generate_activity_id, send_lemmy_activity, verify_person},
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::activities::following::{follow::FollowCommunity, undo_follow::UndoFollowCommunity},
+  ActorType,
 };
-use activitystreams_kinds::activity::UndoType;
-use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
+use activitypub_federation::{
+  core::object_id::ObjectId,
   data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType},
-  verify::verify_urls_match,
+  traits::ActivityHandler,
+  utils::verify_urls_match,
 };
+use activitystreams_kinds::activity::UndoType;
+use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::community::{CommunityFollower, CommunityFollowerForm},
   traits::Followable,
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
+use url::Url;
 
 impl UndoFollowCommunity {
   #[tracing::instrument(skip_all)]
@@ -44,6 +47,15 @@ impl UndoFollowCommunity {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for UndoFollowCommunity {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -51,7 +63,6 @@ impl ActivityHandler for UndoFollowCommunity {
     context: &Data<LemmyContext>,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     verify_urls_match(self.actor.inner(), self.object.actor.inner())?;
     verify_person(&self.actor, context, request_counter).await?;
     self.object.verify(context, request_counter).await?;
@@ -66,12 +77,12 @@ impl ActivityHandler for UndoFollowCommunity {
   ) -> Result<(), LemmyError> {
     let person = self
       .actor
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let community = self
       .object
       .object
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
 
     let community_follower_form = CommunityFollowerForm {
index 2c8b0921cef2305e25fd8e374eb08de224a5c894..3a4754996b282990ddd101f82eed6abeb4ab3044 100644 (file)
@@ -1,24 +1,24 @@
 use crate::{
-  check_is_apub_id_valid,
-  context::WithContext,
   generate_moderators_url,
   insert_activity,
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
+  ActorType,
+  CONTEXT,
+};
+use activitypub_federation::{
+  core::{activity_queue::SendActivity, object_id::ObjectId},
+  deser::context::WithContext,
 };
 use activitystreams_kinds::public;
 use anyhow::anyhow;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  activity_queue::send_activity,
-  object_id::ObjectId,
-  traits::ActorType,
-  verify::verify_domains_match,
-};
 use lemmy_db_schema::source::community::Community;
 use lemmy_db_views_actor::structs::{CommunityPersonBanView, CommunityView};
-use lemmy_utils::{settings::structs::Settings, LemmyError};
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::Serialize;
+use std::ops::Deref;
 use tracing::info;
 use url::{ParseError, Url};
 use uuid::Uuid;
@@ -39,7 +39,7 @@ async fn verify_person(
   request_counter: &mut i32,
 ) -> Result<(), LemmyError> {
   let person = person_id
-    .dereference(context, context.client(), request_counter)
+    .dereference::<LemmyError>(context, local_instance(context), request_counter)
     .await?;
   if person.banned {
     let err = anyhow!("Person {} is banned", person_id);
@@ -58,7 +58,7 @@ pub(crate) async fn verify_person_in_community(
   request_counter: &mut i32,
 ) -> Result<(), LemmyError> {
   let person = person_id
-    .dereference(context, context.client(), request_counter)
+    .dereference::<LemmyError>(context, local_instance(context), request_counter)
     .await?;
   if person.banned {
     return Err(LemmyError::from_message("Person is banned from site"));
@@ -74,12 +74,6 @@ pub(crate) async fn verify_person_in_community(
   Ok(())
 }
 
-fn verify_activity(id: &Url, actor: &Url, settings: &Settings) -> Result<(), LemmyError> {
-  check_is_apub_id_valid(actor, false, settings)?;
-  verify_domains_match(id, actor)?;
-  Ok(())
-}
-
 /// Verify that the actor is a community mod. This check is only run if the community is local,
 /// because in case of remote communities, admins can also perform mod actions. As admin status
 /// is not federated, we cant verify their actions remotely.
@@ -97,7 +91,7 @@ pub(crate) async fn verify_mod_action(
 ) -> Result<(), LemmyError> {
   if community.local {
     let actor = mod_id
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
 
     // Note: this will also return true for admins in addition to mods, but as we dont know about
@@ -183,15 +177,15 @@ async fn send_lemmy_activity<T: Serialize>(
   if !context.settings().federation.enabled || inboxes.is_empty() {
     return Ok(());
   }
-  let activity = WithContext::new(activity);
+  let activity = WithContext::new(activity, CONTEXT.deref().clone());
 
   info!("Sending activity {}", activity_id.to_string());
 
   // Don't send anything to ourselves
   // TODO: this should be a debug assert
   let hostname = context.settings().get_hostname_without_port()?;
-  let inboxes: Vec<&Url> = inboxes
-    .iter()
+  let inboxes: Vec<Url> = inboxes
+    .into_iter()
     .filter(|i| i.domain().expect("valid inbox url") != hostname)
     .collect();
 
@@ -200,13 +194,15 @@ async fn send_lemmy_activity<T: Serialize>(
   let object_value = serde_json::to_value(&activity)?;
   insert_activity(activity_id, object_value, true, sensitive, context.pool()).await?;
 
-  send_activity(
-    activity_id,
-    actor,
+  SendActivity {
+    activity_id: activity_id.clone(),
+    actor_public_key: actor.get_public_key(),
+    actor_private_key: actor.private_key().expect("actor has private key"),
     inboxes,
-    serialised_activity,
-    context.client(),
-    context.activity_queue(),
-  )
-  .await
+    activity: serialised_activity,
+  }
+  .send(local_instance(context))
+  .await?;
+
+  Ok(())
 }
index f2e3f24f8c0025709b1873ba02f1262bd8fd657c..4896b4c64733139c3e56402bd88237e8df11f2e4 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_db_schema::{
   },
   traits::Likeable,
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::{
   send::{send_comment_ws_message_simple, send_post_ws_message},
   LemmyContext,
index eb350770ed22bf33be79a6dd120ea4ef2e3dd460..4f410ae9764cd6dd482d7edb15e98472871df97d 100644 (file)
@@ -2,30 +2,32 @@ use crate::{
   activities::{
     community::{announce::GetCommunity, send_activity_in_community},
     generate_activity_id,
-    verify_activity,
     verify_is_public,
     verify_person_in_community,
     voting::{undo_vote_comment, undo_vote_post},
   },
   activity_lists::AnnouncableActivities,
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::activities::voting::{
     undo_vote::UndoVote,
     vote::{Vote, VoteType},
   },
+  ActorType,
   PostOrComment,
 };
-use activitystreams_kinds::{activity::UndoType, public};
-use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
+use activitypub_federation::{
+  core::object_id::ObjectId,
   data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType},
-  verify::verify_urls_match,
+  traits::ActivityHandler,
+  utils::verify_urls_match,
 };
+use activitystreams_kinds::{activity::UndoType, public};
+use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
+use url::Url;
 
 impl UndoVote {
   /// UndoVote has as:Public value in cc field, unlike other activities. This indicates to other
@@ -67,6 +69,15 @@ impl UndoVote {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for UndoVote {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -75,7 +86,6 @@ impl ActivityHandler for UndoVote {
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     verify_is_public(&self.to, &self.cc)?;
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     let community = self.get_community(context, request_counter).await?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
     verify_urls_match(self.actor.inner(), self.object.actor.inner())?;
@@ -91,12 +101,12 @@ impl ActivityHandler for UndoVote {
   ) -> Result<(), LemmyError> {
     let actor = self
       .actor
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let object = self
       .object
       .object
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     match object {
       PostOrComment::Post(p) => undo_vote_post(actor, &p, context).await,
index a851e28f4e543ee115ec91da46a3b8690e65c340..7971704db120db99b719b721beecd065456573a9 100644 (file)
@@ -2,31 +2,29 @@ use crate::{
   activities::{
     community::{announce::GetCommunity, send_activity_in_community},
     generate_activity_id,
-    verify_activity,
     verify_is_public,
     verify_person_in_community,
     voting::{vote_comment, vote_post},
   },
   activity_lists::AnnouncableActivities,
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::activities::voting::vote::{Vote, VoteType},
+  ActorType,
   PostOrComment,
 };
+use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
 use activitystreams_kinds::public;
 use anyhow::anyhow;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  data::Data,
-  object_id::ObjectId,
-  traits::{ActivityHandler, ActorType},
-};
 use lemmy_db_schema::{
   newtypes::CommunityId,
   source::{community::Community, post::Post, site::Site},
   traits::Crud,
 };
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
+use url::Url;
 
 /// Vote has as:Public value in cc field, unlike other activities. This indicates to other software
 /// (like GNU social, or presumably Mastodon), that the like actor should not be disclosed.
@@ -73,6 +71,15 @@ impl Vote {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for Vote {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+
+  fn id(&self) -> &Url {
+    &self.id
+  }
+
+  fn actor(&self) -> &Url {
+    self.actor.inner()
+  }
 
   #[tracing::instrument(skip_all)]
   async fn verify(
@@ -81,7 +88,6 @@ impl ActivityHandler for Vote {
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     verify_is_public(&self.to, &self.cc)?;
-    verify_activity(&self.id, self.actor.inner(), &context.settings())?;
     let community = self.get_community(context, request_counter).await?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
     let site = blocking(context.pool(), Site::read_local_site).await??;
@@ -99,11 +105,11 @@ impl ActivityHandler for Vote {
   ) -> Result<(), LemmyError> {
     let actor = self
       .actor
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let object = self
       .object
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     match object {
       PostOrComment::Post(p) => vote_post(&self.kind, actor, &p, context).await,
@@ -122,7 +128,7 @@ impl GetCommunity for Vote {
   ) -> Result<ApubCommunity, LemmyError> {
     let object = self
       .object
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let cid = match object {
       PostOrComment::Post(p) => p.community_id,
index c9debefaa2fb97c0dbd8a7e3982355635c800bb5..656c8020693b9f8e1eccb7d5e29a54fba3a298ea 100644 (file)
@@ -1,5 +1,5 @@
 use crate::{
-  activities::community::announce::GetCommunity,
+  activities::{community::announce::GetCommunity, verify_person_in_community},
   objects::community::ApubCommunity,
   protocol::{
     activities::{
@@ -28,25 +28,29 @@ use crate::{
     Id,
   },
 };
-use lemmy_apub_lib::traits::ActivityHandler;
-use lemmy_utils::LemmyError;
+use activitypub_federation::{
+  core::object_id::ObjectId,
+  data::Data,
+  deser::context::WithContext,
+  traits::{activity_handler, ActivityHandler},
+};
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
+#[derive(Debug, Deserialize, Serialize)]
 #[serde(untagged)]
-#[activity_handler(LemmyContext)]
+#[activity_handler(LemmyContext, LemmyError)]
 pub enum SharedInboxActivities {
-  GroupInboxActivities(Box<GroupInboxActivities>),
+  GroupInboxActivities(Box<WithContext<GroupInboxActivities>>),
   // Note, pm activities need to be at the end, otherwise comments will end up here. We can probably
   // avoid this problem by replacing createpm.object with our own struct, instead of NoteExt.
-  PersonInboxActivities(Box<PersonInboxActivities>),
+  PersonInboxActivities(Box<WithContext<PersonInboxActivities>>),
 }
 
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
+#[derive(Debug, Deserialize, Serialize)]
 #[serde(untagged)]
-#[activity_handler(LemmyContext)]
 pub enum GroupInboxActivities {
   FollowCommunity(FollowCommunity),
   UndoFollowCommunity(UndoFollowCommunity),
@@ -54,9 +58,9 @@ pub enum GroupInboxActivities {
   Report(Report),
 }
 
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
 #[serde(untagged)]
-#[activity_handler(LemmyContext)]
+#[activity_handler(LemmyContext, LemmyError)]
 pub enum PersonInboxActivities {
   AcceptFollowCommunity(AcceptFollowCommunity),
   /// Some activities can also be sent from user to user, eg a comment with mentions
@@ -67,9 +71,9 @@ pub enum PersonInboxActivities {
   AnnounceActivity(AnnounceActivity),
 }
 
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
 #[serde(untagged)]
-#[activity_handler(LemmyContext)]
+#[activity_handler(LemmyContext, LemmyError)]
 pub enum AnnouncableActivities {
   CreateOrUpdateComment(CreateOrUpdateComment),
   CreateOrUpdatePost(Box<CreateOrUpdatePost>),
@@ -86,9 +90,9 @@ pub enum AnnouncableActivities {
   Page(Page),
 }
 
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
 #[serde(untagged)]
-#[activity_handler(LemmyContext)]
+#[activity_handler(LemmyContext, LemmyError)]
 #[allow(clippy::enum_variant_names)]
 pub enum SiteInboxActivities {
   BlockUser(BlockUser),
@@ -124,21 +128,72 @@ impl GetCommunity for AnnouncableActivities {
 }
 
 impl Id for AnnouncableActivities {
+  fn object_id(&self) -> &Url {
+    ActivityHandler::id(self)
+  }
+}
+
+// Need to implement this manually to announce matching activities
+#[async_trait::async_trait(?Send)]
+impl ActivityHandler for GroupInboxActivities {
+  type DataType = LemmyContext;
+  type Error = LemmyError;
+
   fn id(&self) -> &Url {
-    use AnnouncableActivities::*;
     match self {
-      CreateOrUpdateComment(c) => &c.id,
-      CreateOrUpdatePost(c) => &c.id,
-      Vote(v) => &v.id,
-      UndoVote(u) => &u.id,
-      Delete(d) => &d.id,
-      UndoDelete(u) => &u.id,
-      UpdateCommunity(u) => &u.id,
-      BlockUser(b) => &b.id,
-      UndoBlockUser(u) => &u.id,
-      AddMod(a) => &a.id,
-      RemoveMod(r) => &r.id,
-      Page(p) => p.id.inner(),
+      GroupInboxActivities::FollowCommunity(a) => a.id(),
+      GroupInboxActivities::UndoFollowCommunity(a) => a.id(),
+      GroupInboxActivities::AnnouncableActivities(a) => a.object_id(),
+      GroupInboxActivities::Report(a) => a.id(),
+    }
+  }
+
+  fn actor(&self) -> &Url {
+    match self {
+      GroupInboxActivities::FollowCommunity(a) => a.actor(),
+      GroupInboxActivities::UndoFollowCommunity(a) => a.actor(),
+      GroupInboxActivities::AnnouncableActivities(a) => a.actor(),
+      GroupInboxActivities::Report(a) => a.actor(),
+    }
+  }
+
+  async fn verify(
+    &self,
+    data: &Data<Self::DataType>,
+    request_counter: &mut i32,
+  ) -> Result<(), LemmyError> {
+    match self {
+      GroupInboxActivities::FollowCommunity(a) => a.verify(data, request_counter).await,
+      GroupInboxActivities::UndoFollowCommunity(a) => a.verify(data, request_counter).await,
+      GroupInboxActivities::AnnouncableActivities(a) => a.verify(data, request_counter).await,
+      GroupInboxActivities::Report(a) => a.verify(data, request_counter).await,
+    }
+  }
+
+  async fn receive(
+    self,
+    data: &Data<Self::DataType>,
+    request_counter: &mut i32,
+  ) -> Result<(), LemmyError> {
+    match self {
+      GroupInboxActivities::FollowCommunity(a) => a.receive(data, request_counter).await,
+      GroupInboxActivities::UndoFollowCommunity(a) => a.receive(data, request_counter).await,
+      GroupInboxActivities::AnnouncableActivities(activity) => {
+        activity.clone().receive(data, request_counter).await?;
+
+        // Ignore failures in get_community(). those happen because Delete/PrivateMessage is not in a
+        // community, but looks identical to Delete/Post or Delete/Comment which are in a community.
+        let community = activity.get_community(data, &mut 0).await;
+        if let Ok(community) = community {
+          if community.local {
+            let actor_id = ObjectId::new(activity.actor().clone());
+            verify_person_in_community(&actor_id, &community, data, &mut 0).await?;
+            AnnounceActivity::send(*activity, &community, data).await?;
+          }
+        }
+        Ok(())
+      }
+      GroupInboxActivities::Report(a) => a.receive(data, request_counter).await,
     }
   }
 }
index 028174ae9ec234a76b08050ebf1fbe1ff97b00f3..b8cd6469012ded2ea2b3bfbb654178c387546a88 100644 (file)
@@ -1,19 +1,24 @@
 use crate::{
   collections::CommunityContext,
   generate_moderators_url,
+  local_instance,
   objects::person::ApubPerson,
   protocol::collections::group_moderators::GroupModerators,
 };
+use activitypub_federation::{
+  core::object_id::ObjectId,
+  traits::ApubObject,
+  utils::verify_domains_match,
+};
 use activitystreams_kinds::collection::OrderedCollectionType;
 use chrono::NaiveDateTime;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject, verify::verify_domains_match};
 use lemmy_db_schema::{
   source::community::{CommunityModerator, CommunityModeratorForm},
   traits::Joinable,
 };
 use lemmy_db_views_actor::structs::CommunityModeratorView;
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use url::Url;
 
 #[derive(Clone, Debug)]
@@ -22,8 +27,8 @@ pub(crate) struct ApubCommunityModerators(pub(crate) Vec<CommunityModeratorView>
 #[async_trait::async_trait(?Send)]
 impl ApubObject for ApubCommunityModerators {
   type DataType = CommunityContext;
-  type TombstoneType = ();
   type ApubType = GroupModerators;
+  type Error = LemmyError;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     None
@@ -66,10 +71,6 @@ impl ApubObject for ApubCommunityModerators {
     })
   }
 
-  fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError> {
-    unimplemented!()
-  }
-
   #[tracing::instrument(skip_all)]
   async fn verify(
     group_moderators: &GroupModerators,
@@ -111,7 +112,7 @@ impl ApubObject for ApubCommunityModerators {
     for mod_id in apub.ordered_items {
       let mod_id = ObjectId::new(mod_id);
       let mod_user: ApubPerson = mod_id
-        .dereference(&data.1, data.1.client(), request_counter)
+        .dereference::<LemmyError>(&data.1, local_instance(&data.1), request_counter)
         .await?;
 
       if !current_moderators
index 098471c260b7f08da920c6941c4ef1f8b850b125..dde98859aedb78c9a35f86772d522a16a6868a51 100644 (file)
@@ -8,17 +8,17 @@ use crate::{
     collections::group_outbox::GroupOutbox,
   },
 };
+use activitypub_federation::{
+  data::Data,
+  traits::{ActivityHandler, ApubObject},
+  utils::verify_domains_match,
+};
 use activitystreams_kinds::collection::OrderedCollectionType;
 use chrono::NaiveDateTime;
 use futures::future::join_all;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  data::Data,
-  traits::{ActivityHandler, ApubObject},
-  verify::verify_domains_match,
-};
 use lemmy_db_schema::source::post::Post;
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use url::Url;
 
 #[derive(Clone, Debug)]
@@ -27,8 +27,8 @@ pub(crate) struct ApubCommunityOutbox(Vec<ApubPost>);
 #[async_trait::async_trait(?Send)]
 impl ApubObject for ApubCommunityOutbox {
   type DataType = CommunityContext;
-  type TombstoneType = ();
   type ApubType = GroupOutbox;
+  type Error = LemmyError;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     None
@@ -78,11 +78,6 @@ impl ApubObject for ApubCommunityOutbox {
     })
   }
 
-  fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError> {
-    // no tombstone for this, there is only a tombstone for the community
-    unimplemented!()
-  }
-
   #[tracing::instrument(skip_all)]
   async fn verify(
     group_outbox: &GroupOutbox,
diff --git a/crates/apub/src/context.rs b/crates/apub/src/context.rs
deleted file mode 100644 (file)
index 9d2d3d4..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-use once_cell::sync::Lazy;
-use serde::{Deserialize, Serialize};
-
-static CONTEXT: Lazy<Vec<serde_json::Value>> = Lazy::new(|| {
-  serde_json::from_str(include_str!("../assets/lemmy/context.json")).expect("parse context")
-});
-
-#[derive(Serialize, Deserialize, Debug)]
-pub(crate) struct WithContext<T> {
-  #[serde(rename = "@context")]
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
-  context: Vec<serde_json::Value>,
-  #[serde(flatten)]
-  inner: T,
-}
-
-impl<T> WithContext<T> {
-  pub(crate) fn new(inner: T) -> WithContext<T> {
-    WithContext {
-      context: (*CONTEXT).clone(),
-      inner,
-    }
-  }
-  pub(crate) fn inner(self) -> T {
-    self.inner
-  }
-}
index cd889ccc6106a43104ee2f96359c031316f9aa2c..274c31d4453447d2951700e1480dcacbdbcb4dfc 100644 (file)
@@ -1,9 +1,9 @@
-use crate::fetcher::webfinger::webfinger_resolve_actor;
+use crate::{fetcher::webfinger::webfinger_resolve_actor, ActorType};
+use activitypub_federation::traits::ApubObject;
 use itertools::Itertools;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::traits::{ActorType, ApubObject};
 use lemmy_db_schema::traits::ApubActor;
-use lemmy_utils::{settings::structs::Settings, LemmyError};
+use lemmy_utils::{error::LemmyError, settings::structs::Settings};
 use lemmy_websocket::LemmyContext;
 
 pub mod post_or_comment;
@@ -20,8 +20,11 @@ pub async fn resolve_actor_identifier<Actor, DbActor>(
   context: &LemmyContext,
 ) -> Result<DbActor, LemmyError>
 where
-  Actor:
-    ApubObject<DataType = LemmyContext> + ApubObject<DbType = DbActor> + ActorType + Send + 'static,
+  Actor: ApubObject<DataType = LemmyContext, Error = LemmyError>
+    + ApubObject<DbType = DbActor>
+    + ActorType
+    + Send
+    + 'static,
   for<'de2> <Actor as ApubObject>::ApubType: serde::Deserialize<'de2>,
   DbActor: ApubActor + Send + 'static,
 {
index eaebeca6b736f14664a6cff59008cba3c5569fbd..ba9a2ac49c9737d592f3a5a27e2febf544e91747 100644 (file)
@@ -2,9 +2,9 @@ use crate::{
   objects::{comment::ApubComment, post::ApubPost},
   protocol::objects::{note::Note, page::Page},
 };
+use activitypub_federation::traits::ApubObject;
 use chrono::NaiveDateTime;
-use lemmy_apub_lib::traits::ApubObject;
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
 use url::Url;
@@ -27,7 +27,7 @@ impl ApubObject for PostOrComment {
   type DataType = LemmyContext;
   type ApubType = PageOrNote;
   type DbType = ();
-  type TombstoneType = ();
+  type Error = LemmyError;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     None
@@ -60,10 +60,6 @@ impl ApubObject for PostOrComment {
     unimplemented!()
   }
 
-  fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError> {
-    unimplemented!()
-  }
-
   #[tracing::instrument(skip_all)]
   async fn verify(
     apub: &Self::ApubType,
index e4ae45e6844bd008b242b48e477ed72e94fa3858..43244b4d7a7f54328a7029f63526e06eb8100e54 100644 (file)
@@ -1,11 +1,12 @@
 use crate::{
   fetcher::webfinger::webfinger_resolve_actor,
+  local_instance,
   objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost},
   protocol::objects::{group::Group, note::Note, page::Page, person::Person},
 };
+use activitypub_federation::{core::object_id::ObjectId, traits::ApubObject};
 use chrono::NaiveDateTime;
-use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
 use url::Url;
@@ -23,10 +24,11 @@ pub async fn search_by_apub_id(
   context: &LemmyContext,
 ) -> Result<SearchableObjects, LemmyError> {
   let request_counter = &mut 0;
+  let instance = local_instance(context);
   match Url::parse(query) {
     Ok(url) => {
       ObjectId::new(url)
-        .dereference(context, context.client(), request_counter)
+        .dereference::<LemmyError>(context, instance, request_counter)
         .await
     }
     Err(_) => {
@@ -37,7 +39,7 @@ pub async fn search_by_apub_id(
             webfinger_resolve_actor::<ApubPerson>(identifier, context, request_counter).await?;
           Ok(SearchableObjects::Person(
             ObjectId::new(id)
-              .dereference(context, context.client(), request_counter)
+              .dereference::<LemmyError>(context, instance, request_counter)
               .await?,
           ))
         }
@@ -46,7 +48,7 @@ pub async fn search_by_apub_id(
             webfinger_resolve_actor::<ApubCommunity>(identifier, context, request_counter).await?;
           Ok(SearchableObjects::Community(
             ObjectId::new(id)
-              .dereference(context, context.client(), request_counter)
+              .dereference::<LemmyError>(context, instance, request_counter)
               .await?,
           ))
         }
@@ -79,7 +81,7 @@ impl ApubObject for SearchableObjects {
   type DataType = LemmyContext;
   type ApubType = SearchableApubTypes;
   type DbType = ();
-  type TombstoneType = ();
+  type Error = LemmyError;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     match self {
@@ -133,10 +135,6 @@ impl ApubObject for SearchableObjects {
     unimplemented!()
   }
 
-  fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError> {
-    unimplemented!()
-  }
-
   #[tracing::instrument(skip_all)]
   async fn verify(
     apub: &Self::ApubType,
index 7ec5e9dd90cfd4b6494c9bd577cd9feb5b7c9e34..16a74c2e51db0aecd859f71c722e2dd18f71e10c 100644 (file)
@@ -2,9 +2,9 @@ use crate::{
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::objects::{group::Group, person::Person},
 };
+use activitypub_federation::{core::inbox::ActorPublicKey, traits::ApubObject};
 use chrono::NaiveDateTime;
-use lemmy_apub_lib::traits::{ActorType, ApubObject};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use url::Url;
@@ -33,7 +33,7 @@ impl ApubObject for UserOrCommunity {
   type DataType = LemmyContext;
   type ApubType = PersonOrGroup;
   type DbType = ();
-  type TombstoneType = ();
+  type Error = LemmyError;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     Some(match self {
@@ -68,10 +68,6 @@ impl ApubObject for UserOrCommunity {
     unimplemented!()
   }
 
-  fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError> {
-    unimplemented!()
-  }
-
   #[tracing::instrument(skip_all)]
   async fn verify(
     apub: &Self::ApubType,
@@ -106,30 +102,11 @@ impl ApubObject for UserOrCommunity {
   }
 }
 
-impl ActorType for UserOrCommunity {
-  fn actor_id(&self) -> Url {
-    match self {
-      UserOrCommunity::User(p) => p.actor_id(),
-      UserOrCommunity::Community(p) => p.actor_id(),
-    }
-  }
-
-  fn public_key(&self) -> String {
+impl ActorPublicKey for UserOrCommunity {
+  fn public_key(&self) -> &str {
     match self {
       UserOrCommunity::User(p) => p.public_key(),
       UserOrCommunity::Community(p) => p.public_key(),
     }
   }
-
-  fn private_key(&self) -> Option<String> {
-    todo!()
-  }
-
-  fn inbox_url(&self) -> Url {
-    todo!()
-  }
-
-  fn shared_inbox_url(&self) -> Option<Url> {
-    todo!()
-  }
 }
index da516b1da4e42a46d703fa7b244545048316d730..b53a988eec21de2713ba88d34d098c8b4157dbea 100644 (file)
@@ -1,11 +1,9 @@
+use crate::{local_instance, ActorType};
+use activitypub_federation::{core::object_id::ObjectId, traits::ApubObject};
 use anyhow::anyhow;
 use itertools::Itertools;
-use lemmy_apub_lib::{
-  object_id::ObjectId,
-  traits::{ActorType, ApubObject},
-};
 use lemmy_db_schema::newtypes::DbUrl;
-use lemmy_utils::{request::retry, LemmyError};
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use tracing::debug;
@@ -34,7 +32,7 @@ pub(crate) async fn webfinger_resolve_actor<Kind>(
   request_counter: &mut i32,
 ) -> Result<DbUrl, LemmyError>
 where
-  Kind: ApubObject<DataType = LemmyContext> + ActorType + Send + 'static,
+  Kind: ApubObject<DataType = LemmyContext, Error = LemmyError> + ActorType + Send + 'static,
   for<'de2> <Kind as ApubObject>::ApubType: serde::Deserialize<'de2>,
 {
   let protocol = context.settings().get_protocol_string();
@@ -53,7 +51,7 @@ where
     return Err(LemmyError::from_message("Request retry limit reached"));
   }
 
-  let response = retry(|| context.client().get(&fetch_url).send()).await?;
+  let response = context.client().get(&fetch_url).send().await?;
 
   let res: WebfingerResponse = response.json().await.map_err(LemmyError::from)?;
 
@@ -71,7 +69,7 @@ where
     .collect();
   for l in links {
     let object = ObjectId::<Kind>::new(l)
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await;
     if object.is_ok() {
       return object.map(|o| o.actor_id().into());
index 1918a38e8ceb3495223b09d3d88484091965d0c8..59cbee8e89309b71ffd605717fb7fcadb29dbbd8 100644 (file)
@@ -2,12 +2,12 @@ use crate::{
   http::{create_apub_response, create_apub_tombstone_response},
   objects::comment::ApubComment,
 };
+use activitypub_federation::traits::ApubObject;
 use actix_web::{web, web::Path, HttpResponse};
 use diesel::result::Error::NotFound;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::traits::ApubObject;
 use lemmy_db_schema::{newtypes::CommentId, source::comment::Comment, traits::Crud};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
 
@@ -33,6 +33,6 @@ pub(crate) async fn get_apub_comment(
   if !comment.deleted {
     Ok(create_apub_response(&comment.into_apub(&**context).await?))
   } else {
-    Ok(create_apub_tombstone_response(&comment.to_tombstone()?))
+    Ok(create_apub_tombstone_response(comment.ap_id.clone()))
   }
 }
index 41f6d1c0ba515b34100c6f822211eadaf64643d8..6b8c7fe7e2eeaa6d48086355d8e55b9b5e524d63 100644 (file)
@@ -1,34 +1,27 @@
 use crate::{
-  activities::{community::announce::GetCommunity, verify_person_in_community},
   activity_lists::GroupInboxActivities,
   collections::{
     community_moderators::ApubCommunityModerators,
     community_outbox::ApubCommunityOutbox,
     CommunityContext,
   },
-  context::WithContext,
   generate_outbox_url,
-  http::{
-    create_apub_response,
-    create_apub_tombstone_response,
-    payload_to_string,
-    receive_activity,
-    ActivityCommonFields,
-  },
-  objects::community::ApubCommunity,
-  protocol::{
-    activities::community::announce::AnnounceActivity,
-    collections::group_followers::GroupFollowers,
-  },
+  http::{create_apub_response, create_apub_tombstone_response, receive_lemmy_activity},
+  local_instance,
+  objects::{community::ApubCommunity, person::ApubPerson},
+  protocol::collections::group_followers::GroupFollowers,
+};
+use activitypub_federation::{
+  core::object_id::ObjectId,
+  deser::context::WithContext,
+  traits::ApubObject,
 };
-use actix_web::{web, web::Payload, HttpRequest, HttpResponse};
+use actix_web::{web, HttpRequest, HttpResponse};
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject};
 use lemmy_db_schema::{source::community::Community, traits::ApubActor};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
-use tracing::info;
 
 #[derive(Deserialize)]
 pub(crate) struct CommunityQuery {
@@ -52,7 +45,7 @@ pub(crate) async fn get_apub_community_http(
 
     Ok(create_apub_response(&apub))
   } else {
-    Ok(create_apub_tombstone_response(&community.to_tombstone()?))
+    Ok(create_apub_tombstone_response(community.actor_id.clone()))
   }
 }
 
@@ -60,42 +53,11 @@ pub(crate) async fn get_apub_community_http(
 #[tracing::instrument(skip_all)]
 pub async fn community_inbox(
   request: HttpRequest,
-  payload: Payload,
-  _path: web::Path<String>,
+  payload: String,
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError> {
-  let unparsed = payload_to_string(payload).await?;
-  info!("Received community inbox activity {}", unparsed);
-  let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?;
-  let activity = serde_json::from_str::<WithContext<GroupInboxActivities>>(&unparsed)?;
-
-  receive_group_inbox(activity.inner(), activity_data, request, &context).await?;
-
-  Ok(HttpResponse::Ok().finish())
-}
-
-pub(in crate::http) async fn receive_group_inbox(
-  activity: GroupInboxActivities,
-  activity_data: ActivityCommonFields,
-  request: HttpRequest,
-  context: &LemmyContext,
-) -> Result<HttpResponse, LemmyError> {
-  let actor_id = ObjectId::new(activity_data.actor.clone());
-  let res = receive_activity(request, activity.clone(), activity_data, context).await?;
-
-  if let GroupInboxActivities::AnnouncableActivities(announcable) = activity {
-    // Ignore failures in get_community(). those happen because Delete/PrivateMessage is not in a
-    // community, but looks identical to Delete/Post or Delete/Comment which are in a community.
-    let community = announcable.get_community(context, &mut 0).await;
-    if let Ok(community) = community {
-      if community.local {
-        verify_person_in_community(&actor_id, &community, context, &mut 0).await?;
-        AnnounceActivity::send(*announcable, &community, context).await?;
-      }
-    }
-  }
-
-  Ok(res)
+  receive_lemmy_activity::<WithContext<GroupInboxActivities>, ApubPerson>(request, payload, context)
+    .await
 }
 
 /// Returns an empty followers collection, only populating the size (for privacy).
@@ -124,7 +86,7 @@ pub(crate) async fn get_apub_community_outbox(
   let id = ObjectId::new(generate_outbox_url(&community.actor_id)?);
   let outbox_data = CommunityContext(community.into(), context.get_ref().clone());
   let outbox: ApubCommunityOutbox = id
-    .dereference(&outbox_data, context.client(), &mut 0)
+    .dereference::<LemmyError>(&outbox_data, local_instance(&context), &mut 0)
     .await?;
   Ok(create_apub_response(&outbox.into_apub(&outbox_data).await?))
 }
@@ -142,7 +104,7 @@ pub(crate) async fn get_apub_community_moderators(
   let id = ObjectId::new(generate_outbox_url(&community.actor_id)?);
   let outbox_data = CommunityContext(community, context.get_ref().clone());
   let moderators: ApubCommunityModerators = id
-    .dereference(&outbox_data, context.client(), &mut 0)
+    .dereference::<LemmyError>(&outbox_data, local_instance(&context), &mut 0)
     .await?;
   Ok(create_apub_response(
     &moderators.into_apub(&outbox_data).await?,
index 0112d2056d5554b75065ab5492d3d3b5626765c9..d5d94066187d9c2df0a218bafb73e84352e09883 100644 (file)
@@ -1,34 +1,29 @@
 use crate::{
   activity_lists::SharedInboxActivities,
-  check_is_apub_id_valid,
-  context::WithContext,
   fetcher::user_or_community::UserOrCommunity,
-  http::{community::receive_group_inbox, person::receive_person_inbox},
   insert_activity,
+  local_instance,
+  protocol::objects::tombstone::Tombstone,
+  CONTEXT,
 };
-use actix_web::{
-  web,
-  web::{Bytes, BytesMut, Payload},
-  HttpRequest,
-  HttpResponse,
-};
-use anyhow::{anyhow, Context};
-use futures::StreamExt;
-use http::StatusCode;
-use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
+use activitypub_federation::{
+  core::inbox::{receive_activity, ActorPublicKey},
   data::Data,
-  object_id::ObjectId,
-  signatures::verify_signature,
-  traits::{ActivityHandler, ActorType},
+  deser::context::WithContext,
+  traits::{ActivityHandler, ApubObject},
   APUB_JSON_CONTENT_TYPE,
 };
+use actix_web::{web, HttpRequest, HttpResponse};
+use http::StatusCode;
+use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::source::activity::Activity;
-use lemmy_utils::{location_info, LemmyError};
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
-use serde::{Deserialize, Serialize};
-use std::{fmt::Debug, io::Read};
-use tracing::{debug, info};
+use once_cell::sync::OnceCell;
+use serde::{de::DeserializeOwned, Deserialize, Serialize};
+use serde_json::Value;
+use std::ops::Deref;
+use tracing::{debug, log::info};
 use url::Url;
 
 mod comment;
@@ -41,88 +36,44 @@ pub mod site;
 #[tracing::instrument(skip_all)]
 pub async fn shared_inbox(
   request: HttpRequest,
-  payload: Payload,
+  payload: String,
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError> {
-  let unparsed = payload_to_string(payload).await?;
-  info!("Received shared inbox activity {}", unparsed);
-  let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?;
-  let activity = serde_json::from_str::<WithContext<SharedInboxActivities>>(&unparsed)?;
-  match activity.inner() {
-    SharedInboxActivities::GroupInboxActivities(g) => {
-      receive_group_inbox(*g, activity_data, request, &context).await
-    }
-    SharedInboxActivities::PersonInboxActivities(p) => {
-      receive_person_inbox(*p, activity_data, request, &context).await
-    }
-  }
+  receive_lemmy_activity::<SharedInboxActivities, UserOrCommunity>(request, payload, context).await
 }
 
-async fn payload_to_string(mut payload: Payload) -> Result<String, LemmyError> {
-  let mut bytes = BytesMut::new();
-  while let Some(item) = payload.next().await {
-    bytes.extend_from_slice(&item?);
-  }
-  let mut unparsed = String::new();
-  Bytes::from(bytes).as_ref().read_to_string(&mut unparsed)?;
-  Ok(unparsed)
-}
-
-#[derive(Clone, Debug, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub(crate) struct ActivityCommonFields {
-  pub(crate) id: Url,
-  pub(crate) actor: Url,
-}
-
-// TODO: move most of this code to library
-#[tracing::instrument(skip_all)]
-async fn receive_activity<'a, T>(
+pub async fn receive_lemmy_activity<Activity, Actor>(
   request: HttpRequest,
-  activity: T,
-  activity_data: ActivityCommonFields,
-  context: &LemmyContext,
+  payload: String,
+  context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError>
 where
-  T: ActivityHandler<DataType = LemmyContext>
-    + Clone
-    + Deserialize<'a>
-    + Serialize
-    + std::fmt::Debug
+  Activity: ActivityHandler<DataType = LemmyContext, Error = LemmyError>
+    + DeserializeOwned
     + Send
     + 'static,
+  Actor: ApubObject<DataType = LemmyContext, Error = LemmyError> + ActorPublicKey + Send + 'static,
+  for<'de2> <Actor as ApubObject>::ApubType: serde::Deserialize<'de2>,
 {
-  check_is_apub_id_valid(&activity_data.actor, false, &context.settings())?;
-  let request_counter = &mut 0;
-  let actor = ObjectId::<UserOrCommunity>::new(activity_data.actor)
-    .dereference(context, context.client(), request_counter)
-    .await?;
-  verify_signature(&request, &actor.public_key())?;
-
-  info!("Verifying activity {}", activity_data.id.to_string());
-  activity
-    .verify(&Data::new(context.clone()), request_counter)
-    .await?;
-  assert_activity_not_local(&activity_data.id, &context.settings().hostname)?;
-
-  // Log the activity, so we avoid receiving and parsing it twice. Note that this could still happen
-  // if we receive the same activity twice in very quick succession.
-  let object_value = serde_json::to_value(&activity)?;
-  let insert =
-    insert_activity(&activity_data.id, object_value, false, true, context.pool()).await?;
+  let activity_value: Value = serde_json::from_str(&payload)?;
+  let activity: Activity = serde_json::from_value(activity_value.clone())?;
+  // Log the activity, so we avoid receiving and parsing it twice.
+  let insert = insert_activity(activity.id(), activity_value, false, true, context.pool()).await?;
   if !insert {
-    debug!(
-      "Received duplicate activity {}",
-      activity_data.id.to_string()
-    );
+    debug!("Received duplicate activity {}", activity.id().to_string());
     return Ok(HttpResponse::BadRequest().finish());
   }
-
-  info!("Receiving activity {}", activity_data.id.to_string());
-  activity
-    .receive(&Data::new(context.clone()), request_counter)
-    .await?;
-  Ok(HttpResponse::Ok().finish())
+  info!("Received activity {}", payload);
+
+  static DATA: OnceCell<Data<LemmyContext>> = OnceCell::new();
+  let data = DATA.get_or_init(|| Data::new(context.get_ref().clone()));
+  receive_activity::<Activity, Actor, LemmyContext, LemmyError>(
+    request,
+    activity,
+    local_instance(&context),
+    data,
+  )
+  .await
 }
 
 /// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub
@@ -133,7 +84,7 @@ where
 {
   HttpResponse::Ok()
     .content_type(APUB_JSON_CONTENT_TYPE)
-    .json(WithContext::new(data))
+    .json(WithContext::new(data, CONTEXT.deref().clone()))
 }
 
 fn create_json_apub_response(data: serde_json::Value) -> HttpResponse {
@@ -142,14 +93,12 @@ fn create_json_apub_response(data: serde_json::Value) -> HttpResponse {
     .json(data)
 }
 
-fn create_apub_tombstone_response<T>(data: &T) -> HttpResponse
-where
-  T: Serialize,
-{
+fn create_apub_tombstone_response<T: Into<Url>>(id: T) -> HttpResponse {
+  let tombstone = Tombstone::new(id.into());
   HttpResponse::Gone()
     .content_type(APUB_JSON_CONTENT_TYPE)
     .status(StatusCode::GONE)
-    .json(WithContext::new(data))
+    .json(WithContext::new(tombstone, CONTEXT.deref().clone()))
 }
 
 #[derive(Deserialize)]
@@ -184,19 +133,3 @@ pub(crate) async fn get_activity(
     Ok(create_json_apub_response(activity.data))
   }
 }
-
-fn assert_activity_not_local(id: &Url, hostname: &str) -> Result<(), LemmyError> {
-  let activity_domain = id.domain().context(location_info!())?;
-
-  if activity_domain == hostname {
-    let err = anyhow!(
-      "Error: received activity which was sent by local instance: {:?}",
-      id
-    );
-    return Err(LemmyError::from_error_message(
-      err,
-      "received_local_activity",
-    ));
-  }
-  Ok(())
-}
index f0540268ae60446dce82794a133e184ce4a5fcde..f887b26520e38163296a4ee7c3aaf55a27019296 100644 (file)
@@ -1,25 +1,18 @@
 use crate::{
   activity_lists::PersonInboxActivities,
-  context::WithContext,
+  fetcher::user_or_community::UserOrCommunity,
   generate_outbox_url,
-  http::{
-    create_apub_response,
-    create_apub_tombstone_response,
-    payload_to_string,
-    receive_activity,
-    ActivityCommonFields,
-  },
+  http::{create_apub_response, create_apub_tombstone_response, receive_lemmy_activity},
   objects::person::ApubPerson,
   protocol::collections::empty_outbox::EmptyOutbox,
 };
-use actix_web::{web, web::Payload, HttpRequest, HttpResponse};
+use activitypub_federation::{deser::context::WithContext, traits::ApubObject};
+use actix_web::{web, HttpRequest, HttpResponse};
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::traits::ApubObject;
 use lemmy_db_schema::{source::person::Person, traits::ApubActor};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
-use tracing::info;
 
 #[derive(Deserialize)]
 pub struct PersonQuery {
@@ -45,31 +38,20 @@ pub(crate) async fn get_apub_person_http(
 
     Ok(create_apub_response(&apub))
   } else {
-    Ok(create_apub_tombstone_response(&person.to_tombstone()?))
+    Ok(create_apub_tombstone_response(person.actor_id.clone()))
   }
 }
 
 #[tracing::instrument(skip_all)]
 pub async fn person_inbox(
   request: HttpRequest,
-  payload: Payload,
-  _path: web::Path<String>,
+  payload: String,
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError> {
-  let unparsed = payload_to_string(payload).await?;
-  info!("Received person inbox activity {}", unparsed);
-  let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?;
-  let activity = serde_json::from_str::<WithContext<PersonInboxActivities>>(&unparsed)?;
-  receive_person_inbox(activity.inner(), activity_data, request, &context).await
-}
-
-pub(in crate::http) async fn receive_person_inbox(
-  activity: PersonInboxActivities,
-  activity_data: ActivityCommonFields,
-  request: HttpRequest,
-  context: &LemmyContext,
-) -> Result<HttpResponse, LemmyError> {
-  receive_activity(request, activity, activity_data, context).await
+  receive_lemmy_activity::<WithContext<PersonInboxActivities>, UserOrCommunity>(
+    request, payload, context,
+  )
+  .await
 }
 
 #[tracing::instrument(skip_all)]
index 845803b906b2657855950c767c50783bc3bb7013..0e321d176a14f0ece12734cf354adab1b29d7ae8 100644 (file)
@@ -2,12 +2,12 @@ use crate::{
   http::{create_apub_response, create_apub_tombstone_response},
   objects::post::ApubPost,
 };
+use activitypub_federation::traits::ApubObject;
 use actix_web::{web, HttpResponse};
 use diesel::result::Error::NotFound;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::traits::ApubObject;
 use lemmy_db_schema::{newtypes::PostId, source::post::Post, traits::Crud};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
 
@@ -33,6 +33,6 @@ pub(crate) async fn get_apub_post(
   if !post.deleted {
     Ok(create_apub_response(&post.into_apub(&context).await?))
   } else {
-    Ok(create_apub_tombstone_response(&post.to_tombstone()?))
+    Ok(create_apub_tombstone_response(post.ap_id.clone()))
   }
 }
index e4811066379e53cd424231c97b3861e793b81fe8..3d8327387830bd7cb0a9679d8c0a281cd6a149f5 100644 (file)
@@ -1,17 +1,15 @@
 use crate::{
   activity_lists::SiteInboxActivities,
-  context::WithContext,
-  http::{create_apub_response, payload_to_string, receive_activity, ActivityCommonFields},
-  objects::instance::ApubSite,
+  http::{create_apub_response, receive_lemmy_activity},
+  objects::{instance::ApubSite, person::ApubPerson},
   protocol::collections::empty_outbox::EmptyOutbox,
 };
-use actix_web::{web, web::Payload, HttpRequest, HttpResponse};
+use activitypub_federation::{deser::context::WithContext, traits::ApubObject};
+use actix_web::{web, HttpRequest, HttpResponse};
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::traits::ApubObject;
 use lemmy_db_schema::source::site::Site;
-use lemmy_utils::{settings::structs::Settings, LemmyError};
+use lemmy_utils::{error::LemmyError, settings::structs::Settings};
 use lemmy_websocket::LemmyContext;
-use tracing::info;
 use url::Url;
 
 pub(crate) async fn get_apub_site_http(
@@ -38,12 +36,9 @@ pub(crate) async fn get_apub_site_outbox() -> Result<HttpResponse, LemmyError> {
 #[tracing::instrument(skip_all)]
 pub async fn get_apub_site_inbox(
   request: HttpRequest,
-  payload: Payload,
+  payload: String,
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError> {
-  let unparsed = payload_to_string(payload).await?;
-  info!("Received site inbox activity {}", unparsed);
-  let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?;
-  let activity = serde_json::from_str::<WithContext<SiteInboxActivities>>(&unparsed)?;
-  receive_activity(request, activity.inner(), activity_data, &context).await
+  receive_lemmy_activity::<WithContext<SiteInboxActivities>, ApubPerson>(request, payload, context)
+    .await
 }
index b7f1912d8a072d6c7053e2d7f992574e76c135f7..e758e706db23e753e5731a3be98a5416db357729 100644 (file)
@@ -1,22 +1,50 @@
 use crate::fetcher::post_or_comment::PostOrComment;
-use anyhow::{anyhow, Context};
+use activitypub_federation::{
+  core::{inbox::ActorPublicKey, signatures::PublicKey},
+  InstanceSettingsBuilder,
+  LocalInstance,
+};
+use anyhow::Context;
 use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{newtypes::DbUrl, source::activity::Activity, utils::DbPool};
-use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
-use serde::{Deserialize, Deserializer};
-use std::net::IpAddr;
+use lemmy_utils::{error::LemmyError, location_info, settings::structs::Settings};
+use lemmy_websocket::LemmyContext;
+use once_cell::sync::{Lazy, OnceCell};
+use std::env;
 use url::{ParseError, Url};
 
 pub mod activities;
 pub(crate) mod activity_lists;
 pub(crate) mod collections;
-mod context;
 pub mod fetcher;
 pub mod http;
 pub(crate) mod mentions;
 pub mod objects;
 pub mod protocol;
 
+static CONTEXT: Lazy<Vec<serde_json::Value>> = Lazy::new(|| {
+  serde_json::from_str(include_str!("../assets/lemmy/context.json")).expect("parse context")
+});
+
+// TODO: store this in context? but its only used in this crate, no need to expose it elsewhere
+fn local_instance(context: &LemmyContext) -> &'static LocalInstance {
+  static LOCAL_INSTANCE: OnceCell<LocalInstance> = OnceCell::new();
+  LOCAL_INSTANCE.get_or_init(|| {
+    let settings = InstanceSettingsBuilder::default()
+      .http_fetch_retry_limit(context.settings().http_fetch_retry_limit)
+      .worker_count(context.settings().federation.worker_count)
+      .testing_send_sync(env::var("APUB_TESTING_SEND_SYNC").is_ok())
+      .verify_url_function(|url| check_apub_id_valid(url, &Settings::get()))
+      .build()
+      .expect("configure federation");
+    LocalInstance::new(
+      context.settings().hostname,
+      context.client().clone(),
+      settings,
+    )
+  })
+}
+
 /// Checks if the ID is allowed for sending or receiving.
 ///
 /// In particular, it checks for:
@@ -28,119 +56,71 @@ pub mod protocol;
 /// `use_strict_allowlist` should be true only when parsing a remote community, or when parsing a
 /// post/comment in a local community.
 #[tracing::instrument(skip(settings))]
-pub(crate) fn check_is_apub_id_valid(
-  apub_id: &Url,
-  use_strict_allowlist: bool,
-  settings: &Settings,
-) -> Result<(), LemmyError> {
-  let domain = apub_id.domain().context(location_info!())?.to_string();
-  let local_instance = settings.get_hostname_without_port()?;
-
-  if !settings.federation.enabled {
-    return if domain == local_instance {
-      Ok(())
-    } else {
-      let err = anyhow!(
-        "Trying to connect with {}, but federation is disabled",
-        domain
-      );
-      Err(LemmyError::from_error_message(err, "federation_disabled"))
-    };
+fn check_apub_id_valid(apub_id: &Url, settings: &Settings) -> Result<(), &'static str> {
+  let domain = apub_id.domain().expect("apud id has domain").to_string();
+  let local_instance = settings
+    .get_hostname_without_port()
+    .expect("local hostname is valid");
+  if domain == local_instance {
+    return Ok(());
   }
 
-  let host = apub_id.host_str().context(location_info!())?;
-  let host_as_ip = host.parse::<IpAddr>();
-  if host == "localhost" || host_as_ip.is_ok() {
-    let err = anyhow!("invalid hostname {}: {}", host, apub_id);
-    return Err(LemmyError::from_error_message(err, "invalid_hostname"));
+  if !settings.federation.enabled {
+    return Err("Federation disabled");
   }
 
   if apub_id.scheme() != settings.get_protocol_string() {
-    let err = anyhow!("invalid apub id scheme {}: {}", apub_id.scheme(), apub_id);
-    return Err(LemmyError::from_error_message(err, "invalid_scheme"));
+    return Err("Invalid protocol scheme");
   }
 
-  // TODO: might be good to put the part above in one method, and below in another
-  //       (which only gets called in apub::objects)
-  //        -> no that doesnt make sense, we still need the code below for blocklist and strict allowlist
   if let Some(blocked) = settings.to_owned().federation.blocked_instances {
     if blocked.contains(&domain) {
-      let err = anyhow!("{} is in federation blocklist", domain);
-      return Err(LemmyError::from_error_message(err, "federation_blocked"));
+      return Err("Domain is blocked");
     }
   }
 
+  if let Some(allowed) = settings.to_owned().federation.allowed_instances {
+    if !allowed.contains(&domain) {
+      return Err("Domain is not in allowlist");
+    }
+  }
+
+  Ok(())
+}
+
+#[tracing::instrument(skip(settings))]
+pub(crate) fn check_apub_id_valid_with_strictness(
+  apub_id: &Url,
+  is_strict: bool,
+  settings: &Settings,
+) -> Result<(), LemmyError> {
+  check_apub_id_valid(apub_id, settings).map_err(LemmyError::from_message)?;
+  let domain = apub_id.domain().expect("apud id has domain").to_string();
+  let local_instance = settings
+    .get_hostname_without_port()
+    .expect("local hostname is valid");
+  if domain == local_instance {
+    return Ok(());
+  }
+
   if let Some(mut allowed) = settings.to_owned().federation.allowed_instances {
     // Only check allowlist if this is a community, or strict allowlist is enabled.
     let strict_allowlist = settings.to_owned().federation.strict_allowlist;
-    if use_strict_allowlist || strict_allowlist {
+    if is_strict || strict_allowlist {
       // need to allow this explicitly because apub receive might contain objects from our local
       // instance.
       allowed.push(local_instance);
 
       if !allowed.contains(&domain) {
-        let err = anyhow!("{} not in federation allowlist", domain);
-        return Err(LemmyError::from_error_message(
-          err,
-          "federation_not_allowed",
+        return Err(LemmyError::from_message(
+          "Federation forbidden by strict allowlist",
         ));
       }
     }
   }
-
   Ok(())
 }
 
-pub(crate) fn deserialize_one_or_many<'de, T, D>(deserializer: D) -> Result<Vec<T>, D::Error>
-where
-  T: Deserialize<'de>,
-  D: Deserializer<'de>,
-{
-  #[derive(Deserialize)]
-  #[serde(untagged)]
-  enum OneOrMany<T> {
-    One(T),
-    Many(Vec<T>),
-  }
-
-  let result: OneOrMany<T> = Deserialize::deserialize(deserializer)?;
-  Ok(match result {
-    OneOrMany::Many(list) => list,
-    OneOrMany::One(value) => vec![value],
-  })
-}
-
-pub(crate) fn deserialize_one<'de, T, D>(deserializer: D) -> Result<[T; 1], D::Error>
-where
-  T: Deserialize<'de>,
-  D: Deserializer<'de>,
-{
-  #[derive(Deserialize)]
-  #[serde(untagged)]
-  enum MaybeArray<T> {
-    Simple(T),
-    Array([T; 1]),
-  }
-
-  let result: MaybeArray<T> = Deserialize::deserialize(deserializer)?;
-  Ok(match result {
-    MaybeArray::Simple(value) => [value],
-    MaybeArray::Array(value) => value,
-  })
-}
-
-pub(crate) fn deserialize_skip_error<'de, T, D>(deserializer: D) -> Result<T, D::Error>
-where
-  T: Deserialize<'de> + Default,
-  D: Deserializer<'de>,
-{
-  let result = Deserialize::deserialize(deserializer);
-  Ok(match result {
-    Ok(o) => o,
-    Err(_) => Default::default(),
-  })
-}
-
 pub enum EndpointType {
   Community,
   Person,
@@ -221,3 +201,23 @@ async fn insert_activity(
     .await??,
   )
 }
+
+/// Common methods provided by ActivityPub actors (community and person). Not all methods are
+/// implemented by all actors.
+pub trait ActorType: ActorPublicKey {
+  fn actor_id(&self) -> Url;
+
+  fn private_key(&self) -> Option<String>;
+
+  fn inbox_url(&self) -> Url;
+
+  fn shared_inbox_url(&self) -> Option<Url>;
+
+  fn shared_inbox_or_inbox_url(&self) -> Url {
+    self.shared_inbox_url().unwrap_or_else(|| self.inbox_url())
+  }
+
+  fn get_public_key(&self) -> PublicKey {
+    PublicKey::new_main_key(self.actor_id(), self.public_key().to_string())
+  }
+}
index b68391a983eafa2d30669fbea44378c9baa1060a..053952ca2fe277ce46d7a6064232b8cc57cedb5d 100644 (file)
@@ -1,18 +1,19 @@
 use crate::{
   fetcher::webfinger::webfinger_resolve_actor,
   objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson},
+  ActorType,
 };
+use activitypub_federation::core::object_id::ObjectId;
 use activitystreams_kinds::link::MentionType;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{object_id::ObjectId, traits::ActorType};
 use lemmy_db_schema::{
   source::{comment::Comment, person::Person, post::Post},
   traits::Crud,
   utils::DbPool,
 };
 use lemmy_utils::{
+  error::LemmyError,
   utils::{scrape_text_for_mentions, MentionData},
-  LemmyError,
 };
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
index 96c9f05a924a8758d916ccd7bdf252b748e66e54..30ddfdf6059cd8947933179ac72e3cab7daf008a 100644 (file)
@@ -1,23 +1,21 @@
 use crate::{
   activities::{verify_is_public, verify_person_in_community},
-  check_is_apub_id_valid,
+  check_apub_id_valid_with_strictness,
+  local_instance,
   mentions::collect_non_local_mentions,
   objects::{read_from_string_or_source, verify_is_remote_object},
-  protocol::{
-    objects::{note::Note, tombstone::Tombstone},
-    Source,
-  },
+  protocol::{objects::note::Note, Source},
   PostOrComment,
 };
+use activitypub_federation::{
+  core::object_id::ObjectId,
+  deser::values::MediaTypeMarkdownOrHtml,
+  traits::ApubObject,
+  utils::verify_domains_match,
+};
 use activitystreams_kinds::{object::NoteType, public};
 use chrono::NaiveDateTime;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  object_id::ObjectId,
-  traits::ApubObject,
-  values::MediaTypeMarkdownOrHtml,
-  verify::verify_domains_match,
-};
 use lemmy_db_schema::{
   source::{
     comment::{Comment, CommentForm},
@@ -28,8 +26,8 @@ use lemmy_db_schema::{
   traits::Crud,
 };
 use lemmy_utils::{
+  error::LemmyError,
   utils::{convert_datetime, markdown_to_html, remove_slurs},
-  LemmyError,
 };
 use lemmy_websocket::LemmyContext;
 use std::ops::Deref;
@@ -56,7 +54,7 @@ impl ApubObject for ApubComment {
   type DataType = LemmyContext;
   type ApubType = Note;
   type DbType = Comment;
-  type TombstoneType = Tombstone;
+  type Error = LemmyError;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     None
@@ -128,10 +126,6 @@ impl ApubObject for ApubComment {
     Ok(note)
   }
 
-  fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
-    Ok(Tombstone::new(self.ap_id.clone().into()))
-  }
-
   #[tracing::instrument(skip_all)]
   async fn verify(
     note: &Note,
@@ -148,7 +142,7 @@ impl ApubObject for ApubComment {
       Community::read(conn, community_id)
     })
     .await??;
-    check_is_apub_id_valid(note.id.inner(), community.local, &context.settings())?;
+    check_apub_id_valid_with_strictness(note.id.inner(), community.local, &context.settings())?;
     verify_is_remote_object(note.id.inner())?;
     verify_person_in_community(
       &note.attributed_to,
@@ -174,7 +168,7 @@ impl ApubObject for ApubComment {
   ) -> Result<ApubComment, LemmyError> {
     let creator = note
       .attributed_to
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let (post, parent_comment_id) = note.get_parents(context, request_counter).await?;
 
index a8904ac58bf86daa049f3b87eabe2cd400baaf5f..4c381c1c44387c83922ca91211baa8cbd88e2e09 100644 (file)
@@ -1,28 +1,30 @@
 use crate::{
-  check_is_apub_id_valid,
+  check_apub_id_valid_with_strictness,
   collections::{community_moderators::ApubCommunityModerators, CommunityContext},
   generate_moderators_url,
   generate_outbox_url,
+  local_instance,
   objects::instance::fetch_instance_actor_for_object,
   protocol::{
-    objects::{group::Group, tombstone::Tombstone, Endpoints},
+    objects::{group::Group, Endpoints},
     ImageObject,
     Source,
   },
+  ActorType,
+};
+use activitypub_federation::{
+  core::{inbox::ActorPublicKey, object_id::ObjectId},
+  traits::ApubObject,
 };
 use activitystreams_kinds::actor::GroupType;
 use chrono::NaiveDateTime;
 use itertools::Itertools;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  object_id::ObjectId,
-  traits::{ActorType, ApubObject},
-};
 use lemmy_db_schema::{source::community::Community, traits::ApubActor};
 use lemmy_db_views_actor::structs::CommunityFollowerView;
 use lemmy_utils::{
+  error::LemmyError,
   utils::{convert_datetime, markdown_to_html},
-  LemmyError,
 };
 use lemmy_websocket::LemmyContext;
 use std::ops::Deref;
@@ -50,7 +52,7 @@ impl ApubObject for ApubCommunity {
   type DataType = LemmyContext;
   type ApubType = Group;
   type DbType = Community;
-  type TombstoneType = Tombstone;
+  type Error = LemmyError;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     Some(self.last_refreshed_at)
@@ -100,7 +102,7 @@ impl ApubObject for ApubCommunity {
       endpoints: self.shared_inbox_url.clone().map(|s| Endpoints {
         shared_inbox: s.into(),
       }),
-      public_key: self.get_public_key()?,
+      public_key: self.get_public_key(),
       published: Some(convert_datetime(self.published)),
       updated: self.updated.map(convert_datetime),
       posting_restricted_to_mods: Some(self.posting_restricted_to_mods),
@@ -108,10 +110,6 @@ impl ApubObject for ApubCommunity {
     Ok(group)
   }
 
-  fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
-    Ok(Tombstone::new(self.actor_id()))
-  }
-
   #[tracing::instrument(skip_all)]
   async fn verify(
     group: &Group,
@@ -141,14 +139,14 @@ impl ApubObject for ApubCommunity {
 
     group
       .outbox
-      .dereference(&outbox_data, context.client(), request_counter)
+      .dereference::<LemmyError>(&outbox_data, local_instance(context), request_counter)
       .await
       .map_err(|e| debug!("{}", e))
       .ok();
 
     if let Some(moderators) = &group.moderators {
       moderators
-        .dereference(&outbox_data, context.client(), request_counter)
+        .dereference::<LemmyError>(&outbox_data, local_instance(context), request_counter)
         .await
         .map_err(|e| debug!("{}", e))
         .ok();
@@ -164,9 +162,6 @@ impl ActorType for ApubCommunity {
   fn actor_id(&self) -> Url {
     self.actor_id.to_owned().into()
   }
-  fn public_key(&self) -> String {
-    self.public_key.to_owned()
-  }
   fn private_key(&self) -> Option<String> {
     self.private_key.to_owned()
   }
@@ -180,6 +175,12 @@ impl ActorType for ApubCommunity {
   }
 }
 
+impl ActorPublicKey for ApubCommunity {
+  fn public_key(&self) -> &str {
+    &self.public_key
+  }
+}
+
 impl ApubCommunity {
   /// For a given community, returns the inboxes of all followers.
   #[tracing::instrument(skip_all)]
@@ -205,7 +206,9 @@ impl ApubCommunity {
       .unique()
       .filter(|inbox: &Url| inbox.host_str() != Some(&context.settings().hostname))
       // Don't send to blocked instances
-      .filter(|inbox| check_is_apub_id_valid(inbox, false, &context.settings()).is_ok())
+      .filter(|inbox| {
+        check_apub_id_valid_with_strictness(inbox, false, &context.settings()).is_ok()
+      })
       .collect();
 
     Ok(inboxes)
index 09b34fc533b384eeea27a23ff7ca2c3fc51cdc67..cd4ceb467634c435ab2f426b4f825d6dc9f68078 100644 (file)
@@ -1,27 +1,29 @@
 use crate::{
-  check_is_apub_id_valid,
+  check_apub_id_valid_with_strictness,
+  local_instance,
   objects::read_from_string_or_source_opt,
   protocol::{
     objects::instance::{Instance, InstanceType},
     ImageObject,
     Source,
   },
+  ActorType,
+};
+use activitypub_federation::{
+  core::{inbox::ActorPublicKey, object_id::ObjectId},
+  deser::values::MediaTypeHtml,
+  traits::ApubObject,
+  utils::verify_domains_match,
 };
 use chrono::NaiveDateTime;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  object_id::ObjectId,
-  traits::{ActorType, ApubObject},
-  values::MediaTypeHtml,
-  verify::verify_domains_match,
-};
 use lemmy_db_schema::{
   source::site::{Site, SiteForm},
   utils::naive_now,
 };
 use lemmy_utils::{
+  error::LemmyError,
   utils::{check_slurs, check_slurs_opt, convert_datetime, markdown_to_html},
-  LemmyError,
 };
 use lemmy_websocket::LemmyContext;
 use std::ops::Deref;
@@ -49,7 +51,7 @@ impl ApubObject for ApubSite {
   type DataType = LemmyContext;
   type ApubType = Instance;
   type DbType = Site;
-  type TombstoneType = ();
+  type Error = LemmyError;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     Some(self.last_refreshed_at)
@@ -87,17 +89,13 @@ impl ApubObject for ApubSite {
       image: self.banner.clone().map(ImageObject::new),
       inbox: self.inbox_url.clone().into(),
       outbox: Url::parse(&format!("{}/site_outbox", self.actor_id))?,
-      public_key: self.get_public_key()?,
+      public_key: self.get_public_key(),
       published: convert_datetime(self.published),
       updated: self.updated.map(convert_datetime),
     };
     Ok(instance)
   }
 
-  fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError> {
-    unimplemented!()
-  }
-
   #[tracing::instrument(skip_all)]
   async fn verify(
     apub: &Self::ApubType,
@@ -105,7 +103,7 @@ impl ApubObject for ApubSite {
     data: &Self::DataType,
     _request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    check_is_apub_id_valid(apub.id.inner(), true, &data.settings())?;
+    check_apub_id_valid_with_strictness(apub.id.inner(), true, &data.settings())?;
     verify_domains_match(expected_domain, apub.id.inner())?;
 
     let slur_regex = &data.settings().slur_regex();
@@ -146,9 +144,6 @@ impl ActorType for ApubSite {
   fn actor_id(&self) -> Url {
     self.actor_id.to_owned().into()
   }
-  fn public_key(&self) -> String {
-    self.public_key.to_owned()
-  }
   fn private_key(&self) -> Option<String> {
     self.private_key.to_owned()
   }
@@ -162,6 +157,12 @@ impl ActorType for ApubSite {
   }
 }
 
+impl ActorPublicKey for ApubSite {
+  fn public_key(&self) -> &str {
+    &self.public_key
+  }
+}
+
 /// Instance actor is at the root path, so we simply need to clear the path and other unnecessary
 /// parts of the url.
 pub fn instance_actor_id_from_url(mut url: Url) -> Url {
@@ -180,7 +181,7 @@ pub(in crate::objects) async fn fetch_instance_actor_for_object(
   // try to fetch the instance actor (to make things like instance rules available)
   let instance_id = instance_actor_id_from_url(object_id);
   let site = ObjectId::<ApubSite>::new(instance_id.clone())
-    .dereference(context, context.client(), request_counter)
+    .dereference::<LemmyError>(context, local_instance(context), request_counter)
     .await;
   if let Err(e) = site {
     debug!("Failed to dereference site for {}: {}", instance_id, e);
index b3aa80b54868d2c7a25c737692c261379e8750cd..e07eb4def59da13f96158cf1b8e3c66b4194a0bd 100644 (file)
@@ -1,8 +1,8 @@
 use crate::protocol::Source;
+use activitypub_federation::deser::values::MediaTypeMarkdownOrHtml;
 use anyhow::anyhow;
 use html2md::parse_html;
-use lemmy_apub_lib::values::MediaTypeMarkdownOrHtml;
-use lemmy_utils::{settings::structs::Settings, LemmyError};
+use lemmy_utils::{error::LemmyError, settings::structs::Settings};
 use url::Url;
 
 pub mod comment;
@@ -60,15 +60,14 @@ pub(crate) mod tests {
     PgConnection,
   };
   use lemmy_api_common::request::build_user_agent;
-  use lemmy_apub_lib::activity_queue::create_activity_queue;
   use lemmy_db_schema::{
     source::secret::Secret,
     utils::{establish_unpooled_connection, get_database_url_from_env},
   };
   use lemmy_utils::{
+    error::LemmyError,
     rate_limit::{rate_limiter::RateLimiter, RateLimit},
     settings::structs::Settings,
-    LemmyError,
   };
   use lemmy_websocket::{chat_server::ChatServer, LemmyContext};
   use parking_lot::Mutex;
@@ -77,12 +76,7 @@ pub(crate) mod tests {
   use std::sync::Arc;
 
   // TODO: would be nice if we didnt have to use a full context for tests.
-  //       or at least write a helper function so this code is shared with main.rs
   pub(crate) fn init_context() -> LemmyContext {
-    let client = reqwest::Client::new().into();
-    // activity queue isnt used in tests, so worker count makes no difference
-    let queue_manager = create_activity_queue(client, 4);
-    let activity_queue = queue_manager.queue_handle().clone();
     // call this to run migrations
     establish_unpooled_connection();
     let settings = Settings::init().unwrap();
@@ -118,11 +112,10 @@ pub(crate) mod tests {
       |_, _, _, _| Box::pin(x()),
       |_, _, _, _| Box::pin(x()),
       client.clone(),
-      activity_queue.clone(),
       settings.clone(),
       secret.clone(),
     )
     .start();
-    LemmyContext::create(pool, chat_server, client, activity_queue, settings, secret)
+    LemmyContext::create(pool, chat_server, client, settings, secret)
   }
 }
index bf2cb3cb608a9ef7c31237d7256682e6a90ce9ec..7b87f90113c6a63ebe35af1065024e3efdbd09c8 100644 (file)
@@ -1,5 +1,5 @@
 use crate::{
-  check_is_apub_id_valid,
+  check_apub_id_valid_with_strictness,
   generate_outbox_url,
   objects::{instance::fetch_instance_actor_for_object, read_from_string_or_source_opt},
   protocol::{
@@ -10,22 +10,23 @@ use crate::{
     ImageObject,
     Source,
   },
+  ActorType,
+};
+use activitypub_federation::{
+  core::{inbox::ActorPublicKey, object_id::ObjectId},
+  traits::ApubObject,
+  utils::verify_domains_match,
 };
 use chrono::NaiveDateTime;
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  object_id::ObjectId,
-  traits::{ActorType, ApubObject},
-  verify::verify_domains_match,
-};
 use lemmy_db_schema::{
   source::person::{Person as DbPerson, PersonForm},
   traits::ApubActor,
   utils::naive_now,
 };
 use lemmy_utils::{
+  error::LemmyError,
   utils::{check_slurs, check_slurs_opt, convert_datetime, markdown_to_html},
-  LemmyError,
 };
 use lemmy_websocket::LemmyContext;
 use std::ops::Deref;
@@ -52,7 +53,7 @@ impl ApubObject for ApubPerson {
   type DataType = LemmyContext;
   type ApubType = Person;
   type DbType = DbPerson;
-  type TombstoneType = ();
+  type Error = LemmyError;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     Some(self.last_refreshed_at)
@@ -104,17 +105,13 @@ impl ApubObject for ApubPerson {
       endpoints: self.shared_inbox_url.clone().map(|s| Endpoints {
         shared_inbox: s.into(),
       }),
-      public_key: self.get_public_key()?,
+      public_key: self.get_public_key(),
       updated: self.updated.map(convert_datetime),
       inbox: self.inbox_url.clone().into(),
     };
     Ok(person)
   }
 
-  fn to_tombstone(&self) -> Result<(), LemmyError> {
-    unimplemented!()
-  }
-
   #[tracing::instrument(skip_all)]
   async fn verify(
     person: &Person,
@@ -123,7 +120,7 @@ impl ApubObject for ApubPerson {
     _request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     verify_domains_match(person.id.inner(), expected_domain)?;
-    check_is_apub_id_valid(person.id.inner(), false, &context.settings())?;
+    check_apub_id_valid_with_strictness(person.id.inner(), false, &context.settings())?;
 
     let slur_regex = &context.settings().slur_regex();
     check_slurs(&person.preferred_username, slur_regex)?;
@@ -182,10 +179,6 @@ impl ActorType for ApubPerson {
     self.actor_id.to_owned().into()
   }
 
-  fn public_key(&self) -> String {
-    self.public_key.to_owned()
-  }
-
   fn private_key(&self) -> Option<String> {
     self.private_key.to_owned()
   }
@@ -199,6 +192,12 @@ impl ActorType for ApubPerson {
   }
 }
 
+impl ActorPublicKey for ApubPerson {
+  fn public_key(&self) -> &str {
+    &self.public_key
+  }
+}
+
 #[cfg(test)]
 pub(crate) mod tests {
   use super::*;
index 49797036440441fe6e4fc4177376392eaea16753..bdefe2802cee957f587a92679d8324697fd889bc 100644 (file)
@@ -1,27 +1,24 @@
 use crate::{
   activities::{verify_is_public, verify_person_in_community},
-  check_is_apub_id_valid,
+  check_apub_id_valid_with_strictness,
+  local_instance,
   objects::{read_from_string_or_source_opt, verify_is_remote_object},
   protocol::{
-    objects::{
-      page::{Attachment, AttributedTo, Page, PageType},
-      tombstone::Tombstone,
-    },
+    objects::page::{Attachment, AttributedTo, Page, PageType},
     ImageObject,
     Source,
   },
 };
+use activitypub_federation::{
+  core::object_id::ObjectId,
+  deser::values::MediaTypeMarkdownOrHtml,
+  traits::ApubObject,
+  utils::verify_domains_match,
+};
 use activitystreams_kinds::public;
 use chrono::NaiveDateTime;
 use lemmy_api_common::{request::fetch_site_data, utils::blocking};
-use lemmy_apub_lib::{
-  object_id::ObjectId,
-  traits::ApubObject,
-  values::MediaTypeMarkdownOrHtml,
-  verify::verify_domains_match,
-};
 use lemmy_db_schema::{
-  self,
   source::{
     community::Community,
     moderator::{ModLockPost, ModLockPostForm, ModStickyPost, ModStickyPostForm},
@@ -29,10 +26,11 @@ use lemmy_db_schema::{
     post::{Post, PostForm},
   },
   traits::Crud,
+  {self},
 };
 use lemmy_utils::{
+  error::LemmyError,
   utils::{check_slurs, convert_datetime, markdown_to_html, remove_slurs},
-  LemmyError,
 };
 use lemmy_websocket::LemmyContext;
 use std::ops::Deref;
@@ -59,7 +57,7 @@ impl ApubObject for ApubPost {
   type DataType = LemmyContext;
   type ApubType = Page;
   type DbType = Post;
-  type TombstoneType = Tombstone;
+  type Error = LemmyError;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     None
@@ -123,10 +121,6 @@ impl ApubObject for ApubPost {
     Ok(page)
   }
 
-  fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
-    Ok(Tombstone::new(self.ap_id.clone().into()))
-  }
-
   #[tracing::instrument(skip_all)]
   async fn verify(
     page: &Page,
@@ -142,7 +136,7 @@ impl ApubObject for ApubPost {
     };
 
     let community = page.extract_community(context, request_counter).await?;
-    check_is_apub_id_valid(page.id.inner(), community.local, &context.settings())?;
+    check_apub_id_valid_with_strictness(page.id.inner(), community.local, &context.settings())?;
     verify_person_in_community(&page.creator()?, &community, context, request_counter).await?;
     check_slurs(&page.name, &context.settings().slur_regex())?;
     verify_domains_match(page.creator()?.inner(), page.id.inner())?;
@@ -158,7 +152,7 @@ impl ApubObject for ApubPost {
   ) -> Result<ApubPost, LemmyError> {
     let creator = page
       .creator()?
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     let community = page.extract_community(context, request_counter).await?;
 
@@ -222,7 +216,7 @@ impl ApubObject for ApubPost {
 
     // read existing, local post if any (for generating mod log)
     let old_post = ObjectId::<ApubPost>::new(page.id.clone())
-      .dereference_local(context)
+      .dereference_local::<LemmyError>(context)
       .await;
 
     let post = blocking(context.pool(), move |conn| Post::upsert(conn, &form)).await??;
index a984180dbd576972a657bbaa7341a2dc7c9f0619..56363f7793181fb430c5459ac142a0bfaab34dc3 100644 (file)
@@ -1,18 +1,20 @@
 use crate::{
+  check_apub_id_valid_with_strictness,
+  local_instance,
   objects::read_from_string_or_source,
   protocol::{
     objects::chat_message::{ChatMessage, ChatMessageType},
     Source,
   },
 };
-use chrono::NaiveDateTime;
-use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{
-  object_id::ObjectId,
+use activitypub_federation::{
+  core::object_id::ObjectId,
+  deser::values::MediaTypeHtml,
   traits::ApubObject,
-  values::MediaTypeHtml,
-  verify::verify_domains_match,
+  utils::verify_domains_match,
 };
+use chrono::NaiveDateTime;
+use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{
     person::Person,
@@ -21,8 +23,9 @@ use lemmy_db_schema::{
   traits::Crud,
 };
 use lemmy_utils::{
+  error::LemmyError,
+  settings::structs::Settings,
   utils::{convert_datetime, markdown_to_html},
-  LemmyError,
 };
 use lemmy_websocket::LemmyContext;
 use std::ops::Deref;
@@ -49,7 +52,7 @@ impl ApubObject for ApubPrivateMessage {
   type DataType = LemmyContext;
   type ApubType = ChatMessage;
   type DbType = PrivateMessage;
-  type TombstoneType = ();
+  type Error = LemmyError;
 
   fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
     None
@@ -87,7 +90,7 @@ impl ApubObject for ApubPrivateMessage {
       r#type: ChatMessageType::ChatMessage,
       id: ObjectId::new(self.ap_id.clone()),
       attributed_to: ObjectId::new(creator.actor_id),
-      to: [ObjectId::new(recipient.actor_id)],
+      to: ObjectId::new(recipient.actor_id),
       content: markdown_to_html(&self.content),
       media_type: Some(MediaTypeHtml::Html),
       source: Some(Source::new(self.content.clone())),
@@ -97,10 +100,6 @@ impl ApubObject for ApubPrivateMessage {
     Ok(note)
   }
 
-  fn to_tombstone(&self) -> Result<(), LemmyError> {
-    unimplemented!()
-  }
-
   #[tracing::instrument(skip_all)]
   async fn verify(
     note: &ChatMessage,
@@ -110,9 +109,10 @@ impl ApubObject for ApubPrivateMessage {
   ) -> Result<(), LemmyError> {
     verify_domains_match(note.id.inner(), expected_domain)?;
     verify_domains_match(note.attributed_to.inner(), note.id.inner())?;
+    check_apub_id_valid_with_strictness(note.id.inner(), false, &Settings::get())?;
     let person = note
       .attributed_to
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
     if person.banned {
       return Err(LemmyError::from_message("Person is banned from site"));
@@ -128,10 +128,11 @@ impl ApubObject for ApubPrivateMessage {
   ) -> Result<ApubPrivateMessage, LemmyError> {
     let creator = note
       .attributed_to
-      .dereference(context, context.client(), request_counter)
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
-    let recipient = note.to[0]
-      .dereference(context, context.client(), request_counter)
+    let recipient = note
+      .to
+      .dereference::<LemmyError>(context, local_instance(context), request_counter)
       .await?;
 
     let form = PrivateMessageForm {
index ab4e3eca91653f32399d378d393154a7db340c2f..1929a6a53483278fb13104fdc0429e2fb66e6322 100644 (file)
@@ -1,7 +1,7 @@
 use crate::{activities::block::SiteOrCommunity, objects::person::ApubPerson, protocol::Unparsed};
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
 use activitystreams_kinds::activity::BlockType;
 use chrono::{DateTime, FixedOffset};
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
@@ -9,10 +9,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct BlockUser {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   pub(crate) target: ObjectId<SiteOrCommunity>,
   #[serde(rename = "type")]
index 8e756be5559ecde7bf0d296dca9f5eebccbe519b..b2dcfaffa5efdf06102f2ff022e39b2f9548ebf9 100644 (file)
@@ -2,8 +2,8 @@ use crate::{
   objects::person::ApubPerson,
   protocol::{activities::block::block_user::BlockUser, Unparsed},
 };
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
 use activitystreams_kinds::activity::UndoType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
@@ -11,10 +11,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct UndoBlockUser {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: BlockUser,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: UndoType,
index 5697c19f4002c3e1789543faf5aabbaa4c402f58..e720b8e6de48f00ec0a4b48306baabea6f768a98 100644 (file)
@@ -1,6 +1,6 @@
 use crate::{objects::person::ApubPerson, protocol::Unparsed};
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
 use activitystreams_kinds::activity::AddType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
@@ -8,11 +8,11 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct AddMod {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: ObjectId<ApubPerson>,
   pub(crate) target: Url,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: AddType,
index 75a7d9af4a4964f06084059265fe4ed6dfa02664..9db17a0fef48cfc2f5085740da87c160c338733b 100644 (file)
@@ -3,8 +3,8 @@ use crate::{
   objects::community::ApubCommunity,
   protocol::{IdOrNestedObject, Unparsed},
 };
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
 use activitystreams_kinds::activity::AnnounceType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
@@ -12,10 +12,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct AnnounceActivity {
   pub(crate) actor: ObjectId<ApubCommunity>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: IdOrNestedObject<AnnouncableActivities>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: AnnounceType,
index 304772bb22f1218897b19380f0cd957691f33eff..bd972202f7f7e068a4718e7666b5a246a007b64c 100644 (file)
@@ -1,6 +1,6 @@
 use crate::{objects::person::ApubPerson, protocol::Unparsed};
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
 use activitystreams_kinds::activity::RemoveType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
@@ -8,10 +8,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct RemoveMod {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: RemoveType,
index 40bbe83bd74aeb0e077d5afdcc02d31c8595067c..cd66c657eee5837ae8fd12e29be8ed1465622065 100644 (file)
@@ -3,8 +3,8 @@ use crate::{
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::Unparsed,
 };
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one};
 use activitystreams_kinds::activity::FlagType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
@@ -12,8 +12,8 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct Report {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one")]
-  pub(crate) to: [ObjectId<ApubCommunity>; 1],
+  #[serde(deserialize_with = "deserialize_one")]
+  pub(crate) to: ObjectId<ApubCommunity>,
   pub(crate) object: ObjectId<PostOrComment>,
   pub(crate) summary: String,
   #[serde(rename = "type")]
index 4c4ef2f0308753d88830520a2edfe10352b4eac7..d0b27a5512e1785e5446d0551b9e04a85168f335 100644 (file)
@@ -2,8 +2,8 @@ use crate::{
   objects::person::ApubPerson,
   protocol::{objects::group::Group, Unparsed},
 };
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
 use activitystreams_kinds::activity::UpdateType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
@@ -13,11 +13,11 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct UpdateCommunity {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   // TODO: would be nice to use a separate struct here, which only contains the fields updated here
   pub(crate) object: Box<Group>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: UpdateType,
index cf0697b179185161ce71ed4cdf408381d65f4ea6..5ebc0f5548eec4b515122662521e0eb8207bce63 100644 (file)
@@ -3,7 +3,7 @@ use crate::{
   objects::person::ApubPerson,
   protocol::{activities::CreateOrUpdateType, objects::note::Note, Unparsed},
 };
-use lemmy_apub_lib::object_id::ObjectId;
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
 use serde::{Deserialize, Serialize};
 use url::Url;
 
@@ -11,10 +11,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct CreateOrUpdateComment {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: Note,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(default)]
   pub(crate) tag: Vec<MentionOrValue>,
index eb96572f17d34dcf61e34663b0129f0f4c8b99bb..d40073cf336baa4b8897542232c72de9c5b499e8 100644 (file)
@@ -2,7 +2,7 @@ use crate::{
   objects::person::ApubPerson,
   protocol::{activities::CreateOrUpdateType, objects::page::Page, Unparsed},
 };
-use lemmy_apub_lib::object_id::ObjectId;
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
 use serde::{Deserialize, Serialize};
 use url::Url;
 
@@ -10,10 +10,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct CreateOrUpdatePost {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: Page,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: CreateOrUpdateType,
index a4e62b6566e2dc39e6e02e6cd7f7f64353e93406..e0288498b1e8d5a19fd5f965a43da360f9aecd45 100644 (file)
@@ -2,7 +2,7 @@ use crate::{
   objects::person::ApubPerson,
   protocol::{activities::CreateOrUpdateType, objects::chat_message::ChatMessage, Unparsed},
 };
-use lemmy_apub_lib::object_id::ObjectId;
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one};
 use serde::{Deserialize, Serialize};
 use url::Url;
 
@@ -11,8 +11,8 @@ use url::Url;
 pub struct CreateOrUpdatePrivateMessage {
   pub(crate) id: Url,
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one")]
-  pub(crate) to: [ObjectId<ApubPerson>; 1],
+  #[serde(deserialize_with = "deserialize_one")]
+  pub(crate) to: ObjectId<ApubPerson>,
   pub(crate) object: ChatMessage,
   #[serde(rename = "type")]
   pub(crate) kind: CreateOrUpdateType,
index 3fb5984d6f372dd5ad86ab8c49ad01fd9d76fe58..76256cacbba29cce9d275d38b5c9076519ef8866 100644 (file)
@@ -2,8 +2,8 @@ use crate::{
   objects::person::ApubPerson,
   protocol::{objects::tombstone::Tombstone, IdOrNestedObject, Unparsed},
 };
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
 use activitystreams_kinds::activity::DeleteType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use serde_with::skip_serializing_none;
 use url::Url;
@@ -13,14 +13,14 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct Delete {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: IdOrNestedObject<Tombstone>,
   #[serde(rename = "type")]
   pub(crate) kind: DeleteType,
   pub(crate) id: Url,
 
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   #[serde(default)]
   #[serde(skip_serializing_if = "Vec::is_empty")]
   pub(crate) cc: Vec<Url>,
index a45bfbdb61438e775e58878f8bdaa7749466136c..d455be99cc3770db6ceae4e379f12c6b334320a9 100644 (file)
@@ -1,6 +1,6 @@
 use crate::objects::person::ApubPerson;
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
 use activitystreams_kinds::activity::DeleteType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use serde_with::skip_serializing_none;
 use url::Url;
@@ -10,14 +10,14 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct DeleteUser {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: ObjectId<ApubPerson>,
   #[serde(rename = "type")]
   pub(crate) kind: DeleteType,
   pub(crate) id: Url,
 
-  #[serde(deserialize_with = "crate::deserialize_one_or_many", default)]
+  #[serde(deserialize_with = "deserialize_one_or_many", default)]
   #[serde(skip_serializing_if = "Vec::is_empty")]
   pub(crate) cc: Vec<Url>,
 }
index e676ab00bf3773678a1a5d5dd48a7191ba60f069..1ae6aa84b80434dc388024907af02244336ddfde 100644 (file)
@@ -2,8 +2,8 @@ use crate::{
   objects::person::ApubPerson,
   protocol::{activities::deletion::delete::Delete, Unparsed},
 };
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
 use activitystreams_kinds::activity::UndoType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
@@ -11,14 +11,14 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct UndoDelete {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: Delete,
   #[serde(rename = "type")]
   pub(crate) kind: UndoType,
   pub(crate) id: Url,
 
-  #[serde(deserialize_with = "crate::deserialize_one_or_many", default)]
+  #[serde(deserialize_with = "deserialize_one_or_many", default)]
   #[serde(skip_serializing_if = "Vec::is_empty")]
   pub(crate) cc: Vec<Url>,
   #[serde(flatten)]
index dcb0b181ab5cd9cd015824ede668c8f4db33568d..a600fbfba1bc65b5bc32e34b018b9b20f89d54be 100644 (file)
@@ -2,8 +2,8 @@ use crate::{
   objects::community::ApubCommunity,
   protocol::{activities::following::follow::FollowCommunity, Unparsed},
 };
+use activitypub_federation::core::object_id::ObjectId;
 use activitystreams_kinds::activity::AcceptType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
index 2072af486f08aeebe4d17d0f47b81c93eeea8a0e..2cef197d317eb70f583140617b50194596a60a26 100644 (file)
@@ -2,8 +2,8 @@ use crate::{
   objects::{community::ApubCommunity, person::ApubPerson},
   protocol::Unparsed,
 };
+use activitypub_federation::core::object_id::ObjectId;
 use activitystreams_kinds::activity::FollowType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
index 1936146909e4fbd8c900c372a38296cfa6d4aa10..38306b7c13696a9177e4935a8a255cd7dc8a3909 100644 (file)
@@ -2,8 +2,8 @@ use crate::{
   objects::person::ApubPerson,
   protocol::{activities::following::follow::FollowCommunity, Unparsed},
 };
+use activitypub_federation::core::object_id::ObjectId;
 use activitystreams_kinds::activity::UndoType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
index d8ba7cbae3d88e0f915e3994802cd2f88659dfa7..77e526884624270084915aa0532ae3e238ef2dce 100644 (file)
@@ -2,8 +2,8 @@ use crate::{
   objects::person::ApubPerson,
   protocol::{activities::voting::vote::Vote, Unparsed},
 };
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
 use activitystreams_kinds::activity::UndoType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
@@ -11,10 +11,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct UndoVote {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: Vote,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: UndoType,
index 763d862335ccf3600ccff06381409dfebee98033..80ea2ed5629ece1b551eec6025f2b05b647cc374 100644 (file)
@@ -3,8 +3,8 @@ use crate::{
   objects::person::ApubPerson,
   protocol::Unparsed,
 };
-use lemmy_apub_lib::object_id::ObjectId;
-use lemmy_utils::LemmyError;
+use activitypub_federation::{core::object_id::ObjectId, deser::helpers::deserialize_one_or_many};
+use lemmy_utils::error::LemmyError;
 use serde::{Deserialize, Serialize};
 use std::convert::TryFrom;
 use strum_macros::Display;
@@ -14,10 +14,10 @@ use url::Url;
 #[serde(rename_all = "camelCase")]
 pub struct Vote {
   pub(crate) actor: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) object: ObjectId<PostOrComment>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) cc: Vec<Url>,
   #[serde(rename = "type")]
   pub(crate) kind: VoteType,
index 265575af4a722689b753fa12a5f21406ed7b9872..8c9cf06ed4ff6c32419fcc7e1355005f35db8b2e 100644 (file)
@@ -1,5 +1,5 @@
 use activitystreams_kinds::collection::OrderedCollectionType;
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
index 777d19803b61ff66c6a49527b50ae8410c8b0362..eeea8e07330b1f2ba2204c76d717b36811d929b0 100644 (file)
@@ -3,7 +3,7 @@ use activitystreams_kinds::collection::CollectionType;
 use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::source::community::Community;
 use lemmy_db_views_actor::structs::CommunityFollowerView;
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use url::Url;
index 6a72b9551675a295b9b30600c172fd4a8849806f..4d1042821c745064a7a1e161f6f2dc7ba6aabd2a 100644 (file)
@@ -1,6 +1,6 @@
 use crate::objects::person::ApubPerson;
+use activitypub_federation::core::object_id::ObjectId;
 use activitystreams_kinds::collection::OrderedCollectionType;
-use lemmy_apub_lib::object_id::ObjectId;
 use serde::{Deserialize, Serialize};
 use url::Url;
 
index 3206ac23e959f58a7b11b58007fc3511948863d9..c81a5c159d2672c37c220175afcb4db16a562e78 100644 (file)
@@ -1,7 +1,8 @@
+use crate::local_instance;
+use activitypub_federation::{deser::values::MediaTypeMarkdown, utils::fetch_object_http};
 use activitystreams_kinds::object::ImageType;
-use lemmy_apub_lib::{utils::fetch_object_http, values::MediaTypeMarkdown};
 use lemmy_db_schema::newtypes::DbUrl;
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{de::DeserializeOwned, Deserialize, Serialize};
 use std::collections::HashMap;
@@ -49,7 +50,7 @@ impl ImageObject {
 pub struct Unparsed(HashMap<String, serde_json::Value>);
 
 pub(crate) trait Id {
-  fn id(&self) -> &Url;
+  fn object_id(&self) -> &Url;
 }
 
 #[derive(Clone, Debug, Deserialize, Serialize)]
@@ -63,7 +64,7 @@ impl<Kind: Id + DeserializeOwned> IdOrNestedObject<Kind> {
   pub(crate) fn id(&self) -> &Url {
     match self {
       IdOrNestedObject::Id(i) => i,
-      IdOrNestedObject::NestedObject(n) => n.id(),
+      IdOrNestedObject::NestedObject(n) => n.object_id(),
     }
   }
   pub(crate) async fn object(
@@ -72,7 +73,9 @@ impl<Kind: Id + DeserializeOwned> IdOrNestedObject<Kind> {
     request_counter: &mut i32,
   ) -> Result<Kind, LemmyError> {
     match self {
-      IdOrNestedObject::Id(i) => fetch_object_http(&i, context.client(), request_counter).await,
+      IdOrNestedObject::Id(i) => {
+        Ok(fetch_object_http(&i, local_instance(context), request_counter).await?)
+      }
       IdOrNestedObject::NestedObject(o) => Ok(o),
     }
   }
@@ -80,9 +83,9 @@ impl<Kind: Id + DeserializeOwned> IdOrNestedObject<Kind> {
 
 #[cfg(test)]
 pub(crate) mod tests {
-  use crate::context::WithContext;
+  use activitypub_federation::deser::context::WithContext;
   use assert_json_diff::assert_json_include;
-  use lemmy_utils::LemmyError;
+  use lemmy_utils::error::LemmyError;
   use serde::{de::DeserializeOwned, Serialize};
   use std::{collections::HashMap, fs::File, io::BufReader};
 
index e0ac8db98628128798a4e4a59233fe68e24c4fa7..c2ee57e4eb4dff4a05cbc3c91b92c1f247e42cd2 100644 (file)
@@ -2,8 +2,14 @@ use crate::{
   objects::{person::ApubPerson, private_message::ApubPrivateMessage},
   protocol::Source,
 };
+use activitypub_federation::{
+  core::object_id::ObjectId,
+  deser::{
+    helpers::{deserialize_one, deserialize_skip_error},
+    values::MediaTypeHtml,
+  },
+};
 use chrono::{DateTime, FixedOffset};
-use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeHtml};
 use serde::{Deserialize, Serialize};
 use serde_with::skip_serializing_none;
 
@@ -14,12 +20,12 @@ pub struct ChatMessage {
   pub(crate) r#type: ChatMessageType,
   pub(crate) id: ObjectId<ApubPrivateMessage>,
   pub(crate) attributed_to: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one")]
-  pub(crate) to: [ObjectId<ApubPerson>; 1],
+  #[serde(deserialize_with = "deserialize_one")]
+  pub(crate) to: ObjectId<ApubPerson>,
   pub(crate) content: String,
 
   pub(crate) media_type: Option<MediaTypeHtml>,
-  #[serde(deserialize_with = "crate::deserialize_skip_error", default)]
+  #[serde(deserialize_with = "deserialize_skip_error", default)]
   pub(crate) source: Option<Source>,
   pub(crate) published: Option<DateTime<FixedOffset>>,
   pub(crate) updated: Option<DateTime<FixedOffset>>,
index 8f161c2da7ed1d9dca8f10f3f06277176556e034..ba01e12d56946f55e10d6831a642bee25c24fcd6 100644 (file)
@@ -1,5 +1,5 @@
 use crate::{
-  check_is_apub_id_valid,
+  check_apub_id_valid_with_strictness,
   collections::{
     community_moderators::ApubCommunityModerators,
     community_outbox::ApubCommunityOutbox,
@@ -7,13 +7,17 @@ use crate::{
   objects::{community::ApubCommunity, read_from_string_or_source_opt},
   protocol::{objects::Endpoints, ImageObject, Source},
 };
+use activitypub_federation::{
+  core::{object_id::ObjectId, signatures::PublicKey},
+  deser::helpers::deserialize_skip_error,
+  utils::verify_domains_match,
+};
 use activitystreams_kinds::actor::GroupType;
 use chrono::{DateTime, FixedOffset};
-use lemmy_apub_lib::{object_id::ObjectId, signatures::PublicKey, verify::verify_domains_match};
 use lemmy_db_schema::{source::community::CommunityForm, utils::naive_now};
 use lemmy_utils::{
+  error::LemmyError,
   utils::{check_slurs, check_slurs_opt},
-  LemmyError,
 };
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
@@ -36,7 +40,7 @@ pub struct Group {
   /// title
   pub(crate) name: Option<String>,
   pub(crate) summary: Option<String>,
-  #[serde(deserialize_with = "crate::deserialize_skip_error", default)]
+  #[serde(deserialize_with = "deserialize_skip_error", default)]
   pub(crate) source: Option<Source>,
   pub(crate) icon: Option<ImageObject>,
   /// banner
@@ -59,7 +63,7 @@ impl Group {
     expected_domain: &Url,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
-    check_is_apub_id_valid(self.id.inner(), true, &context.settings())?;
+    check_apub_id_valid_with_strictness(self.id.inner(), true, &context.settings())?;
     verify_domains_match(expected_domain, self.id.inner())?;
 
     let slur_regex = &context.settings().slur_regex();
index a18b72795fededb912e28c6d1519cfeaa9167c9c..b921ad207fef580feb9960ca4580aafed5548da8 100644 (file)
@@ -2,8 +2,11 @@ use crate::{
   objects::instance::ApubSite,
   protocol::{ImageObject, Source},
 };
+use activitypub_federation::{
+  core::{object_id::ObjectId, signatures::PublicKey},
+  deser::{helpers::deserialize_skip_error, values::MediaTypeHtml},
+};
 use chrono::{DateTime, FixedOffset};
-use lemmy_apub_lib::{object_id::ObjectId, signatures::PublicKey, values::MediaTypeHtml};
 use serde::{Deserialize, Serialize};
 use serde_with::skip_serializing_none;
 use url::Url;
@@ -30,7 +33,7 @@ pub struct Instance {
 
   // sidebar
   pub(crate) content: Option<String>,
-  #[serde(deserialize_with = "crate::deserialize_skip_error", default)]
+  #[serde(deserialize_with = "deserialize_skip_error", default)]
   pub(crate) source: Option<Source>,
   // short instance description
   pub(crate) summary: Option<String>,
index ac3e722c7b1c41ee56db975f211b062fdc551016..cd17e65d5f6cc1c102a0389a9b65f02baadace07 100644 (file)
@@ -1,15 +1,22 @@
 use crate::{
   fetcher::post_or_comment::PostOrComment,
+  local_instance,
   mentions::MentionOrValue,
   objects::{comment::ApubComment, person::ApubPerson, post::ApubPost},
   protocol::Source,
 };
+use activitypub_federation::{
+  core::object_id::ObjectId,
+  deser::{
+    helpers::{deserialize_one_or_many, deserialize_skip_error},
+    values::MediaTypeMarkdownOrHtml,
+  },
+};
 use activitystreams_kinds::object::NoteType;
 use chrono::{DateTime, FixedOffset};
 use lemmy_api_common::utils::blocking;
-use lemmy_apub_lib::{object_id::ObjectId, values::MediaTypeMarkdownOrHtml};
 use lemmy_db_schema::{newtypes::CommentId, source::post::Post, traits::Crud};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use serde_with::skip_serializing_none;
@@ -23,15 +30,15 @@ pub struct Note {
   pub(crate) r#type: NoteType,
   pub(crate) id: ObjectId<ApubComment>,
   pub(crate) attributed_to: ObjectId<ApubPerson>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many", default)]
+  #[serde(deserialize_with = "deserialize_one_or_many", default)]
   pub(crate) cc: Vec<Url>,
   pub(crate) content: String,
   pub(crate) in_reply_to: ObjectId<PostOrComment>,
 
   pub(crate) media_type: Option<MediaTypeMarkdownOrHtml>,
-  #[serde(deserialize_with = "crate::deserialize_skip_error", default)]
+  #[serde(deserialize_with = "deserialize_skip_error", default)]
   pub(crate) source: Option<Source>,
   pub(crate) published: Option<DateTime<FixedOffset>>,
   pub(crate) updated: Option<DateTime<FixedOffset>>,
@@ -49,7 +56,7 @@ impl Note {
     let parent = Box::pin(
       self
         .in_reply_to
-        .dereference(context, context.client(), request_counter)
+        .dereference::<LemmyError>(context, local_instance(context), request_counter)
         .await?,
     );
     match parent.deref() {
index 426de96f4cf750281e8bc86c0ea4386d431d852c..74db11afef500ba5ff99d2c719a720dd0cc8c86c 100644 (file)
@@ -1,19 +1,23 @@
 use crate::{
   fetcher::user_or_community::{PersonOrGroupType, UserOrCommunity},
+  local_instance,
   objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost},
   protocol::{ImageObject, Source},
 };
-use activitystreams_kinds::link::LinkType;
-use chrono::{DateTime, FixedOffset};
-use itertools::Itertools;
-use lemmy_apub_lib::{
+use activitypub_federation::{
+  core::object_id::ObjectId,
   data::Data,
-  object_id::ObjectId,
+  deser::{
+    helpers::{deserialize_one_or_many, deserialize_skip_error},
+    values::MediaTypeMarkdownOrHtml,
+  },
   traits::{ActivityHandler, ApubObject},
-  values::MediaTypeMarkdownOrHtml,
 };
+use activitystreams_kinds::link::LinkType;
+use chrono::{DateTime, FixedOffset};
+use itertools::Itertools;
 use lemmy_db_schema::newtypes::DbUrl;
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use serde_with::skip_serializing_none;
@@ -35,18 +39,18 @@ pub struct Page {
   pub(crate) kind: PageType,
   pub(crate) id: ObjectId<ApubPost>,
   pub(crate) attributed_to: AttributedTo,
-  #[serde(deserialize_with = "crate::deserialize_one_or_many")]
+  #[serde(deserialize_with = "deserialize_one_or_many")]
   pub(crate) to: Vec<Url>,
   pub(crate) name: String,
 
-  #[serde(deserialize_with = "crate::deserialize_one_or_many", default)]
+  #[serde(deserialize_with = "deserialize_one_or_many", default)]
   pub(crate) cc: Vec<Url>,
   pub(crate) content: Option<String>,
   pub(crate) media_type: Option<MediaTypeMarkdownOrHtml>,
-  #[serde(deserialize_with = "crate::deserialize_skip_error", default)]
+  #[serde(deserialize_with = "deserialize_skip_error", default)]
   pub(crate) source: Option<Source>,
   /// deprecated, use attachment field
-  #[serde(deserialize_with = "crate::deserialize_skip_error", default)]
+  #[serde(deserialize_with = "deserialize_skip_error", default)]
   pub(crate) url: Option<Url>,
   /// most software uses array type for attachment field, so we do the same. nevertheless, we only
   /// use the first item
@@ -89,7 +93,7 @@ impl Page {
   /// Both stickied and locked need to be false on a newly created post (verified in [[CreatePost]].
   pub(crate) async fn is_mod_action(&self, context: &LemmyContext) -> Result<bool, LemmyError> {
     let old_post = ObjectId::<ApubPost>::new(self.id.clone())
-      .dereference_local(context)
+      .dereference_local::<LemmyError>(context)
       .await;
 
     let stickied_changed = Page::is_stickied_changed(&old_post, &self.stickied);
@@ -135,7 +139,7 @@ impl Page {
           if let Some(cid) = iter.next() {
             let cid = ObjectId::new(cid.clone());
             if let Ok(c) = cid
-              .dereference(context, context.client(), request_counter)
+              .dereference::<LemmyError>(context, local_instance(context), request_counter)
               .await
             {
               break Ok(c);
@@ -150,7 +154,7 @@ impl Page {
           .find(|a| a.kind == PersonOrGroupType::Group)
           .map(|a| ObjectId::<ApubCommunity>::new(a.id.clone().into_inner()))
           .ok_or_else(|| LemmyError::from_message("page does not specify group"))?
-          .dereference(context, context.client(), request_counter)
+          .dereference::<LemmyError>(context, local_instance(context), request_counter)
           .await
       }
     }
@@ -181,6 +185,13 @@ impl Attachment {
 #[async_trait::async_trait(?Send)]
 impl ActivityHandler for Page {
   type DataType = LemmyContext;
+  type Error = LemmyError;
+  fn id(&self) -> &Url {
+    unimplemented!()
+  }
+  fn actor(&self) -> &Url {
+    unimplemented!()
+  }
   async fn verify(
     &self,
     data: &Data<Self::DataType>,
index 75d20cf6d287ecd931187520f1605dad6a53daab..ac52e46ac234b2ee469cc9af4db57da67b60cddf 100644 (file)
@@ -2,8 +2,11 @@ use crate::{
   objects::person::ApubPerson,
   protocol::{objects::Endpoints, ImageObject, Source},
 };
+use activitypub_federation::{
+  core::{object_id::ObjectId, signatures::PublicKey},
+  deser::helpers::deserialize_skip_error,
+};
 use chrono::{DateTime, FixedOffset};
-use lemmy_apub_lib::{object_id::ObjectId, signatures::PublicKey};
 use serde::{Deserialize, Serialize};
 use serde_with::skip_serializing_none;
 use url::Url;
@@ -32,7 +35,7 @@ pub struct Person {
   /// displayname
   pub(crate) name: Option<String>,
   pub(crate) summary: Option<String>,
-  #[serde(deserialize_with = "crate::deserialize_skip_error", default)]
+  #[serde(deserialize_with = "deserialize_skip_error", default)]
   pub(crate) source: Option<Source>,
   /// user avatar
   pub(crate) icon: Option<ImageObject>,
index 0e60d6247cd77279ce326c8d357ce28eacfee557..1b66f2a7eb4d0bfa3c8b94b8176b699d23646a1b 100644 (file)
@@ -23,7 +23,7 @@ impl Tombstone {
 }
 
 impl Id for Tombstone {
-  fn id(&self) -> &Url {
+  fn object_id(&self) -> &Url {
     &self.id
   }
 }
diff --git a/crates/apub_lib/src/activity_queue.rs b/crates/apub_lib/src/activity_queue.rs
deleted file mode 100644 (file)
index a94229f..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-use crate::{signatures::sign_and_send, traits::ActorType};
-use anyhow::{anyhow, Context, Error};
-use background_jobs::{
-  memory_storage::Storage,
-  ActixJob,
-  Backoff,
-  Manager,
-  MaxRetries,
-  QueueHandle,
-  WorkerConfig,
-};
-use lemmy_utils::{location_info, LemmyError};
-use reqwest_middleware::ClientWithMiddleware;
-use serde::{Deserialize, Serialize};
-use std::{env, fmt::Debug, future::Future, pin::Pin};
-use tracing::{info, warn};
-use url::Url;
-
-pub async fn send_activity(
-  activity_id: &Url,
-  actor: &dyn ActorType,
-  inboxes: Vec<&Url>,
-  activity: String,
-  client: &ClientWithMiddleware,
-  activity_queue: &QueueHandle,
-) -> Result<(), LemmyError> {
-  for i in inboxes {
-    let message = SendActivityTask {
-      activity_id: activity_id.clone(),
-      inbox: i.to_owned(),
-      actor_id: actor.actor_id(),
-      activity: activity.clone(),
-      private_key: actor.private_key().context(location_info!())?,
-    };
-    if env::var("APUB_TESTING_SEND_SYNC").is_ok() {
-      let res = do_send(message, client).await;
-      // Don't fail on error, as we intentionally do some invalid actions in tests, to verify that
-      // they are rejected on the receiving side. These errors shouldn't bubble up to make the API
-      // call fail. This matches the behaviour in production.
-      if let Err(e) = res {
-        warn!("{}", e);
-      }
-    } else {
-      activity_queue.queue::<SendActivityTask>(message).await?;
-      let stats = activity_queue.get_stats().await?;
-      info!(
-        "Activity queue stats: pending: {}, running: {}, dead (this hour): {}, complete (this hour): {}",
-        stats.pending,
-        stats.running,
-        stats.dead.this_hour(),
-        stats.complete.this_hour()
-      );
-    }
-  }
-
-  Ok(())
-}
-
-#[derive(Clone, Debug, Deserialize, Serialize)]
-struct SendActivityTask {
-  activity_id: Url,
-  inbox: Url,
-  actor_id: Url,
-  activity: String,
-  private_key: String,
-}
-
-/// Signs the activity with the sending actor's key, and delivers to the given inbox. Also retries
-/// if the delivery failed.
-impl ActixJob for SendActivityTask {
-  type State = MyState;
-  type Future = Pin<Box<dyn Future<Output = Result<(), Error>>>>;
-  const NAME: &'static str = "SendActivityTask";
-
-  /// With these params, retries are made at the following intervals:
-  ///          3s
-  ///          9s
-  ///         27s
-  ///      1m 21s
-  ///      4m  3s
-  ///     12m  9s
-  ///     36m 27s
-  ///  1h 49m 21s
-  ///  5h 28m  3s
-  /// 16h 24m  9s
-  const MAX_RETRIES: MaxRetries = MaxRetries::Count(10);
-  const BACKOFF: Backoff = Backoff::Exponential(3);
-
-  fn run(self, state: Self::State) -> Self::Future {
-    Box::pin(async move { do_send(self, &state.client).await })
-  }
-}
-
-async fn do_send(task: SendActivityTask, client: &ClientWithMiddleware) -> Result<(), Error> {
-  info!("Sending {} to {}", task.activity_id, task.inbox);
-  let result = sign_and_send(
-    client,
-    &task.inbox,
-    task.activity.clone(),
-    &task.actor_id,
-    task.private_key.to_owned(),
-  )
-  .await;
-
-  let r: Result<(), Error> = match result {
-    Ok(o) => {
-      if !o.status().is_success() {
-        let status = o.status();
-        let text = o.text().await?;
-
-        Err(anyhow!(
-          "Send {} to {} failed with status {}: {}",
-          task.activity_id,
-          task.inbox,
-          status,
-          text,
-        ))
-      } else {
-        Ok(())
-      }
-    }
-    Err(e) => Err(anyhow!(
-      "Failed to send activity {} to {}: {}",
-      &task.activity_id,
-      task.inbox,
-      e
-    )),
-  };
-  r
-}
-
-pub fn create_activity_queue(client: ClientWithMiddleware, worker_count: u64) -> Manager {
-  // Configure and start our workers
-  WorkerConfig::new_managed(Storage::new(), move |_| MyState {
-    client: client.clone(),
-  })
-  .register::<SendActivityTask>()
-  .set_worker_count("default", worker_count)
-  .start()
-}
-
-#[derive(Clone)]
-struct MyState {
-  pub client: ClientWithMiddleware,
-}
diff --git a/crates/apub_lib/src/data.rs b/crates/apub_lib/src/data.rs
deleted file mode 100644 (file)
index d366f0f..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-use std::{ops::Deref, sync::Arc};
-
-#[derive(Debug)]
-pub struct Data<T: ?Sized>(Arc<T>);
-
-impl<T> Data<T> {
-  /// Create new `Data` instance.
-  pub fn new(state: T) -> Data<T> {
-    Data(Arc::new(state))
-  }
-
-  /// Get reference to inner app data.
-  pub fn get_ref(&self) -> &T {
-    self.0.as_ref()
-  }
-
-  /// Convert to the internal Arc<T>
-  pub fn into_inner(self) -> Arc<T> {
-    self.0
-  }
-}
-
-impl<T: ?Sized> Deref for Data<T> {
-  type Target = Arc<T>;
-
-  fn deref(&self) -> &Arc<T> {
-    &self.0
-  }
-}
-
-impl<T: ?Sized> Clone for Data<T> {
-  fn clone(&self) -> Data<T> {
-    Data(self.0.clone())
-  }
-}
diff --git a/crates/apub_lib/src/lib.rs b/crates/apub_lib/src/lib.rs
deleted file mode 100644 (file)
index 7c11016..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-pub mod activity_queue;
-pub mod data;
-pub mod object_id;
-pub mod signatures;
-pub mod traits;
-pub mod utils;
-pub mod values;
-pub mod verify;
-
-pub static APUB_JSON_CONTENT_TYPE: &str = "application/activity+json";
diff --git a/crates/apub_lib/src/object_id.rs b/crates/apub_lib/src/object_id.rs
deleted file mode 100644 (file)
index da38961..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-use crate::{traits::ApubObject, utils::fetch_object_http};
-use anyhow::anyhow;
-use chrono::{Duration as ChronoDuration, NaiveDateTime, Utc};
-use diesel::NotFound;
-use lemmy_utils::{settings::structs::Settings, LemmyError};
-use reqwest_middleware::ClientWithMiddleware;
-use serde::{Deserialize, Serialize};
-use std::{
-  fmt::{Debug, Display, Formatter},
-  marker::PhantomData,
-};
-use url::Url;
-
-/// We store Url on the heap because it is quite large (88 bytes).
-#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
-#[serde(transparent)]
-pub struct ObjectId<Kind>(Box<Url>, #[serde(skip)] PhantomData<Kind>)
-where
-  Kind: ApubObject + Send + 'static,
-  for<'de2> <Kind as ApubObject>::ApubType: serde::Deserialize<'de2>;
-
-impl<Kind> ObjectId<Kind>
-where
-  Kind: ApubObject + Send + 'static,
-  for<'de2> <Kind as ApubObject>::ApubType: serde::Deserialize<'de2>,
-{
-  pub fn new<T>(url: T) -> Self
-  where
-    T: Into<Url>,
-  {
-    ObjectId(Box::new(url.into()), PhantomData::<Kind>)
-  }
-
-  pub fn inner(&self) -> &Url {
-    &self.0
-  }
-
-  pub fn into_inner(self) -> Url {
-    *self.0
-  }
-
-  /// Fetches an activitypub object, either from local database (if possible), or over http.
-  pub async fn dereference(
-    &self,
-    data: &<Kind as ApubObject>::DataType,
-    client: &ClientWithMiddleware,
-    request_counter: &mut i32,
-  ) -> Result<Kind, LemmyError> {
-    let db_object = self.dereference_from_db(data).await?;
-
-    // if its a local object, only fetch it from the database and not over http
-    if self.0.domain() == Some(&Settings::get().get_hostname_without_port()?) {
-      return match db_object {
-        None => Err(NotFound {}.into()),
-        Some(o) => Ok(o),
-      };
-    }
-
-    // object found in database
-    if let Some(object) = db_object {
-      // object is old and should be refetched
-      if let Some(last_refreshed_at) = object.last_refreshed_at() {
-        if should_refetch_object(last_refreshed_at) {
-          return self
-            .dereference_from_http(data, client, request_counter, Some(object))
-            .await;
-        }
-      }
-      Ok(object)
-    }
-    // object not found, need to fetch over http
-    else {
-      self
-        .dereference_from_http(data, client, request_counter, None)
-        .await
-    }
-  }
-
-  /// Fetch an object from the local db. Instead of falling back to http, this throws an error if
-  /// the object is not found in the database.
-  pub async fn dereference_local(
-    &self,
-    data: &<Kind as ApubObject>::DataType,
-  ) -> Result<Kind, LemmyError> {
-    let object = self.dereference_from_db(data).await?;
-    object.ok_or_else(|| anyhow!("object not found in database {}", self).into())
-  }
-
-  /// returning none means the object was not found in local db
-  async fn dereference_from_db(
-    &self,
-    data: &<Kind as ApubObject>::DataType,
-  ) -> Result<Option<Kind>, LemmyError> {
-    let id = self.0.clone();
-    ApubObject::read_from_apub_id(*id, data).await
-  }
-
-  async fn dereference_from_http(
-    &self,
-    data: &<Kind as ApubObject>::DataType,
-    client: &ClientWithMiddleware,
-    request_counter: &mut i32,
-    db_object: Option<Kind>,
-  ) -> Result<Kind, LemmyError> {
-    let res = fetch_object_http(&self.0, client, request_counter).await;
-
-    if let Err(e) = &res {
-      // TODO: very ugly
-      if e.message == Some("410".to_string()) {
-        if let Some(db_object) = db_object {
-          db_object.delete(data).await?;
-        }
-        return Err(anyhow!("Fetched remote object {} which was deleted", self).into());
-      }
-    }
-
-    let res2 = res?;
-
-    Kind::verify(&res2, self.inner(), data, request_counter).await?;
-    Kind::from_apub(res2, data, request_counter).await
-  }
-}
-
-static ACTOR_REFETCH_INTERVAL_SECONDS: i64 = 24 * 60 * 60;
-static ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG: i64 = 20;
-
-/// Determines when a remote actor should be refetched from its instance. In release builds, this is
-/// `ACTOR_REFETCH_INTERVAL_SECONDS` after the last refetch, in debug builds
-/// `ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG`.
-///
-/// TODO it won't pick up new avatars, summaries etc until a day after.
-/// Actors need an "update" activity pushed to other servers to fix this.
-fn should_refetch_object(last_refreshed: NaiveDateTime) -> bool {
-  let update_interval = if cfg!(debug_assertions) {
-    // avoid infinite loop when fetching community outbox
-    ChronoDuration::seconds(ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG)
-  } else {
-    ChronoDuration::seconds(ACTOR_REFETCH_INTERVAL_SECONDS)
-  };
-  let refresh_limit = Utc::now().naive_utc() - update_interval;
-  last_refreshed.lt(&refresh_limit)
-}
-
-impl<Kind> Display for ObjectId<Kind>
-where
-  Kind: ApubObject + Send + 'static,
-  for<'de2> <Kind as ApubObject>::ApubType: serde::Deserialize<'de2>,
-{
-  #[allow(clippy::to_string_in_display)]
-  fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-    // Use to_string here because Url.display is not useful for us
-    write!(f, "{}", self.0)
-  }
-}
-
-impl<Kind> From<ObjectId<Kind>> for Url
-where
-  Kind: ApubObject + Send + 'static,
-  for<'de2> <Kind as ApubObject>::ApubType: serde::Deserialize<'de2>,
-{
-  fn from(id: ObjectId<Kind>) -> Self {
-    *id.0
-  }
-}
-
-#[cfg(test)]
-mod tests {
-  use super::*;
-  use crate::object_id::should_refetch_object;
-
-  #[test]
-  fn test_should_refetch_object() {
-    let one_second_ago = Utc::now().naive_utc() - ChronoDuration::seconds(1);
-    assert!(!should_refetch_object(one_second_ago));
-
-    let two_days_ago = Utc::now().naive_utc() - ChronoDuration::days(2);
-    assert!(should_refetch_object(two_days_ago));
-  }
-}
diff --git a/crates/apub_lib/src/signatures.rs b/crates/apub_lib/src/signatures.rs
deleted file mode 100644 (file)
index 6e5d6d2..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-use crate::APUB_JSON_CONTENT_TYPE;
-use actix_web::HttpRequest;
-use anyhow::anyhow;
-use http::{header::HeaderName, HeaderMap, HeaderValue};
-use http_signature_normalization_actix::Config as ConfigActix;
-use http_signature_normalization_reqwest::prelude::{Config, SignExt};
-use lemmy_utils::{LemmyError, REQWEST_TIMEOUT};
-use once_cell::sync::Lazy;
-use openssl::{
-  hash::MessageDigest,
-  pkey::PKey,
-  sign::{Signer, Verifier},
-};
-use reqwest::Response;
-use reqwest_middleware::ClientWithMiddleware;
-use serde::{Deserialize, Serialize};
-use sha2::{Digest, Sha256};
-use std::str::FromStr;
-use tracing::debug;
-use url::Url;
-
-static CONFIG2: Lazy<ConfigActix> = Lazy::new(ConfigActix::new);
-static HTTP_SIG_CONFIG: Lazy<Config> = Lazy::new(Config::new);
-
-/// Creates an HTTP post request to `inbox_url`, with the given `client` and `headers`, and
-/// `activity` as request body. The request is signed with `private_key` and then sent.
-pub async fn sign_and_send(
-  client: &ClientWithMiddleware,
-  inbox_url: &Url,
-  activity: String,
-  actor_id: &Url,
-  private_key: String,
-) -> Result<Response, LemmyError> {
-  let signing_key_id = format!("{}#main-key", actor_id);
-
-  let mut headers = HeaderMap::new();
-  let mut host = inbox_url.domain().expect("read inbox domain").to_string();
-  if let Some(port) = inbox_url.port() {
-    host = format!("{}:{}", host, port);
-  }
-  headers.insert(
-    HeaderName::from_str("Content-Type")?,
-    HeaderValue::from_str(APUB_JSON_CONTENT_TYPE)?,
-  );
-  headers.insert(HeaderName::from_str("Host")?, HeaderValue::from_str(&host)?);
-
-  let request = client
-    .post(&inbox_url.to_string())
-    // signature is only valid for 10 seconds, so no reason to wait any longer
-    .timeout(REQWEST_TIMEOUT)
-    .headers(headers)
-    .signature_with_digest(
-      HTTP_SIG_CONFIG.clone(),
-      signing_key_id,
-      Sha256::new(),
-      activity,
-      move |signing_string| {
-        let private_key = PKey::private_key_from_pem(private_key.as_bytes())?;
-        let mut signer = Signer::new(MessageDigest::sha256(), &private_key)?;
-        signer.update(signing_string.as_bytes())?;
-
-        Ok(base64::encode(signer.sign_to_vec()?)) as Result<_, LemmyError>
-      },
-    )
-    .await?;
-
-  let response = client.execute(request).await?;
-
-  Ok(response)
-}
-
-/// Verifies the HTTP signature on an incoming inbox request.
-pub fn verify_signature(request: &HttpRequest, public_key: &str) -> Result<(), LemmyError> {
-  let verified = CONFIG2
-    .begin_verify(
-      request.method(),
-      request.uri().path_and_query(),
-      request.headers().clone(),
-    )?
-    .verify(|signature, signing_string| -> Result<bool, LemmyError> {
-      debug!(
-        "Verifying with key {}, message {}",
-        &public_key, &signing_string
-      );
-      let public_key = PKey::public_key_from_pem(public_key.as_bytes())?;
-      let mut verifier = Verifier::new(MessageDigest::sha256(), &public_key)?;
-      verifier.update(signing_string.as_bytes())?;
-      Ok(verifier.verify(&base64::decode(signature)?)?)
-    })?;
-
-  if verified {
-    debug!("verified signature for {}", &request.uri());
-    Ok(())
-  } else {
-    Err(anyhow!("Invalid signature on request: {}", &request.uri()).into())
-  }
-}
-
-#[derive(Clone, Debug, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct PublicKey {
-  pub(crate) id: String,
-  pub(crate) owner: Box<Url>,
-  pub public_key_pem: String,
-}
diff --git a/crates/apub_lib/src/traits.rs b/crates/apub_lib/src/traits.rs
deleted file mode 100644 (file)
index 43fec52..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-use crate::{data::Data, signatures::PublicKey};
-use chrono::NaiveDateTime;
-pub use lemmy_apub_lib_derive::*;
-use lemmy_utils::LemmyError;
-use url::Url;
-
-#[async_trait::async_trait(?Send)]
-pub trait ActivityHandler {
-  type DataType;
-  async fn verify(
-    &self,
-    data: &Data<Self::DataType>,
-    request_counter: &mut i32,
-  ) -> Result<(), LemmyError>;
-
-  async fn receive(
-    self,
-    data: &Data<Self::DataType>,
-    request_counter: &mut i32,
-  ) -> Result<(), LemmyError>;
-}
-
-#[async_trait::async_trait(?Send)]
-pub trait ApubObject {
-  type DataType;
-  type ApubType;
-  type DbType;
-  type TombstoneType;
-
-  /// If this object should be refetched after a certain interval, it should return the last refresh
-  /// time here. This is mainly used to update remote actors.
-  fn last_refreshed_at(&self) -> Option<NaiveDateTime>;
-  /// Try to read the object with given ID from local database. Returns Ok(None) if it doesn't exist.
-  async fn read_from_apub_id(
-    object_id: Url,
-    data: &Self::DataType,
-  ) -> Result<Option<Self>, LemmyError>
-  where
-    Self: Sized;
-  /// Marks the object as deleted in local db. Called when a tombstone is received.
-  async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError>;
-
-  /// Trait for converting an object or actor into the respective ActivityPub type.
-  async fn into_apub(self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError>;
-  fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError>;
-
-  async fn verify(
-    apub: &Self::ApubType,
-    expected_domain: &Url,
-    data: &Self::DataType,
-    request_counter: &mut i32,
-  ) -> Result<(), LemmyError>;
-
-  /// Converts an object from ActivityPub type to Lemmy internal type.
-  ///
-  /// * `apub` The object to read from
-  /// * `context` LemmyContext which holds DB pool, HTTP client etc
-  /// * `expected_domain` Domain where the object was received from. None in case of mod action.
-  /// * `mod_action_allowed` True if the object can be a mod activity, ignore `expected_domain` in this case
-  async fn from_apub(
-    apub: Self::ApubType,
-    data: &Self::DataType,
-    request_counter: &mut i32,
-  ) -> Result<Self, LemmyError>
-  where
-    Self: Sized;
-}
-
-/// Common methods provided by ActivityPub actors (community and person). Not all methods are
-/// implemented by all actors.
-pub trait ActorType {
-  fn actor_id(&self) -> Url;
-
-  fn public_key(&self) -> String;
-  fn private_key(&self) -> Option<String>;
-
-  fn inbox_url(&self) -> Url;
-
-  fn shared_inbox_url(&self) -> Option<Url>;
-
-  fn shared_inbox_or_inbox_url(&self) -> Url {
-    self.shared_inbox_url().unwrap_or_else(|| self.inbox_url())
-  }
-
-  fn get_public_key(&self) -> Result<PublicKey, LemmyError> {
-    Ok(PublicKey {
-      id: format!("{}#main-key", self.actor_id()),
-      owner: Box::new(self.actor_id()),
-      public_key_pem: self.public_key(),
-    })
-  }
-}
diff --git a/crates/apub_lib/src/utils.rs b/crates/apub_lib/src/utils.rs
deleted file mode 100644 (file)
index 391e01d..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-use crate::APUB_JSON_CONTENT_TYPE;
-use anyhow::anyhow;
-use http::StatusCode;
-use lemmy_utils::{request::retry, settings::structs::Settings, LemmyError, REQWEST_TIMEOUT};
-use reqwest_middleware::ClientWithMiddleware;
-use serde::de::DeserializeOwned;
-use tracing::log::info;
-use url::Url;
-
-pub async fn fetch_object_http<Kind: DeserializeOwned>(
-  url: &Url,
-  client: &ClientWithMiddleware,
-  request_counter: &mut i32,
-) -> Result<Kind, LemmyError> {
-  // dont fetch local objects this way
-  debug_assert!(url.domain() != Some(&Settings::get().hostname));
-  info!("Fetching remote object {}", url.to_string());
-
-  *request_counter += 1;
-  if *request_counter > Settings::get().http_fetch_retry_limit {
-    return Err(LemmyError::from(anyhow!("Request retry limit reached")));
-  }
-
-  let res = retry(|| {
-    client
-      .get(url.as_str())
-      .header("Accept", APUB_JSON_CONTENT_TYPE)
-      .timeout(REQWEST_TIMEOUT)
-      .send()
-  })
-  .await?;
-
-  if res.status() == StatusCode::GONE {
-    return Err(LemmyError::from_message("410"));
-  }
-
-  Ok(res.json().await?)
-}
diff --git a/crates/apub_lib/src/values.rs b/crates/apub_lib/src/values.rs
deleted file mode 100644 (file)
index bf1780a..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-//! The enums here serve to limit a json string value to a single, hardcoded value which can be
-//! verified at compilation time. When using it as the type of a struct field, the struct can only
-//! be constructed or deserialized if the field has the exact same value.
-//!
-//! If we used String as the field type, any value would be accepted, and we would have to check
-//! manually at runtime that it contains the expected value.
-//!
-//! The enums in [`activitystreams::activity::kind`] work in the same way, and can be used to
-//! distinguish different activity types.
-//!
-//! In the example below, `MyObject` can only be constructed or
-//! deserialized if `media_type` is `text/markdown`, but not if it is `text/html`.
-//!
-//! ```
-//! use lemmy_apub_lib::values::MediaTypeMarkdown;
-//! use serde_json::from_str;
-//! use serde::{Deserialize, Serialize};
-//!
-//! #[derive(Deserialize, Serialize)]
-//! struct MyObject {
-//!   content: String,
-//!   media_type: MediaTypeMarkdown,
-//! }
-//!
-//! let markdown_json = r#"{"content": "**test**", "media_type": "text/markdown"}"#;
-//! let from_markdown = from_str::<MyObject>(markdown_json);
-//! assert!(from_markdown.is_ok());
-//!
-//! let markdown_html = r#"{"content": "<b>test</b>", "media_type": "text/html"}"#;
-//! let from_html = from_str::<MyObject>(markdown_html);
-//! assert!(from_html.is_err());
-//! ```
-
-use serde::{Deserialize, Serialize};
-
-/// Media type for markdown text.
-///
-/// <https://www.iana.org/assignments/media-types/media-types.xhtml>
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub enum MediaTypeMarkdown {
-  #[serde(rename = "text/markdown")]
-  Markdown,
-}
-
-/// Media type for HTML text.
-///
-/// <https://www.iana.org/assignments/media-types/media-types.xhtml>
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub enum MediaTypeHtml {
-  #[serde(rename = "text/html")]
-  Html,
-}
-/// Media type which allows both markdown and HTML.
-#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
-pub enum MediaTypeMarkdownOrHtml {
-  #[serde(rename = "text/markdown")]
-  Markdown,
-  #[serde(rename = "text/html")]
-  Html,
-}
diff --git a/crates/apub_lib/src/verify.rs b/crates/apub_lib/src/verify.rs
deleted file mode 100644 (file)
index b792775..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-use lemmy_utils::LemmyError;
-use url::Url;
-
-#[derive(Debug)]
-struct DomainError;
-
-impl std::fmt::Display for DomainError {
-  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-    write!(f, "Domain mismatch")
-  }
-}
-
-impl std::error::Error for DomainError {}
-
-pub fn verify_domains_match(a: &Url, b: &Url) -> Result<(), LemmyError> {
-  if a.domain() != b.domain() {
-    return Err(DomainError.into());
-  }
-  Ok(())
-}
-
-pub fn verify_urls_match(a: &Url, b: &Url) -> Result<(), LemmyError> {
-  if a != b {
-    return Err(DomainError.into());
-  }
-  Ok(())
-}
diff --git a/crates/apub_lib_derive/src/lib.rs b/crates/apub_lib_derive/src/lib.rs
deleted file mode 100644 (file)
index d548af4..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-use proc_macro2::{TokenStream, TokenTree};
-use quote::quote;
-use syn::{parse_macro_input, Attribute, Data, DeriveInput, Fields::Unnamed, Ident, Variant};
-
-/// Generates implementation ActivityHandler for an enum, which looks like the following (handling
-/// all enum variants).
-///
-/// Based on this code:
-/// ```ignore
-/// #[derive(serde::Deserialize, serde::Serialize, ActivityHandler)]
-/// #[serde(untagged)]
-/// pub enum PersonInboxActivities {
-///  CreateNote(CreateNote),
-///  UpdateNote(UpdateNote),
-/// ```
-/// It will generate this:
-/// ```ignore
-/// impl ActivityHandler for PersonInboxActivities {
-///
-///     async fn verify(
-///     &self,
-///     context: &LemmyContext,
-///     request_counter: &mut i32,
-///   ) -> Result<(), LemmyError> {
-///     match self {
-///       PersonInboxActivities::CreateNote(a) => a.verify(context, request_counter).await,
-///       PersonInboxActivities::UpdateNote(a) => a.verify(context, request_counter).await,
-///     }
-///   }
-///
-///   async fn receive(
-///   &self,
-///   context: &LemmyContext,
-///   request_counter: &mut i32,
-/// ) -> Result<(), LemmyError> {
-///     match self {
-///       PersonInboxActivities::CreateNote(a) => a.receive(context, request_counter).await,
-///       PersonInboxActivities::UpdateNote(a) => a.receive(context, request_counter).await,
-///     }
-///   }
-/// fn common(&self) -> &ActivityCommonFields  {
-///     match self {
-///       PersonInboxActivities::CreateNote(a) => a.common(),
-///       PersonInboxActivities::UpdateNote(a) => a.common(),
-///     }
-///   }
-///
-/// ```
-#[proc_macro_derive(ActivityHandler, attributes(activity_handler))]
-pub fn derive_activity_handler(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
-  let input = parse_macro_input!(input as DeriveInput);
-  let attrs: Vec<&Attribute> = input
-    .attrs
-    .iter()
-    .filter(|attr| attr.path.is_ident("activity_handler"))
-    .collect();
-  let attrs: &Vec<TokenStream> = &attrs
-    .first()
-    .expect("Could not decode first attribute from token stream")
-    .tokens
-    .clone()
-    .into_iter()
-    .map(|t| {
-      if let TokenTree::Group(g) = t {
-        g.stream()
-      } else {
-        panic!()
-      }
-    })
-    .collect();
-  let attrs = attrs.first();
-
-  let enum_name = input.ident;
-
-  let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
-
-  let enum_variants = if let Data::Enum(d) = input.data {
-    d.variants
-  } else {
-    unimplemented!()
-  };
-
-  let body_verify = quote! {a.verify(context, request_counter).await};
-  let impl_verify = enum_variants
-    .iter()
-    .map(|v| generate_match_arm(&enum_name, v, &body_verify));
-  let body_receive = quote! {a.receive(context, request_counter).await};
-  let impl_receive = enum_variants
-    .iter()
-    .map(|v| generate_match_arm(&enum_name, v, &body_receive));
-
-  let expanded = quote! {
-      #[async_trait::async_trait(?Send)]
-      impl #impl_generics lemmy_apub_lib::traits::ActivityHandler for #enum_name #ty_generics #where_clause {
-        type DataType = #attrs;
-          async fn verify(
-              &self,
-              context: &lemmy_apub_lib::data::Data<Self::DataType>,
-              request_counter: &mut i32,
-            ) -> Result<(), lemmy_utils::LemmyError> {
-            match self {
-              #(#impl_verify)*
-            }
-          }
-          async fn receive(
-            self,
-            context: &lemmy_apub_lib::data::Data<Self::DataType>,
-            request_counter: &mut i32,
-          ) -> Result<(), lemmy_utils::LemmyError> {
-            match self {
-              #(#impl_receive)*
-            }
-          }
-      }
-  };
-  expanded.into()
-}
-
-fn generate_match_arm(enum_name: &Ident, variant: &Variant, body: &TokenStream) -> TokenStream {
-  let id = &variant.ident;
-  match &variant.fields {
-    Unnamed(_) => {
-      quote! {
-        #enum_name::#id(a) => #body,
-      }
-    }
-    _ => unimplemented!(),
-  }
-}
index 69101b6828b0c6945eb18989637ed5545785ad76..483c9e945ef6cf4ae6fadf1ba158c5541fc01a9c 100644 (file)
@@ -14,7 +14,7 @@ doctest = false
 
 [features]
 full = ["diesel", "diesel-derive-newtype", "diesel_migrations", "bcrypt", "lemmy_utils",
-    "lemmy_apub_lib", "sha2", "regex", "once_cell", "serde_json"]
+    "activitypub_federation", "sha2", "regex", "once_cell", "serde_json"]
 
 [dependencies]
 chrono = { version = "0.4.19", features = ["serde"], default-features = false }
@@ -23,7 +23,7 @@ url = { version = "2.2.2", features = ["serde"] }
 strum =  "0.24.0"
 strum_macros = "0.24.0"
 serde_json = { version = "1.0.79", features = ["preserve_order"], optional = true }
-lemmy_apub_lib = { version = "=0.16.5", path = "../apub_lib", optional = true }
+activitypub_federation = { version = "0.1.0", optional = true }
 lemmy_utils = { version = "=0.16.5", path = "../utils", optional = true }
 bcrypt = { version = "0.12.1", optional = true }
 diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"], optional = true }
index e90ae5248567099cf4be4772a4bd9a6319ddfe4a..d5506990d4ad4e6fbb6a03b2abce01d1ce6a933a 100644 (file)
@@ -5,7 +5,7 @@ use crate::{
   utils::naive_now,
 };
 use diesel::{dsl::*, result::Error, *};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use url::Url;
 
 impl Crud for PrivateMessage {
index 09c5ecdd832efd9e10c5bb1ab1b3aa89b2d437cd..c9ccc170089c3fcde6a949a908e76937dd1279b5 100644 (file)
@@ -1,4 +1,5 @@
 use crate::newtypes::DbUrl;
+use activitypub_federation::{core::object_id::ObjectId, traits::ApubObject};
 use chrono::NaiveDateTime;
 use diesel::{
   backend::Backend,
@@ -8,8 +9,7 @@ use diesel::{
   Connection,
   PgConnection,
 };
-use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use once_cell::sync::Lazy;
 use regex::Regex;
 use std::{env, env::VarError, io::Write};
index 878c68b9ac29ef686d66099c290b64011dd04e90..c0010187bbb4e312cf24eeeeeb38df9f6758c6c6 100644 (file)
@@ -19,7 +19,7 @@ use lemmy_db_views_actor::{
   person_mention_view::PersonMentionQueryBuilder,
   structs::PersonMentionView,
 };
-use lemmy_utils::{claims::Claims, utils::markdown_to_html, LemmyError};
+use lemmy_utils::{claims::Claims, error::LemmyError, utils::markdown_to_html};
 use lemmy_websocket::LemmyContext;
 use once_cell::sync::Lazy;
 use rss::{
index 6439c8b6ab62cfd380fd0ba07e030adc2b39ee35..23d2020b7023412cc8786da9fcfd3c07f0e43f64 100644 (file)
@@ -12,7 +12,7 @@ use actix_web::{
 };
 use anyhow::anyhow;
 use futures::stream::{Stream, StreamExt};
-use lemmy_utils::{claims::Claims, rate_limit::RateLimit, LemmyError, REQWEST_TIMEOUT};
+use lemmy_utils::{claims::Claims, error::LemmyError, rate_limit::RateLimit};
 use lemmy_websocket::LemmyContext;
 use reqwest::Body;
 use reqwest_middleware::{ClientWithMiddleware, RequestBuilder};
@@ -57,9 +57,7 @@ fn adapt_request(
   // remove accept-encoding header so that pictrs doesnt compress the response
   const INVALID_HEADERS: &[HeaderName] = &[ACCEPT_ENCODING, HOST];
 
-  let client_request = client
-    .request(request.method().clone(), url)
-    .timeout(REQWEST_TIMEOUT);
+  let client_request = client.request(request.method().clone(), url);
 
   request
     .headers()
index 6ca2114e4b8348ed88b5059ffb70b3505688cb64..1841b15917ab100bce1201e37d2a4f8dae3ff976 100644 (file)
@@ -2,7 +2,7 @@ use actix_web::{error::ErrorBadRequest, *};
 use anyhow::anyhow;
 use lemmy_api_common::utils::blocking;
 use lemmy_db_views::structs::SiteView;
-use lemmy_utils::{version, LemmyError};
+use lemmy_utils::{error::LemmyError, version};
 use lemmy_websocket::LemmyContext;
 use serde::{Deserialize, Serialize};
 use url::Url;
index 01ed2bc00a242082409041d8fd8a920cd34b9f04..f3856eb5df6f78500ad688d89d75f9f6e46e6560 100644 (file)
@@ -6,7 +6,7 @@ use lemmy_db_schema::{
   source::{community::Community, person::Person},
   traits::ApubActor,
 };
-use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
+use lemmy_utils::{error::LemmyError, location_info, settings::structs::Settings};
 use lemmy_websocket::LemmyContext;
 use serde::Deserialize;
 use url::Url;
index d49ecfa8df6fdcbb63b15faa1745b2bcde2e760f..77a720694924aedeaf5e94b7f0f44b880000d83a 100644 (file)
@@ -1,4 +1,4 @@
-use crate::LemmyError;
+use crate::error::LemmyError;
 use chrono::Utc;
 use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, TokenData, Validation};
 use serde::{Deserialize, Serialize};
index 13aff6985912dc68b138d4dd6a951e7609bed91f..0bc3d71d3455917bf21c62a76af28fa3a0feec3c 100644 (file)
@@ -1,4 +1,4 @@
-use crate::{settings::structs::Settings, LemmyError};
+use crate::{error::LemmyError, settings::structs::Settings};
 use html2text;
 use lettre::{
   message::{Mailbox, MultiPart},
diff --git a/crates/utils/src/error.rs b/crates/utils/src/error.rs
new file mode 100644 (file)
index 0000000..441c042
--- /dev/null
@@ -0,0 +1,115 @@
+use std::{
+  fmt,
+  fmt::{Debug, Display},
+};
+use tracing_error::SpanTrace;
+
+#[derive(serde::Serialize)]
+struct ApiError {
+  error: String,
+}
+
+pub struct LemmyError {
+  pub message: Option<String>,
+  pub inner: anyhow::Error,
+  pub context: SpanTrace,
+}
+
+impl LemmyError {
+  /// Create LemmyError from a message, including stack trace
+  pub fn from_message(message: &str) -> Self {
+    let inner = anyhow::anyhow!("{}", message);
+    LemmyError {
+      message: Some(message.into()),
+      inner,
+      context: SpanTrace::capture(),
+    }
+  }
+
+  /// Create a LemmyError from error and message, including stack trace
+  pub fn from_error_message<E>(error: E, message: &str) -> Self
+  where
+    E: Into<anyhow::Error>,
+  {
+    LemmyError {
+      message: Some(message.into()),
+      inner: error.into(),
+      context: SpanTrace::capture(),
+    }
+  }
+
+  /// Add message to existing LemmyError (or overwrite existing error)
+  pub fn with_message(self, message: &str) -> Self {
+    LemmyError {
+      message: Some(message.into()),
+      ..self
+    }
+  }
+
+  pub fn to_json(&self) -> Result<String, Self> {
+    let api_error = match &self.message {
+      Some(error) => ApiError {
+        error: error.into(),
+      },
+      None => ApiError {
+        error: "Unknown".into(),
+      },
+    };
+
+    Ok(serde_json::to_string(&api_error)?)
+  }
+}
+
+impl<T> From<T> for LemmyError
+where
+  T: Into<anyhow::Error>,
+{
+  fn from(t: T) -> Self {
+    LemmyError {
+      message: None,
+      inner: t.into(),
+      context: SpanTrace::capture(),
+    }
+  }
+}
+
+impl Debug for LemmyError {
+  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    f.debug_struct("LemmyError")
+      .field("message", &self.message)
+      .field("inner", &self.inner)
+      .field("context", &"SpanTrace")
+      .finish()
+  }
+}
+
+impl Display for LemmyError {
+  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    if let Some(message) = &self.message {
+      write!(f, "{}: ", message)?;
+    }
+    writeln!(f, "{}", self.inner)?;
+    fmt::Display::fmt(&self.context, f)
+  }
+}
+
+impl actix_web::error::ResponseError for LemmyError {
+  fn status_code(&self) -> http::StatusCode {
+    match self.inner.downcast_ref::<diesel::result::Error>() {
+      Some(diesel::result::Error::NotFound) => http::StatusCode::NOT_FOUND,
+      _ => http::StatusCode::BAD_REQUEST,
+    }
+  }
+
+  fn error_response(&self) -> actix_web::HttpResponse {
+    if let Some(message) = &self.message {
+      actix_web::HttpResponse::build(self.status_code()).json(ApiError {
+        error: message.into(),
+      })
+    } else {
+      actix_web::HttpResponse::build(self.status_code())
+        .content_type("text/plain")
+        .body(self.inner.to_string())
+    }
+  }
+}
index b8e301bd906fc6342e1e568f67b2307f64e4eae3..beaf173ba3c6294b4fb9580355463776b58de785 100644 (file)
@@ -9,16 +9,14 @@ pub mod rate_limit;
 pub mod settings;
 
 pub mod claims;
+pub mod error;
 pub mod request;
 #[cfg(test)]
 mod test;
 pub mod utils;
 pub mod version;
 
-use actix_web::HttpResponse;
-use http::StatusCode;
-use std::{fmt, fmt::Display, time::Duration};
-use tracing_error::SpanTrace;
+use std::{fmt, time::Duration};
 
 pub type ConnectionId = usize;
 
@@ -44,113 +42,3 @@ macro_rules! location_info {
     )
   };
 }
-
-#[derive(serde::Serialize)]
-struct ApiError {
-  error: String,
-}
-
-pub struct LemmyError {
-  pub message: Option<String>,
-  pub inner: anyhow::Error,
-  pub context: SpanTrace,
-}
-
-impl LemmyError {
-  /// Create LemmyError from a message, including stack trace
-  pub fn from_message(message: &str) -> Self {
-    let inner = anyhow::anyhow!("{}", message);
-    LemmyError {
-      message: Some(message.into()),
-      inner,
-      context: SpanTrace::capture(),
-    }
-  }
-
-  /// Create a LemmyError from error and message, including stack trace
-  pub fn from_error_message<E>(error: E, message: &str) -> Self
-  where
-    E: Into<anyhow::Error>,
-  {
-    LemmyError {
-      message: Some(message.into()),
-      inner: error.into(),
-      context: SpanTrace::capture(),
-    }
-  }
-
-  /// Add message to existing LemmyError (or overwrite existing error)
-  pub fn with_message(self, message: &str) -> Self {
-    LemmyError {
-      message: Some(message.into()),
-      ..self
-    }
-  }
-
-  pub fn to_json(&self) -> Result<String, Self> {
-    let api_error = match &self.message {
-      Some(error) => ApiError {
-        error: error.into(),
-      },
-      None => ApiError {
-        error: "Unknown".into(),
-      },
-    };
-
-    Ok(serde_json::to_string(&api_error)?)
-  }
-}
-
-impl<T> From<T> for LemmyError
-where
-  T: Into<anyhow::Error>,
-{
-  fn from(t: T) -> Self {
-    LemmyError {
-      message: None,
-      inner: t.into(),
-      context: SpanTrace::capture(),
-    }
-  }
-}
-
-impl std::fmt::Debug for LemmyError {
-  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    f.debug_struct("LemmyError")
-      .field("message", &self.message)
-      .field("inner", &self.inner)
-      .field("context", &"SpanTrace")
-      .finish()
-  }
-}
-
-impl Display for LemmyError {
-  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-    if let Some(message) = &self.message {
-      write!(f, "{}: ", message)?;
-    }
-    writeln!(f, "{}", self.inner)?;
-    self.context.fmt(f)
-  }
-}
-
-impl actix_web::error::ResponseError for LemmyError {
-  fn status_code(&self) -> StatusCode {
-    match self.inner.downcast_ref::<diesel::result::Error>() {
-      Some(diesel::result::Error::NotFound) => StatusCode::NOT_FOUND,
-      _ => StatusCode::BAD_REQUEST,
-    }
-  }
-
-  fn error_response(&self) -> HttpResponse {
-    if let Some(message) = &self.message {
-      HttpResponse::build(self.status_code()).json(ApiError {
-        error: message.into(),
-      })
-    } else {
-      HttpResponse::build(self.status_code())
-        .content_type("text/plain")
-        .body(self.inner.to_string())
-    }
-  }
-}
index bf1a8984df2ab97111f244b4c81671ceab768838..50597f24449e889413bc399503a7c982065c5075 100644 (file)
@@ -1,4 +1,4 @@
-use crate::{location_info, settings::structs::Settings, LemmyError};
+use crate::{error::LemmyError, location_info, settings::structs::Settings};
 use anyhow::{anyhow, Context};
 use deser_hjson::from_str;
 use once_cell::sync::Lazy;
index f9c68f4ef6db08f36d2608655b2d36f02c08a557..a7c42cca81c0bf3f62c9e89bd815c7efeda4c4e5 100644 (file)
@@ -1,4 +1,4 @@
-use crate::{IpAddr, LemmyError};
+use crate::{error::LemmyError, IpAddr};
 use actix_web::dev::ConnectionInfo;
 use chrono::{DateTime, FixedOffset, NaiveDateTime};
 use itertools::Itertools;
index 4328d2d39635472eded929c8ffc75cdd7dbe61ae..2337cae321baa1498456fd7e90d4e6e533c0d2de 100644 (file)
@@ -8,7 +8,6 @@ use crate::{
 };
 use actix::prelude::*;
 use anyhow::Context as acontext;
-use background_jobs::QueueHandle;
 use diesel::{
   r2d2::{ConnectionManager, Pool},
   PgConnection,
@@ -19,12 +18,12 @@ use lemmy_db_schema::{
   source::secret::Secret,
 };
 use lemmy_utils::{
+  error::LemmyError,
   location_info,
   rate_limit::RateLimit,
   settings::structs::Settings,
   ConnectionId,
   IpAddr,
-  LemmyError,
 };
 use rand::rngs::ThreadRng;
 use reqwest_middleware::ClientWithMiddleware;
@@ -91,8 +90,6 @@ pub struct ChatServer {
 
   /// An HTTP Client
   client: ClientWithMiddleware,
-
-  activity_queue: QueueHandle,
 }
 
 pub struct SessionInfo {
@@ -111,7 +108,6 @@ impl ChatServer {
     message_handler: MessageHandlerType,
     message_handler_crud: MessageHandlerCrudType,
     client: ClientWithMiddleware,
-    activity_queue: QueueHandle,
     settings: Settings,
     secret: Secret,
   ) -> ChatServer {
@@ -128,7 +124,6 @@ impl ChatServer {
       message_handler,
       message_handler_crud,
       client,
-      activity_queue,
       settings,
       secret,
     }
@@ -465,7 +460,6 @@ impl ChatServer {
       pool: self.pool.clone(),
       chat_server: ctx.address(),
       client: self.client.to_owned(),
-      activity_queue: self.activity_queue.to_owned(),
       settings: self.settings.to_owned(),
       secret: self.secret.to_owned(),
     };
index 12f9783abc29350ee8ffb2eea026d41fa871dc63..2a7d1e8f49a554d1f45bb253807c7de3ea4da549 100644 (file)
@@ -3,9 +3,8 @@ extern crate strum_macros;
 
 use crate::chat_server::ChatServer;
 use actix::Addr;
-use background_jobs::QueueHandle;
 use lemmy_db_schema::{source::secret::Secret, utils::DbPool};
-use lemmy_utils::{settings::structs::Settings, LemmyError};
+use lemmy_utils::{error::LemmyError, settings::structs::Settings};
 use reqwest_middleware::ClientWithMiddleware;
 use serde::Serialize;
 
@@ -19,7 +18,6 @@ pub struct LemmyContext {
   pool: DbPool,
   chat_server: Addr<ChatServer>,
   client: ClientWithMiddleware,
-  activity_queue: QueueHandle,
   settings: Settings,
   secret: Secret,
 }
@@ -29,7 +27,6 @@ impl LemmyContext {
     pool: DbPool,
     chat_server: Addr<ChatServer>,
     client: ClientWithMiddleware,
-    activity_queue: QueueHandle,
     settings: Settings,
     secret: Secret,
   ) -> LemmyContext {
@@ -37,7 +34,6 @@ impl LemmyContext {
       pool,
       chat_server,
       client,
-      activity_queue,
       settings,
       secret,
     }
@@ -51,9 +47,6 @@ impl LemmyContext {
   pub fn client(&self) -> &ClientWithMiddleware {
     &self.client
   }
-  pub fn activity_queue(&self) -> &QueueHandle {
-    &self.activity_queue
-  }
   pub fn settings(&self) -> Settings {
     // TODO hacky solution to be able to hotload the settings.
     Settings::get()
@@ -69,7 +62,6 @@ impl Clone for LemmyContext {
       pool: self.pool.clone(),
       chat_server: self.chat_server.clone(),
       client: self.client.clone(),
-      activity_queue: self.activity_queue.clone(),
       settings: self.settings.clone(),
       secret: self.secret.clone(),
     }
index 3b160e675f51964122f2922ab8fe0eb565881af1..2e3cf0597c54daa6e3a7de0e15f0f0662239ea43 100644 (file)
@@ -22,7 +22,7 @@ use lemmy_db_schema::{
 };
 use lemmy_db_views::structs::{CommentView, LocalUserView, PostView, PrivateMessageView};
 use lemmy_db_views_actor::structs::CommunityView;
-use lemmy_utils::{utils::MentionData, ConnectionId, LemmyError};
+use lemmy_utils::{error::LemmyError, utils::MentionData, ConnectionId};
 
 #[tracing::instrument(skip_all)]
 pub async fn send_post_ws_message<OP: ToString + Send + OperationType + 'static>(
index 5a0b9eb6decf2539fe867e1a547e393bb3902ee4..de681631542878d2e1e28f55267022d32b85bd4b 100644 (file)
@@ -1,4 +1,5 @@
 // This is for db migrations that require code
+use activitypub_federation::core::signatures::generate_actor_keypair;
 use diesel::{
   sql_types::{Nullable, Text},
   *,
@@ -23,7 +24,7 @@ use lemmy_db_schema::{
   traits::Crud,
   utils::naive_now,
 };
-use lemmy_utils::{apub::generate_actor_keypair, LemmyError};
+use lemmy_utils::error::LemmyError;
 use tracing::info;
 use url::Url;
 
index 1280934c936ced11f7e20441c169e2b2ae257c47..b0bbd4bb036e38bc68a83ae7aab91f54b99acf27 100644 (file)
@@ -6,7 +6,7 @@ pub mod scheduled_tasks;
 #[cfg(feature = "console")]
 pub mod telemetry;
 
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use tracing::subscriber::set_global_default;
 use tracing_error::ErrorLayer;
 use tracing_log::LogTracer;
index be7d028cd2ffd46c42791c053b3d19fb1b708a7b..7f5946f5d3e788ebd8ebeae72f0bedf1664dbbcb 100644 (file)
@@ -14,7 +14,6 @@ use lemmy_api_common::{
   utils::{blocking, check_private_instance_and_federation_enabled},
 };
 use lemmy_api_crud::match_websocket_operation_crud;
-use lemmy_apub_lib::activity_queue::create_activity_queue;
 use lemmy_db_schema::{source::secret::Secret, utils::get_database_url_from_env};
 use lemmy_routes::{feeds, images, nodeinfo, webfinger};
 use lemmy_server::{
@@ -25,21 +24,24 @@ use lemmy_server::{
   scheduled_tasks,
 };
 use lemmy_utils::{
+  error::LemmyError,
   rate_limit::{rate_limiter::RateLimiter, RateLimit},
   settings::structs::Settings,
-  LemmyError,
-  REQWEST_TIMEOUT,
 };
 use lemmy_websocket::{chat_server::ChatServer, LemmyContext};
 use parking_lot::Mutex;
 use reqwest::Client;
 use reqwest_middleware::ClientBuilder;
+use reqwest_retry::{policies::ExponentialBackoff, RetryTransientMiddleware};
 use reqwest_tracing::TracingMiddleware;
-use std::{env, sync::Arc, thread};
+use std::{env, sync::Arc, thread, time::Duration};
 use tracing_actix_web::TracingLogger;
 
 embed_migrations!();
 
+/// Max timeout for http requests
+pub const REQWEST_TIMEOUT: Duration = Duration::from_secs(10);
+
 #[actix_web::main]
 async fn main() -> Result<(), LemmyError> {
   let args: Vec<String> = env::args().collect();
@@ -102,11 +104,17 @@ async fn main() -> Result<(), LemmyError> {
     .timeout(REQWEST_TIMEOUT)
     .build()?;
 
-  let client = ClientBuilder::new(client).with(TracingMiddleware).build();
-
-  let queue_manager = create_activity_queue(client.clone(), settings.federation.worker_count);
+  let retry_policy = ExponentialBackoff {
+    max_n_retries: 3,
+    max_retry_interval: REQWEST_TIMEOUT,
+    min_retry_interval: Duration::from_millis(100),
+    backoff_exponent: 2,
+  };
 
-  let activity_queue = queue_manager.queue_handle().clone();
+  let client = ClientBuilder::new(client)
+    .with(TracingMiddleware)
+    .with(RetryTransientMiddleware::new_with_policy(retry_policy))
+    .build();
 
   check_private_instance_and_federation_enabled(&pool, &settings).await?;
 
@@ -116,7 +124,6 @@ async fn main() -> Result<(), LemmyError> {
     |c, i, o, d| Box::pin(match_websocket_operation(c, i, o, d)),
     |c, i, o, d| Box::pin(match_websocket_operation_crud(c, i, o, d)),
     client.clone(),
-    activity_queue.clone(),
     settings.clone(),
     secret.clone(),
   )
@@ -129,7 +136,6 @@ async fn main() -> Result<(), LemmyError> {
       pool.clone(),
       chat_server.to_owned(),
       client.clone(),
-      activity_queue.to_owned(),
       settings.to_owned(),
       secret.to_owned(),
     );
@@ -151,7 +157,5 @@ async fn main() -> Result<(), LemmyError> {
   .run()
   .await?;
 
-  drop(queue_manager);
-
   Ok(())
 }
index 32bfd5e8caf4bce452635682438853f463714d28..5b1ae419bc11f0918878fd08b368761011da0069 100644 (file)
@@ -3,7 +3,7 @@ use clokwerk::{Scheduler, TimeUnits};
 // Import week days and WeekDay
 use diesel::{sql_query, PgConnection, RunQueryDsl};
 use lemmy_db_schema::{source::activity::Activity, utils::DbPool};
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use std::{thread, time::Duration};
 use tracing::info;
 
index 9f8c9f3b4afa1a07e2fccc7755fbd671a44afa5f..2f758e0628dcb988ce4b3a749bcb14ab0808ab44 100644 (file)
@@ -1,5 +1,5 @@
 use console_subscriber::ConsoleLayer;
-use lemmy_utils::LemmyError;
+use lemmy_utils::error::LemmyError;
 use opentelemetry::{
   sdk::{propagation::TraceContextPropagator, Resource},
   KeyValue,