diff --git a/Cargo.lock b/Cargo.lock index d03721847..887fae193 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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.90", + "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.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", ] diff --git a/Cargo.toml b/Cargo.toml index f4eceaf34..f74a0ba35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 } diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 314f18ecc..6de268542 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -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. diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index b2f12298c..023309b4f 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -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(); diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index b81ea8e32..0ef120e67 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -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 } diff --git a/crates/api/src/comment/like.rs b/crates/api/src/comment/like.rs index cc97ebc48..48302ac65 100644 --- a/crates/api/src/comment/like.rs +++ b/crates/api/src/comment/like.rs @@ -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; diff --git a/crates/api/src/comment/mark_as_read.rs b/crates/api/src/comment/mark_as_read.rs index a0dc6dd74..85881f1ca 100644 --- a/crates/api/src/comment/mark_as_read.rs +++ b/crates/api/src/comment/mark_as_read.rs @@ -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)] diff --git a/crates/api/src/comment/save.rs b/crates/api/src/comment/save.rs index 1ece524a8..4d599739a 100644 --- a/crates/api/src/comment/save.rs +++ b/crates/api/src/comment/save.rs @@ -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)] diff --git a/crates/api/src/comment_report/create.rs b/crates/api/src/comment_report/create.rs index 75e1323ab..6a1c2287e 100644 --- a/crates/api/src/comment_report/create.rs +++ b/crates/api/src/comment_report/create.rs @@ -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 diff --git a/crates/api/src/comment_report/list.rs b/crates/api/src/comment_report/list.rs index 296cb8322..c86784255 100644 --- a/crates/api/src/comment_report/list.rs +++ b/crates/api/src/comment_report/list.rs @@ -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 diff --git a/crates/api/src/comment_report/resolve.rs b/crates/api/src/comment_report/resolve.rs index 95481ace7..2c016b95e 100644 --- a/crates/api/src/comment_report/resolve.rs +++ b/crates/api/src/comment_report/resolve.rs @@ -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 diff --git a/crates/api/src/community/add_mod.rs b/crates/api/src/community/add_mod.rs index 9ea9361a9..b8999e4b7 100644 --- a/crates/api/src/community/add_mod.rs +++ b/crates/api/src/community/add_mod.rs @@ -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)] diff --git a/crates/api/src/community/ban.rs b/crates/api/src/community/ban.rs index 60fd32270..07e287835 100644 --- a/crates/api/src/community/ban.rs +++ b/crates/api/src/community/ban.rs @@ -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)] diff --git a/crates/api/src/community/block.rs b/crates/api/src/community/block.rs index 4f740c916..2f5f5f904 100644 --- a/crates/api/src/community/block.rs +++ b/crates/api/src/community/block.rs @@ -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)] diff --git a/crates/api/src/community/follow.rs b/crates/api/src/community/follow.rs index aab21a9c2..53da4f2ef 100644 --- a/crates/api/src/community/follow.rs +++ b/crates/api/src/community/follow.rs @@ -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)] diff --git a/crates/api/src/community/hide.rs b/crates/api/src/community/hide.rs index ddf4f49a1..6a562f1c0 100644 --- a/crates/api/src/community/hide.rs +++ b/crates/api/src/community/hide.rs @@ -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)] diff --git a/crates/api/src/community/transfer.rs b/crates/api/src/community/transfer.rs index 9d8044e3d..fe34bbfa4 100644 --- a/crates/api/src/community/transfer.rs +++ b/crates/api/src/community/transfer.rs @@ -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 diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 0c36890bc..6e2bb4f0e 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -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; diff --git a/crates/api/src/local_user/add_admin.rs b/crates/api/src/local_user/add_admin.rs index 3834dbbef..b44b210b7 100644 --- a/crates/api/src/local_user/add_admin.rs +++ b/crates/api/src/local_user/add_admin.rs @@ -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)] diff --git a/crates/api/src/local_user/ban_person.rs b/crates/api/src/local_user/ban_person.rs index d357e8eb9..6de826dca 100644 --- a/crates/api/src/local_user/ban_person.rs +++ b/crates/api/src/local_user/ban_person.rs @@ -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)] diff --git a/crates/api/src/local_user/block.rs b/crates/api/src/local_user/block.rs index d0812fd97..4878cb020 100644 --- a/crates/api/src/local_user/block.rs +++ b/crates/api/src/local_user/block.rs @@ -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)] diff --git a/crates/api/src/local_user/change_password.rs b/crates/api/src/local_user/change_password.rs index 714659980..6143fc4fa 100644 --- a/crates/api/src/local_user/change_password.rs +++ b/crates/api/src/local_user/change_password.rs @@ -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)] diff --git a/crates/api/src/local_user/change_password_after_reset.rs b/crates/api/src/local_user/change_password_after_reset.rs index 92e4f6ba5..cc4c7400e 100644 --- a/crates/api/src/local_user/change_password_after_reset.rs +++ b/crates/api/src/local_user/change_password_after_reset.rs @@ -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)] diff --git a/crates/api/src/local_user/get_captcha.rs b/crates/api/src/local_user/get_captcha.rs index 5c691b8ca..2740036c7 100644 --- a/crates/api/src/local_user/get_captcha.rs +++ b/crates/api/src/local_user/get_captcha.rs @@ -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)] diff --git a/crates/api/src/local_user/list_banned.rs b/crates/api/src/local_user/list_banned.rs index 4c39d0cd2..5423bdbe9 100644 --- a/crates/api/src/local_user/list_banned.rs +++ b/crates/api/src/local_user/list_banned.rs @@ -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)] diff --git a/crates/api/src/local_user/login.rs b/crates/api/src/local_user/login.rs index e1931d5a4..cd17d61ab 100644 --- a/crates/api/src/local_user/login.rs +++ b/crates/api/src/local_user/login.rs @@ -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)] diff --git a/crates/api/src/local_user/notifications/list_mentions.rs b/crates/api/src/local_user/notifications/list_mentions.rs index 6e7868410..048bef959 100644 --- a/crates/api/src/local_user/notifications/list_mentions.rs +++ b/crates/api/src/local_user/notifications/list_mentions.rs @@ -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)] diff --git a/crates/api/src/local_user/notifications/list_replies.rs b/crates/api/src/local_user/notifications/list_replies.rs index 643a1c9a8..ba7cbb8e9 100644 --- a/crates/api/src/local_user/notifications/list_replies.rs +++ b/crates/api/src/local_user/notifications/list_replies.rs @@ -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)] diff --git a/crates/api/src/local_user/notifications/mark_all_read.rs b/crates/api/src/local_user/notifications/mark_all_read.rs index d5caa02d5..3925e7913 100644 --- a/crates/api/src/local_user/notifications/mark_all_read.rs +++ b/crates/api/src/local_user/notifications/mark_all_read.rs @@ -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)] diff --git a/crates/api/src/local_user/notifications/mark_mention_read.rs b/crates/api/src/local_user/notifications/mark_mention_read.rs index 4c9d06014..b097ddc41 100644 --- a/crates/api/src/local_user/notifications/mark_mention_read.rs +++ b/crates/api/src/local_user/notifications/mark_mention_read.rs @@ -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)] diff --git a/crates/api/src/local_user/notifications/unread_count.rs b/crates/api/src/local_user/notifications/unread_count.rs index a9c06ffc7..cdab17bde 100644 --- a/crates/api/src/local_user/notifications/unread_count.rs +++ b/crates/api/src/local_user/notifications/unread_count.rs @@ -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)] diff --git a/crates/api/src/local_user/report_count.rs b/crates/api/src/local_user/report_count.rs index a07f8c055..774b2fbbd 100644 --- a/crates/api/src/local_user/report_count.rs +++ b/crates/api/src/local_user/report_count.rs @@ -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)] diff --git a/crates/api/src/local_user/reset_password.rs b/crates/api/src/local_user/reset_password.rs index 6903a8b8e..98112b70b 100644 --- a/crates/api/src/local_user/reset_password.rs +++ b/crates/api/src/local_user/reset_password.rs @@ -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)] diff --git a/crates/api/src/local_user/save_settings.rs b/crates/api/src/local_user/save_settings.rs index 5e37470a9..eba76907e 100644 --- a/crates/api/src/local_user/save_settings.rs +++ b/crates/api/src/local_user/save_settings.rs @@ -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; diff --git a/crates/api/src/local_user/verify_email.rs b/crates/api/src/local_user/verify_email.rs index c4af8e34e..7f1797262 100644 --- a/crates/api/src/local_user/verify_email.rs +++ b/crates/api/src/local_user/verify_email.rs @@ -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)] diff --git a/crates/api/src/post/get_link_metadata.rs b/crates/api/src/post/get_link_metadata.rs index db1213324..54e2cfe7c 100644 --- a/crates/api/src/post/get_link_metadata.rs +++ b/crates/api/src/post/get_link_metadata.rs @@ -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)] diff --git a/crates/api/src/post/like.rs b/crates/api/src/post/like.rs index 24d9337c2..519722560 100644 --- a/crates/api/src/post/like.rs +++ b/crates/api/src/post/like.rs @@ -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)] diff --git a/crates/api/src/post/lock.rs b/crates/api/src/post/lock.rs index 965e506fc..1e11117f2 100644 --- a/crates/api/src/post/lock.rs +++ b/crates/api/src/post/lock.rs @@ -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)] diff --git a/crates/api/src/post/mark_read.rs b/crates/api/src/post/mark_read.rs index 8777ebced..07659ea83 100644 --- a/crates/api/src/post/mark_read.rs +++ b/crates/api/src/post/mark_read.rs @@ -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)] diff --git a/crates/api/src/post/save.rs b/crates/api/src/post/save.rs index 09baec988..25bb6c3ce 100644 --- a/crates/api/src/post/save.rs +++ b/crates/api/src/post/save.rs @@ -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)] diff --git a/crates/api/src/post/sticky.rs b/crates/api/src/post/sticky.rs index dffe67e33..952eed6f7 100644 --- a/crates/api/src/post/sticky.rs +++ b/crates/api/src/post/sticky.rs @@ -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)] diff --git a/crates/api/src/post_report/create.rs b/crates/api/src/post_report/create.rs index a960e2c53..28915f01a 100644 --- a/crates/api/src/post_report/create.rs +++ b/crates/api/src/post_report/create.rs @@ -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 diff --git a/crates/api/src/post_report/list.rs b/crates/api/src/post_report/list.rs index 7ae0a5ee9..71cde96aa 100644 --- a/crates/api/src/post_report/list.rs +++ b/crates/api/src/post_report/list.rs @@ -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 diff --git a/crates/api/src/post_report/resolve.rs b/crates/api/src/post_report/resolve.rs index 0b50999d2..469f96b35 100644 --- a/crates/api/src/post_report/resolve.rs +++ b/crates/api/src/post_report/resolve.rs @@ -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 diff --git a/crates/api/src/private_message/mark_read.rs b/crates/api/src/private_message/mark_read.rs index 578967836..fa2506010 100644 --- a/crates/api/src/private_message/mark_read.rs +++ b/crates/api/src/private_message/mark_read.rs @@ -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)] diff --git a/crates/api/src/site/config/read.rs b/crates/api/src/site/config/read.rs index 8626fd5f4..4f82e1255 100644 --- a/crates/api/src/site/config/read.rs +++ b/crates/api/src/site/config/read.rs @@ -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)] diff --git a/crates/api/src/site/config/update.rs b/crates/api/src/site/config/update.rs index 98f2b1f34..4d4f064e2 100644 --- a/crates/api/src/site/config/update.rs +++ b/crates/api/src/site/config/update.rs @@ -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)] diff --git a/crates/api/src/site/leave_admin.rs b/crates/api/src/site/leave_admin.rs index 10a3adc47..55b49fc7d 100644 --- a/crates/api/src/site/leave_admin.rs +++ b/crates/api/src/site/leave_admin.rs @@ -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)] diff --git a/crates/api/src/site/mod_log.rs b/crates/api/src/site/mod_log.rs index 45335d5d3..acb5e827e 100644 --- a/crates/api/src/site/mod_log.rs +++ b/crates/api/src/site/mod_log.rs @@ -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)] diff --git a/crates/api/src/site/registration_applications/approve.rs b/crates/api/src/site/registration_applications/approve.rs index 2e3577de0..04000b63a 100644 --- a/crates/api/src/site/registration_applications/approve.rs +++ b/crates/api/src/site/registration_applications/approve.rs @@ -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)] diff --git a/crates/api/src/site/registration_applications/list.rs b/crates/api/src/site/registration_applications/list.rs index 27633aa64..60dfd446d 100644 --- a/crates/api/src/site/registration_applications/list.rs +++ b/crates/api/src/site/registration_applications/list.rs @@ -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. diff --git a/crates/api/src/site/registration_applications/unread_count.rs b/crates/api/src/site/registration_applications/unread_count.rs index 06f995234..fbaecf40f 100644 --- a/crates/api/src/site/registration_applications/unread_count.rs +++ b/crates/api/src/site/registration_applications/unread_count.rs @@ -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)] diff --git a/crates/api/src/site/resolve_object.rs b/crates/api/src/site/resolve_object.rs index 4e84e162f..1048101d6 100644 --- a/crates/api/src/site/resolve_object.rs +++ b/crates/api/src/site/resolve_object.rs @@ -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)] diff --git a/crates/api/src/site/search.rs b/crates/api/src/site/search.rs index 5e1474238..fef467000 100644 --- a/crates/api/src/site/search.rs +++ b/crates/api/src/site/search.rs @@ -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)] diff --git a/crates/api/src/websocket.rs b/crates/api/src/websocket.rs index aea443a96..13319dc23 100644 --- a/crates/api/src/websocket.rs +++ b/crates/api/src/websocket.rs @@ -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, diff --git a/crates/api_common/src/request.rs b/crates/api_common/src/request.rs index fa48e8703..c5f750115 100644 --- a/crates/api_common/src/request.rs +++ b/crates/api_common/src/request.rs @@ -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 { 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") diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index 94a9c3318..f8a25251f 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -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; diff --git a/crates/api_crud/Cargo.toml b/crates/api_crud/Cargo.toml index 595dba25e..e61a37f77 100644 --- a/crates/api_crud/Cargo.toml +++ b/crates/api_crud/Cargo.toml @@ -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"] } diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 12e208e8c..f550c0535 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -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}, diff --git a/crates/api_crud/src/comment/delete.rs b/crates/api_crud/src/comment/delete.rs index f4fb5d405..a674ed2c3 100644 --- a/crates/api_crud/src/comment/delete.rs +++ b/crates/api_crud/src/comment/delete.rs @@ -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, diff --git a/crates/api_crud/src/comment/list.rs b/crates/api_crud/src/comment/list.rs index f9c37de48..6b949ab6a 100644 --- a/crates/api_crud/src/comment/list.rs +++ b/crates/api_crud/src/comment/list.rs @@ -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)] diff --git a/crates/api_crud/src/comment/read.rs b/crates/api_crud/src/comment/read.rs index fd248cafe..f5013c988 100644 --- a/crates/api_crud/src/comment/read.rs +++ b/crates/api_crud/src/comment/read.rs @@ -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)] diff --git a/crates/api_crud/src/comment/remove.rs b/crates/api_crud/src/comment/remove.rs index 837407c56..fe664d80f 100644 --- a/crates/api_crud/src/comment/remove.rs +++ b/crates/api_crud/src/comment/remove.rs @@ -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, diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs index 06065c89a..2a769277a 100644 --- a/crates/api_crud/src/comment/update.rs +++ b/crates/api_crud/src/comment/update.rs @@ -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}, diff --git a/crates/api_crud/src/community/create.rs b/crates/api_crud/src/community/create.rs index a7582d2ec..1181afc39 100644 --- a/crates/api_crud/src/community/create.rs +++ b/crates/api_crud/src/community/create.rs @@ -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::::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::(context) + .await; if community_dupe.is_ok() { return Err(LemmyError::from_message("community_already_exists")); } diff --git a/crates/api_crud/src/community/delete.rs b/crates/api_crud/src/community/delete.rs index f42e9b01d..441f45811 100644 --- a/crates/api_crud/src/community/delete.rs +++ b/crates/api_crud/src/community/delete.rs @@ -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)] diff --git a/crates/api_crud/src/community/list.rs b/crates/api_crud/src/community/list.rs index af41b83e2..7afb61783 100644 --- a/crates/api_crud/src/community/list.rs +++ b/crates/api_crud/src/community/list.rs @@ -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)] diff --git a/crates/api_crud/src/community/read.rs b/crates/api_crud/src/community/read.rs index 16eee4692..8b9c1bdb5 100644 --- a/crates/api_crud/src/community/read.rs +++ b/crates/api_crud/src/community/read.rs @@ -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)] diff --git a/crates/api_crud/src/community/remove.rs b/crates/api_crud/src/community/remove.rs index 7ca9b73fa..5895a6cbc 100644 --- a/crates/api_crud/src/community/remove.rs +++ b/crates/api_crud/src/community/remove.rs @@ -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)] diff --git a/crates/api_crud/src/community/update.rs b/crates/api_crud/src/community/update.rs index d933c9d88..d8aaef0e5 100644 --- a/crates/api_crud/src/community/update.rs +++ b/crates/api_crud/src/community/update.rs @@ -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)] diff --git a/crates/api_crud/src/lib.rs b/crates/api_crud/src/lib.rs index 9f1553ee1..e29c8fa4f 100644 --- a/crates/api_crud/src/lib.rs +++ b/crates/api_crud/src/lib.rs @@ -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; diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 353e186ad..6ef706d0a 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -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}; diff --git a/crates/api_crud/src/post/delete.rs b/crates/api_crud/src/post/delete.rs index f880b4b5d..734a02461 100644 --- a/crates/api_crud/src/post/delete.rs +++ b/crates/api_crud/src/post/delete.rs @@ -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)] diff --git a/crates/api_crud/src/post/list.rs b/crates/api_crud/src/post/list.rs index 574efeba8..90806cf20 100644 --- a/crates/api_crud/src/post/list.rs +++ b/crates/api_crud/src/post/list.rs @@ -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; diff --git a/crates/api_crud/src/post/read.rs b/crates/api_crud/src/post/read.rs index a5ca262fa..36a0b290b 100644 --- a/crates/api_crud/src/post/read.rs +++ b/crates/api_crud/src/post/read.rs @@ -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)] diff --git a/crates/api_crud/src/post/remove.rs b/crates/api_crud/src/post/remove.rs index 7e50159c9..9ba29158b 100644 --- a/crates/api_crud/src/post/remove.rs +++ b/crates/api_crud/src/post/remove.rs @@ -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)] diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index 16f2fea40..285a08b55 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -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}; diff --git a/crates/api_crud/src/private_message/create.rs b/crates/api_crud/src/private_message/create.rs index 894c178b5..a368e3a53 100644 --- a/crates/api_crud/src/private_message/create.rs +++ b/crates/api_crud/src/private_message/create.rs @@ -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)] diff --git a/crates/api_crud/src/private_message/delete.rs b/crates/api_crud/src/private_message/delete.rs index af06094eb..ef200f485 100644 --- a/crates/api_crud/src/private_message/delete.rs +++ b/crates/api_crud/src/private_message/delete.rs @@ -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)] diff --git a/crates/api_crud/src/private_message/read.rs b/crates/api_crud/src/private_message/read.rs index ce03200c6..bb09be2dc 100644 --- a/crates/api_crud/src/private_message/read.rs +++ b/crates/api_crud/src/private_message/read.rs @@ -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)] diff --git a/crates/api_crud/src/private_message/update.rs b/crates/api_crud/src/private_message/update.rs index aebd5b8be..2c4cba5e1 100644 --- a/crates/api_crud/src/private_message/update.rs +++ b/crates/api_crud/src/private_message/update.rs @@ -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)] diff --git a/crates/api_crud/src/site/create.rs b/crates/api_crud/src/site/create.rs index 49550d668..57301e108 100644 --- a/crates/api_crud/src/site/create.rs +++ b/crates/api_crud/src/site/create.rs @@ -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; diff --git a/crates/api_crud/src/site/read.rs b/crates/api_crud/src/site/read.rs index f9fe75c73..808dcf7d9 100644 --- a/crates/api_crud/src/site/read.rs +++ b/crates/api_crud/src/site/read.rs @@ -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; diff --git a/crates/api_crud/src/site/update.rs b/crates/api_crud/src/site/update.rs index ba0930541..6e88e42ec 100644 --- a/crates/api_crud/src/site/update.rs +++ b/crates/api_crud/src/site/update.rs @@ -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}; diff --git a/crates/api_crud/src/user/create.rs b/crates/api_crud/src/user/create.rs index 456617043..44e5b8820 100644 --- a/crates/api_crud/src/user/create.rs +++ b/crates/api_crud/src/user/create.rs @@ -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}; diff --git a/crates/api_crud/src/user/delete.rs b/crates/api_crud/src/user/delete.rs index c5e0e2197..bde403a56 100644 --- a/crates/api_crud/src/user/delete.rs +++ b/crates/api_crud/src/user/delete.rs @@ -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)] diff --git a/crates/api_crud/src/user/read.rs b/crates/api_crud/src/user/read.rs index e00f60275..ecfd45e09 100644 --- a/crates/api_crud/src/user/read.rs +++ b/crates/api_crud/src/user/read.rs @@ -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)] diff --git a/crates/apub/Cargo.toml b/crates/apub/Cargo.toml index c584610bd..f8320c280 100644 --- a/crates/apub/Cargo.toml +++ b/crates/apub/Cargo.toml @@ -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 } diff --git a/crates/apub/assets/lemmy/activities/community/report_page.json b/crates/apub/assets/lemmy/activities/community/report_page.json index bd1691b57..724beb43a 100644 --- a/crates/apub/assets/lemmy/activities/community/report_page.json +++ b/crates/apub/assets/lemmy/activities/community/report_page.json @@ -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", diff --git a/crates/apub/assets/lemmy/activities/create_or_update/create_private_message.json b/crates/apub/assets/lemmy/activities/create_or_update/create_private_message.json index de080a8f9..85291bc06 100644 --- a/crates/apub/assets/lemmy/activities/create_or_update/create_private_message.json +++ b/crates/apub/assets/lemmy/activities/create_or_update/create_private_message.json @@ -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": { diff --git a/crates/apub/assets/lemmy/objects/chat_message.json b/crates/apub/assets/lemmy/objects/chat_message.json index c639aef92..e21312fc6 100644 --- a/crates/apub/assets/lemmy/objects/chat_message.json +++ b/crates/apub/assets/lemmy/objects/chat_message.json @@ -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": "

Hello hello, testing

\n", "mediaType": "text/html", "source": { diff --git a/crates/apub/src/activities/block/block_user.rs b/crates/apub/src/activities/block/block_user.rs index bcab3148a..6e07fcd8c 100644 --- a/crates/apub/src/activities/block/block_user.rs +++ b/crates/apub/src/activities/block/block_user.rs @@ -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::(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::(context, local_instance(context), request_counter) .await?; let blocked_person = self .object - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await?; let target = self .target - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await?; match target { SiteOrCommunity::Site(_site) => { @@ -242,7 +252,7 @@ impl GetCommunity for BlockUser { ) -> Result { let target = self .target - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await?; match target { SiteOrCommunity::Community(c) => Ok(c), diff --git a/crates/apub/src/activities/block/mod.rs b/crates/apub/src/activities/block/mod.rs index bb35d7d21..dec16cf3d 100644 --- a/crates/apub/src/activities/block/mod.rs +++ b/crates/apub/src/activities/block/mod.rs @@ -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 { @@ -70,10 +68,6 @@ impl ApubObject for SiteOrCommunity { unimplemented!() } - fn to_tombstone(&self) -> Result { - unimplemented!() - } - #[tracing::instrument(skip_all)] async fn verify( apub: &Self::ApubType, diff --git a/crates/apub/src/activities/block/undo_block_user.rs b/crates/apub/src/activities/block/undo_block_user.rs index 130b1eb50..a68653038 100644 --- a/crates/apub/src/activities/block/undo_block_user.rs +++ b/crates/apub/src/activities/block/undo_block_user.rs @@ -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 activitypub_federation::{ + core::object_id::ObjectId, + data::Data, + traits::ActivityHandler, + utils::verify_domains_match, }; use activitystreams_kinds::{activity::UndoType, public}; use lemmy_api_common::utils::blocking; -use lemmy_apub_lib::{ - data::Data, - object_id::ObjectId, - traits::{ActivityHandler, ActorType}, - verify::verify_domains_match, -}; 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, 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::(context, instance, request_counter) .await?; let blocked_person = self .object .object - .dereference(context, context.client(), request_counter) + .dereference::(context, instance, request_counter) .await?; match self .object .target - .dereference(context, context.client(), request_counter) + .dereference::(context, instance, request_counter) .await? { SiteOrCommunity::Site(_site) => { diff --git a/crates/apub/src/activities/community/add_mod.rs b/crates/apub/src/activities/community/add_mod.rs index 2aa7989ee..58d1006c8 100644 --- a/crates/apub/src/activities/community/add_mod.rs +++ b/crates/apub/src/activities/community/add_mod.rs @@ -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::(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::(context, local_instance(context), request_counter) .await?; let form = ModAddCommunityForm { mod_person_id: actor.id, diff --git a/crates/apub/src/activities/community/announce.rs b/crates/apub/src/activities/community/announce.rs index a6612ca1c..a2e00c786 100644 --- a/crates/apub/src/activities/community/announce.rs +++ b/crates/apub/src/activities/community/announce.rs @@ -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, + _context: &Data, _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(()); } diff --git a/crates/apub/src/activities/community/mod.rs b/crates/apub/src/activities/community/mod.rs index d8d8097eb..fe2aaf784 100644 --- a/crates/apub/src/activities/community/mod.rs +++ b/crates/apub/src/activities/community/mod.rs @@ -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 { let community_id = Url::parse(&moderators.to_string().replace("/moderators", ""))?; ObjectId::new(community_id) - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await } diff --git a/crates/apub/src/activities/community/remove_mod.rs b/crates/apub/src/activities/community/remove_mod.rs index f42d47f63..6af0e722d 100644 --- a/crates/apub/src/activities/community/remove_mod.rs +++ b/crates/apub/src/activities/community/remove_mod.rs @@ -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::(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::(context, local_instance(context), request_counter) .await?; let form = ModAddCommunityForm { mod_person_id: actor.id, diff --git a/crates/apub/src/activities/community/report.rs b/crates/apub/src/activities/community/report.rs index 0069aa6e6..b3f129e37 100644 --- a/crates/apub/src/activities/community/report.rs +++ b/crates/apub/src/activities/community/report.rs @@ -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::(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, 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::(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::(context, local_instance(context), request_counter) .await?; match self .object - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await? { PostOrComment::Post(post) => { diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs index e6676b8bf..538838a23 100644 --- a/crates/apub/src/activities/community/update.rs +++ b/crates/apub/src/activities/community/update.rs @@ -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 activitypub_federation::{ + core::object_id::ObjectId, + data::Data, + traits::{ActivityHandler, ApubObject}, }; use activitystreams_kinds::{activity::UpdateType, public}; use lemmy_api_common::utils::blocking; -use lemmy_apub_lib::{ - data::Data, - object_id::ObjectId, - traits::{ActivityHandler, ActorType, ApubObject}, -}; 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 { let cid = ObjectId::new(self.object.id.clone()); cid - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await } } diff --git a/crates/apub/src/activities/create_or_update/comment.rs b/crates/apub/src/activities/create_or_update/comment.rs index c0e53a607..456cbb6b0 100644 --- a/crates/apub/src/activities/create_or_update/comment.rs +++ b/crates/apub/src/activities/create_or_update/comment.rs @@ -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 activitypub_federation::{ + core::object_id::ObjectId, + data::Data, + traits::{ActivityHandler, ApubObject}, + utils::verify_domains_match, }; use activitystreams_kinds::public; use lemmy_api_common::utils::{blocking, check_post_deleted_or_removed}; -use lemmy_apub_lib::{ - data::Data, - object_id::ObjectId, - traits::{ActivityHandler, ActorType, ApubObject}, - verify::verify_domains_match, -}; 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::(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)?; diff --git a/crates/apub/src/activities/create_or_update/mod.rs b/crates/apub/src/activities/create_or_update/mod.rs index 99305f24c..b0e0bf36a 100644 --- a/crates/apub/src/activities/create_or_update/mod.rs +++ b/crates/apub/src/activities/create_or_update/mod.rs @@ -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::(context, local_instance(context), request_counter) .await?; // Note: diff --git a/crates/apub/src/activities/create_or_update/post.rs b/crates/apub/src/activities/create_or_update/post.rs index 286001828..a0d8ce6f4 100644 --- a/crates/apub/src/activities/create_or_update/post.rs +++ b/crates/apub/src/activities/create_or_update/post.rs @@ -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 activitypub_federation::{ + core::object_id::ObjectId, + data::Data, + traits::{ActivityHandler, ApubObject}, + utils::{verify_domains_match, verify_urls_match}, }; use activitystreams_kinds::public; use lemmy_api_common::utils::blocking; -use lemmy_apub_lib::{ - data::Data, - object_id::ObjectId, - traits::{ActivityHandler, ActorType, ApubObject}, - verify::{verify_domains_match, verify_urls_match}, -}; 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)?; diff --git a/crates/apub/src/activities/create_or_update/private_message.rs b/crates/apub/src/activities/create_or_update/private_message.rs index 295e5b4f1..acd50a1aa 100644 --- a/crates/apub/src/activities/create_or_update/private_message.rs +++ b/crates/apub/src/activities/create_or_update/private_message.rs @@ -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 activitypub_federation::{ + core::object_id::ObjectId, + data::Data, + traits::{ActivityHandler, ApubObject}, + utils::verify_domains_match, }; use lemmy_api_common::utils::blocking; -use lemmy_apub_lib::{ - data::Data, - object_id::ObjectId, - traits::{ActivityHandler, ActorType, ApubObject}, - verify::verify_domains_match, -}; 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, 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(()) } diff --git a/crates/apub/src/activities/deletion/delete.rs b/crates/apub/src/activities/deletion/delete.rs index f442494ad..eb3de179a 100644 --- a/crates/apub/src/activities/deletion/delete.rs +++ b/crates/apub/src/activities/deletion/delete.rs @@ -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, 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::(context, local_instance(context), request_counter) .await?, self.object.id(), reason, diff --git a/crates/apub/src/activities/deletion/delete_user.rs b/crates/apub/src/activities/deletion/delete_user.rs index a96333d5e..d29139858 100644 --- a/crates/apub/src/activities/deletion/delete_user.rs +++ b/crates/apub/src/activities/deletion/delete_user.rs @@ -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 activitypub_federation::{ + core::object_id::ObjectId, + data::Data, + traits::ActivityHandler, + utils::verify_urls_match, +}; use activitystreams_kinds::{activity::DeleteType, public}; use lemmy_api_common::utils::{blocking, delete_user_account}; -use lemmy_apub_lib::{ - data::Data, - object_id::ObjectId, - traits::ActivityHandler, - verify::verify_urls_match, -}; 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::(context, local_instance(context), request_counter) .await?; delete_user_account(actor.id, context.pool()).await?; Ok(()) diff --git a/crates/apub/src/activities/deletion/mod.rs b/crates/apub/src/activities/deletion/mod.rs index 123e87fbd..6283ffe0a 100644 --- a/crates/apub/src/activities/deletion/mod.rs +++ b/crates/apub/src/activities/deletion/mod.rs @@ -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::(context, local_instance(context), request_counter) .await? .deref() .clone(); diff --git a/crates/apub/src/activities/deletion/undo_delete.rs b/crates/apub/src/activities/deletion/undo_delete.rs index 34e897479..0854c46e6 100644 --- a/crates/apub/src/activities/deletion/undo_delete.rs +++ b/crates/apub/src/activities/deletion/undo_delete.rs @@ -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, 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::(context, local_instance(context), request_counter) .await?, self.object.object.id(), context, diff --git a/crates/apub/src/activities/following/accept.rs b/crates/apub/src/activities/following/accept.rs index dfc008a94..410b678e7 100644 --- a/crates/apub/src/activities/following/accept.rs +++ b/crates/apub/src/activities/following/accept.rs @@ -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 activitypub_federation::{ + core::object_id::ObjectId, + data::Data, + traits::ActivityHandler, + utils::verify_urls_match, }; use activitystreams_kinds::activity::AcceptType; use lemmy_api_common::utils::blocking; -use lemmy_apub_lib::{ - data::Data, - object_id::ObjectId, - traits::{ActivityHandler, ActorType}, - verify::verify_urls_match, -}; 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::(context) + .await?; let person = follow .actor .clone() - .dereference(context, context.client(), request_counter) + .dereference::(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, 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::(context, local_instance(context), request_counter) .await?; let community = self .object .actor - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await?; // This will throw an error if no follow was requested blocking(context.pool(), move |conn| { diff --git a/crates/apub/src/activities/following/follow.rs b/crates/apub/src/activities/following/follow.rs index d46b3dc20..f78fadff0 100644 --- a/crates/apub/src/activities/following/follow.rs +++ b/crates/apub/src/activities/following/follow.rs @@ -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, 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::(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::(context, local_instance(context), request_counter) .await?; let community = self .object - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await?; let community_follower_form = CommunityFollowerForm { community_id: community.id, diff --git a/crates/apub/src/activities/following/undo_follow.rs b/crates/apub/src/activities/following/undo_follow.rs index f70acdf27..fd178dab2 100644 --- a/crates/apub/src/activities/following/undo_follow.rs +++ b/crates/apub/src/activities/following/undo_follow.rs @@ -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 activitypub_federation::{ + core::object_id::ObjectId, + data::Data, + traits::ActivityHandler, + utils::verify_urls_match, }; use activitystreams_kinds::activity::UndoType; use lemmy_api_common::utils::blocking; -use lemmy_apub_lib::{ - data::Data, - object_id::ObjectId, - traits::{ActivityHandler, ActorType}, - verify::verify_urls_match, -}; 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, 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::(context, local_instance(context), request_counter) .await?; let community = self .object .object - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await?; let community_follower_form = CommunityFollowerForm { diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 2c8b0921c..3a4754996 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -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::(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::(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::(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( 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 = inboxes + .into_iter() .filter(|i| i.domain().expect("valid inbox url") != hostname) .collect(); @@ -200,13 +194,15 @@ async fn send_lemmy_activity( 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(()) } diff --git a/crates/apub/src/activities/voting/mod.rs b/crates/apub/src/activities/voting/mod.rs index f2e3f24f8..4896b4c64 100644 --- a/crates/apub/src/activities/voting/mod.rs +++ b/crates/apub/src/activities/voting/mod.rs @@ -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, diff --git a/crates/apub/src/activities/voting/undo_vote.rs b/crates/apub/src/activities/voting/undo_vote.rs index eb350770e..4f410ae97 100644 --- a/crates/apub/src/activities/voting/undo_vote.rs +++ b/crates/apub/src/activities/voting/undo_vote.rs @@ -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 activitypub_federation::{ + core::object_id::ObjectId, + data::Data, + traits::ActivityHandler, + utils::verify_urls_match, +}; use activitystreams_kinds::{activity::UndoType, public}; use lemmy_api_common::utils::blocking; -use lemmy_apub_lib::{ - data::Data, - object_id::ObjectId, - traits::{ActivityHandler, ActorType}, - verify::verify_urls_match, -}; 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::(context, local_instance(context), request_counter) .await?; let object = self .object .object - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await?; match object { PostOrComment::Post(p) => undo_vote_post(actor, &p, context).await, diff --git a/crates/apub/src/activities/voting/vote.rs b/crates/apub/src/activities/voting/vote.rs index a851e28f4..7971704db 100644 --- a/crates/apub/src/activities/voting/vote.rs +++ b/crates/apub/src/activities/voting/vote.rs @@ -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::(context, local_instance(context), request_counter) .await?; let object = self .object - .dereference(context, context.client(), request_counter) + .dereference::(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 { let object = self .object - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await?; let cid = match object { PostOrComment::Post(p) => p.community_id, diff --git a/crates/apub/src/activity_lists.rs b/crates/apub/src/activity_lists.rs index c9debefaa..656c80206 100644 --- a/crates/apub/src/activity_lists.rs +++ b/crates/apub/src/activity_lists.rs @@ -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(Box>), // 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(Box>), } -#[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), @@ -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, + 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, + 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, } } } diff --git a/crates/apub/src/collections/community_moderators.rs b/crates/apub/src/collections/community_moderators.rs index 028174ae9..b8cd64690 100644 --- a/crates/apub/src/collections/community_moderators.rs +++ b/crates/apub/src/collections/community_moderators.rs @@ -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 #[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 { None @@ -66,10 +71,6 @@ impl ApubObject for ApubCommunityModerators { }) } - fn to_tombstone(&self) -> Result { - 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::(&data.1, local_instance(&data.1), request_counter) .await?; if !current_moderators diff --git a/crates/apub/src/collections/community_outbox.rs b/crates/apub/src/collections/community_outbox.rs index 098471c26..dde98859a 100644 --- a/crates/apub/src/collections/community_outbox.rs +++ b/crates/apub/src/collections/community_outbox.rs @@ -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); #[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 { None @@ -78,11 +78,6 @@ impl ApubObject for ApubCommunityOutbox { }) } - fn to_tombstone(&self) -> Result { - // 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 index 9d2d3d42c..000000000 --- a/crates/apub/src/context.rs +++ /dev/null @@ -1,27 +0,0 @@ -use once_cell::sync::Lazy; -use serde::{Deserialize, Serialize}; - -static CONTEXT: Lazy> = Lazy::new(|| { - serde_json::from_str(include_str!("../assets/lemmy/context.json")).expect("parse context") -}); - -#[derive(Serialize, Deserialize, Debug)] -pub(crate) struct WithContext { - #[serde(rename = "@context")] - #[serde(deserialize_with = "crate::deserialize_one_or_many")] - context: Vec, - #[serde(flatten)] - inner: T, -} - -impl WithContext { - pub(crate) fn new(inner: T) -> WithContext { - WithContext { - context: (*CONTEXT).clone(), - inner, - } - } - pub(crate) fn inner(self) -> T { - self.inner - } -} diff --git a/crates/apub/src/fetcher/mod.rs b/crates/apub/src/fetcher/mod.rs index cd889ccc6..274c31d44 100644 --- a/crates/apub/src/fetcher/mod.rs +++ b/crates/apub/src/fetcher/mod.rs @@ -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( context: &LemmyContext, ) -> Result where - Actor: - ApubObject + ApubObject + ActorType + Send + 'static, + Actor: ApubObject + + ApubObject + + ActorType + + Send + + 'static, for<'de2> ::ApubType: serde::Deserialize<'de2>, DbActor: ApubActor + Send + 'static, { diff --git a/crates/apub/src/fetcher/post_or_comment.rs b/crates/apub/src/fetcher/post_or_comment.rs index eaebeca6b..ba9a2ac49 100644 --- a/crates/apub/src/fetcher/post_or_comment.rs +++ b/crates/apub/src/fetcher/post_or_comment.rs @@ -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 { None @@ -60,10 +60,6 @@ impl ApubObject for PostOrComment { unimplemented!() } - fn to_tombstone(&self) -> Result { - unimplemented!() - } - #[tracing::instrument(skip_all)] async fn verify( apub: &Self::ApubType, diff --git a/crates/apub/src/fetcher/search.rs b/crates/apub/src/fetcher/search.rs index e4ae45e68..43244b4d7 100644 --- a/crates/apub/src/fetcher/search.rs +++ b/crates/apub/src/fetcher/search.rs @@ -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 { 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::(context, instance, request_counter) .await } Err(_) => { @@ -37,7 +39,7 @@ pub async fn search_by_apub_id( webfinger_resolve_actor::(identifier, context, request_counter).await?; Ok(SearchableObjects::Person( ObjectId::new(id) - .dereference(context, context.client(), request_counter) + .dereference::(context, instance, request_counter) .await?, )) } @@ -46,7 +48,7 @@ pub async fn search_by_apub_id( webfinger_resolve_actor::(identifier, context, request_counter).await?; Ok(SearchableObjects::Community( ObjectId::new(id) - .dereference(context, context.client(), request_counter) + .dereference::(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 { match self { @@ -133,10 +135,6 @@ impl ApubObject for SearchableObjects { unimplemented!() } - fn to_tombstone(&self) -> Result { - unimplemented!() - } - #[tracing::instrument(skip_all)] async fn verify( apub: &Self::ApubType, diff --git a/crates/apub/src/fetcher/user_or_community.rs b/crates/apub/src/fetcher/user_or_community.rs index 7ec5e9dd9..16a74c2e5 100644 --- a/crates/apub/src/fetcher/user_or_community.rs +++ b/crates/apub/src/fetcher/user_or_community.rs @@ -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 { Some(match self { @@ -68,10 +68,6 @@ impl ApubObject for UserOrCommunity { unimplemented!() } - fn to_tombstone(&self) -> Result { - 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 { - todo!() - } - - fn inbox_url(&self) -> Url { - todo!() - } - - fn shared_inbox_url(&self) -> Option { - todo!() - } } diff --git a/crates/apub/src/fetcher/webfinger.rs b/crates/apub/src/fetcher/webfinger.rs index da516b1da..b53a988ee 100644 --- a/crates/apub/src/fetcher/webfinger.rs +++ b/crates/apub/src/fetcher/webfinger.rs @@ -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( request_counter: &mut i32, ) -> Result where - Kind: ApubObject + ActorType + Send + 'static, + Kind: ApubObject + ActorType + Send + 'static, for<'de2> ::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::::new(l) - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await; if object.is_ok() { return object.map(|o| o.actor_id().into()); diff --git a/crates/apub/src/http/comment.rs b/crates/apub/src/http/comment.rs index 1918a38e8..59cbee8e8 100644 --- a/crates/apub/src/http/comment.rs +++ b/crates/apub/src/http/comment.rs @@ -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())) } } diff --git a/crates/apub/src/http/community.rs b/crates/apub/src/http/community.rs index 41f6d1c0b..6b8c7fe7e 100644 --- a/crates/apub/src/http/community.rs +++ b/crates/apub/src/http/community.rs @@ -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 actix_web::{web, web::Payload, HttpRequest, HttpResponse}; +use activitypub_federation::{ + core::object_id::ObjectId, + deser::context::WithContext, + traits::ApubObject, +}; +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, + payload: String, context: web::Data, ) -> Result { - 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::>(&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 { - 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::, 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::(&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::(&outbox_data, local_instance(&context), &mut 0) .await?; Ok(create_apub_response( &moderators.into_apub(&outbox_data).await?, diff --git a/crates/apub/src/http/mod.rs b/crates/apub/src/http/mod.rs index 0112d2056..d5d940661 100644 --- a/crates/apub/src/http/mod.rs +++ b/crates/apub/src/http/mod.rs @@ -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, ) -> Result { - 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::>(&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::(request, payload, context).await } -async fn payload_to_string(mut payload: Payload) -> Result { - 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( request: HttpRequest, - activity: T, - activity_data: ActivityCommonFields, - context: &LemmyContext, + payload: String, + context: web::Data, ) -> Result where - T: ActivityHandler - + Clone - + Deserialize<'a> - + Serialize - + std::fmt::Debug + Activity: ActivityHandler + + DeserializeOwned + Send + 'static, + Actor: ApubObject + ActorPublicKey + Send + 'static, + for<'de2> ::ApubType: serde::Deserialize<'de2>, { - check_is_apub_id_valid(&activity_data.actor, false, &context.settings())?; - let request_counter = &mut 0; - let actor = ObjectId::::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!("Received activity {}", payload); - info!("Receiving activity {}", activity_data.id.to_string()); - activity - .receive(&Data::new(context.clone()), request_counter) - .await?; - Ok(HttpResponse::Ok().finish()) + static DATA: OnceCell> = OnceCell::new(); + let data = DATA.get_or_init(|| Data::new(context.get_ref().clone())); + receive_activity::( + 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(data: &T) -> HttpResponse -where - T: Serialize, -{ +fn create_apub_tombstone_response>(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(()) -} diff --git a/crates/apub/src/http/person.rs b/crates/apub/src/http/person.rs index f0540268a..f887b2652 100644 --- a/crates/apub/src/http/person.rs +++ b/crates/apub/src/http/person.rs @@ -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, + payload: String, context: web::Data, ) -> Result { - 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::>(&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 { - receive_activity(request, activity, activity_data, context).await + receive_lemmy_activity::, UserOrCommunity>( + request, payload, context, + ) + .await } #[tracing::instrument(skip_all)] diff --git a/crates/apub/src/http/post.rs b/crates/apub/src/http/post.rs index 845803b90..0e321d176 100644 --- a/crates/apub/src/http/post.rs +++ b/crates/apub/src/http/post.rs @@ -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())) } } diff --git a/crates/apub/src/http/site.rs b/crates/apub/src/http/site.rs index e48110663..3d8327387 100644 --- a/crates/apub/src/http/site.rs +++ b/crates/apub/src/http/site.rs @@ -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 { #[tracing::instrument(skip_all)] pub async fn get_apub_site_inbox( request: HttpRequest, - payload: Payload, + payload: String, context: web::Data, ) -> Result { - 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::>(&unparsed)?; - receive_activity(request, activity.inner(), activity_data, &context).await + receive_lemmy_activity::, ApubPerson>(request, payload, context) + .await } diff --git a/crates/apub/src/lib.rs b/crates/apub/src/lib.rs index b7f1912d8..e758e706d 100644 --- a/crates/apub/src/lib.rs +++ b/crates/apub/src/lib.rs @@ -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> = 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 = 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,117 +56,69 @@ 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::(); - 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(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 { - // 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", - )); - } + if let Some(allowed) = settings.to_owned().federation.allowed_instances { + if !allowed.contains(&domain) { + return Err("Domain is not in allowlist"); } } Ok(()) } -pub(crate) fn deserialize_one_or_many<'de, T, D>(deserializer: D) -> Result, D::Error> -where - T: Deserialize<'de>, - D: Deserializer<'de>, -{ - #[derive(Deserialize)] - #[serde(untagged)] - enum OneOrMany { - One(T), - Many(Vec), +#[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(()); } - let result: OneOrMany = Deserialize::deserialize(deserializer)?; - Ok(match result { - OneOrMany::Many(list) => list, - OneOrMany::One(value) => vec![value], - }) -} + 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 is_strict || strict_allowlist { + // need to allow this explicitly because apub receive might contain objects from our local + // instance. + allowed.push(local_instance); -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 { - Simple(T), - Array([T; 1]), + if !allowed.contains(&domain) { + return Err(LemmyError::from_message( + "Federation forbidden by strict allowlist", + )); + } + } } - - let result: MaybeArray = 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 -where - T: Deserialize<'de> + Default, - D: Deserializer<'de>, -{ - let result = Deserialize::deserialize(deserializer); - Ok(match result { - Ok(o) => o, - Err(_) => Default::default(), - }) + Ok(()) } pub enum EndpointType { @@ -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; + + fn inbox_url(&self) -> Url; + + fn shared_inbox_url(&self) -> Option; + + 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()) + } +} diff --git a/crates/apub/src/mentions.rs b/crates/apub/src/mentions.rs index b68391a98..053952ca2 100644 --- a/crates/apub/src/mentions.rs +++ b/crates/apub/src/mentions.rs @@ -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}; diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs index 96c9f05a9..30ddfdf60 100644 --- a/crates/apub/src/objects/comment.rs +++ b/crates/apub/src/objects/comment.rs @@ -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 { None @@ -128,10 +126,6 @@ impl ApubObject for ApubComment { Ok(note) } - fn to_tombstone(&self) -> Result { - 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( ¬e.attributed_to, @@ -174,7 +168,7 @@ impl ApubObject for ApubComment { ) -> Result { let creator = note .attributed_to - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await?; let (post, parent_comment_id) = note.get_parents(context, request_counter).await?; diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index a8904ac58..4c381c1c4 100644 --- a/crates/apub/src/objects/community.rs +++ b/crates/apub/src/objects/community.rs @@ -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 { 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 { - 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::(&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::(&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 { 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) diff --git a/crates/apub/src/objects/instance.rs b/crates/apub/src/objects/instance.rs index 09b34fc53..cd4ceb467 100644 --- a/crates/apub/src/objects/instance.rs +++ b/crates/apub/src/objects/instance.rs @@ -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 { 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 { - 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 { 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::::new(instance_id.clone()) - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await; if let Err(e) = site { debug!("Failed to dereference site for {}: {}", instance_id, e); diff --git a/crates/apub/src/objects/mod.rs b/crates/apub/src/objects/mod.rs index b3aa80b54..e07eb4def 100644 --- a/crates/apub/src/objects/mod.rs +++ b/crates/apub/src/objects/mod.rs @@ -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) } } diff --git a/crates/apub/src/objects/person.rs b/crates/apub/src/objects/person.rs index bf2cb3cb6..7b87f9011 100644 --- a/crates/apub/src/objects/person.rs +++ b/crates/apub/src/objects/person.rs @@ -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 { 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 { 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::*; diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index 497970364..bdefe2802 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -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 { None @@ -123,10 +121,6 @@ impl ApubObject for ApubPost { Ok(page) } - fn to_tombstone(&self) -> Result { - 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 { let creator = page .creator()? - .dereference(context, context.client(), request_counter) + .dereference::(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::::new(page.id.clone()) - .dereference_local(context) + .dereference_local::(context) .await; let post = blocking(context.pool(), move |conn| Post::upsert(conn, &form)).await??; diff --git a/crates/apub/src/objects/private_message.rs b/crates/apub/src/objects/private_message.rs index a984180db..56363f779 100644 --- a/crates/apub/src/objects/private_message.rs +++ b/crates/apub/src/objects/private_message.rs @@ -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 activitypub_federation::{ + core::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::ApubObject, - values::MediaTypeHtml, - verify::verify_domains_match, -}; 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 { 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::(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 { let creator = note .attributed_to - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await?; - let recipient = note.to[0] - .dereference(context, context.client(), request_counter) + let recipient = note + .to + .dereference::(context, local_instance(context), request_counter) .await?; let form = PrivateMessageForm { diff --git a/crates/apub/src/protocol/activities/block/block_user.rs b/crates/apub/src/protocol/activities/block/block_user.rs index ab4e3eca9..1929a6a53 100644 --- a/crates/apub/src/protocol/activities/block/block_user.rs +++ b/crates/apub/src/protocol/activities/block/block_user.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: ObjectId, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) cc: Vec, pub(crate) target: ObjectId, #[serde(rename = "type")] diff --git a/crates/apub/src/protocol/activities/block/undo_block_user.rs b/crates/apub/src/protocol/activities/block/undo_block_user.rs index 8e756be55..b2dcfaffa 100644 --- a/crates/apub/src/protocol/activities/block/undo_block_user.rs +++ b/crates/apub/src/protocol/activities/block/undo_block_user.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: BlockUser, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: UndoType, diff --git a/crates/apub/src/protocol/activities/community/add_mod.rs b/crates/apub/src/protocol/activities/community/add_mod.rs index 5697c19f4..e720b8e6d 100644 --- a/crates/apub/src/protocol/activities/community/add_mod.rs +++ b/crates/apub/src/protocol/activities/community/add_mod.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: ObjectId, pub(crate) target: Url, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: AddType, diff --git a/crates/apub/src/protocol/activities/community/announce.rs b/crates/apub/src/protocol/activities/community/announce.rs index 75a7d9af4..9db17a0fe 100644 --- a/crates/apub/src/protocol/activities/community/announce.rs +++ b/crates/apub/src/protocol/activities/community/announce.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: IdOrNestedObject, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: AnnounceType, diff --git a/crates/apub/src/protocol/activities/community/remove_mod.rs b/crates/apub/src/protocol/activities/community/remove_mod.rs index 304772bb2..bd972202f 100644 --- a/crates/apub/src/protocol/activities/community/remove_mod.rs +++ b/crates/apub/src/protocol/activities/community/remove_mod.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: ObjectId, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: RemoveType, diff --git a/crates/apub/src/protocol/activities/community/report.rs b/crates/apub/src/protocol/activities/community/report.rs index 40bbe83bd..cd66c657e 100644 --- a/crates/apub/src/protocol/activities/community/report.rs +++ b/crates/apub/src/protocol/activities/community/report.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one")] - pub(crate) to: [ObjectId; 1], + #[serde(deserialize_with = "deserialize_one")] + pub(crate) to: ObjectId, pub(crate) object: ObjectId, pub(crate) summary: String, #[serde(rename = "type")] diff --git a/crates/apub/src/protocol/activities/community/update.rs b/crates/apub/src/protocol/activities/community/update.rs index 4c4ef2f03..d0b27a551 100644 --- a/crates/apub/src/protocol/activities/community/update.rs +++ b/crates/apub/src/protocol/activities/community/update.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, // TODO: would be nice to use a separate struct here, which only contains the fields updated here pub(crate) object: Box, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: UpdateType, diff --git a/crates/apub/src/protocol/activities/create_or_update/comment.rs b/crates/apub/src/protocol/activities/create_or_update/comment.rs index cf0697b17..5ebc0f554 100644 --- a/crates/apub/src/protocol/activities/create_or_update/comment.rs +++ b/crates/apub/src/protocol/activities/create_or_update/comment.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: Note, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(default)] pub(crate) tag: Vec, diff --git a/crates/apub/src/protocol/activities/create_or_update/post.rs b/crates/apub/src/protocol/activities/create_or_update/post.rs index eb96572f1..d40073cf3 100644 --- a/crates/apub/src/protocol/activities/create_or_update/post.rs +++ b/crates/apub/src/protocol/activities/create_or_update/post.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: Page, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: CreateOrUpdateType, diff --git a/crates/apub/src/protocol/activities/create_or_update/private_message.rs b/crates/apub/src/protocol/activities/create_or_update/private_message.rs index a4e62b656..e0288498b 100644 --- a/crates/apub/src/protocol/activities/create_or_update/private_message.rs +++ b/crates/apub/src/protocol/activities/create_or_update/private_message.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one")] - pub(crate) to: [ObjectId; 1], + #[serde(deserialize_with = "deserialize_one")] + pub(crate) to: ObjectId, pub(crate) object: ChatMessage, #[serde(rename = "type")] pub(crate) kind: CreateOrUpdateType, diff --git a/crates/apub/src/protocol/activities/deletion/delete.rs b/crates/apub/src/protocol/activities/deletion/delete.rs index 3fb5984d6..76256cacb 100644 --- a/crates/apub/src/protocol/activities/deletion/delete.rs +++ b/crates/apub/src/protocol/activities/deletion/delete.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: IdOrNestedObject, #[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, diff --git a/crates/apub/src/protocol/activities/deletion/delete_user.rs b/crates/apub/src/protocol/activities/deletion/delete_user.rs index a45bfbdb6..d455be99c 100644 --- a/crates/apub/src/protocol/activities/deletion/delete_user.rs +++ b/crates/apub/src/protocol/activities/deletion/delete_user.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: ObjectId, #[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, } diff --git a/crates/apub/src/protocol/activities/deletion/undo_delete.rs b/crates/apub/src/protocol/activities/deletion/undo_delete.rs index e676ab00b..1ae6aa84b 100644 --- a/crates/apub/src/protocol/activities/deletion/undo_delete.rs +++ b/crates/apub/src/protocol/activities/deletion/undo_delete.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, 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, #[serde(flatten)] diff --git a/crates/apub/src/protocol/activities/following/accept.rs b/crates/apub/src/protocol/activities/following/accept.rs index dcb0b181a..a600fbfba 100644 --- a/crates/apub/src/protocol/activities/following/accept.rs +++ b/crates/apub/src/protocol/activities/following/accept.rs @@ -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; diff --git a/crates/apub/src/protocol/activities/following/follow.rs b/crates/apub/src/protocol/activities/following/follow.rs index 2072af486..2cef197d3 100644 --- a/crates/apub/src/protocol/activities/following/follow.rs +++ b/crates/apub/src/protocol/activities/following/follow.rs @@ -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; diff --git a/crates/apub/src/protocol/activities/following/undo_follow.rs b/crates/apub/src/protocol/activities/following/undo_follow.rs index 193614690..38306b7c1 100644 --- a/crates/apub/src/protocol/activities/following/undo_follow.rs +++ b/crates/apub/src/protocol/activities/following/undo_follow.rs @@ -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; diff --git a/crates/apub/src/protocol/activities/voting/undo_vote.rs b/crates/apub/src/protocol/activities/voting/undo_vote.rs index d8ba7cbae..77e526884 100644 --- a/crates/apub/src/protocol/activities/voting/undo_vote.rs +++ b/crates/apub/src/protocol/activities/voting/undo_vote.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: Vote, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: UndoType, diff --git a/crates/apub/src/protocol/activities/voting/vote.rs b/crates/apub/src/protocol/activities/voting/vote.rs index 763d86233..80ea2ed56 100644 --- a/crates/apub/src/protocol/activities/voting/vote.rs +++ b/crates/apub/src/protocol/activities/voting/vote.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) object: ObjectId, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) cc: Vec, #[serde(rename = "type")] pub(crate) kind: VoteType, diff --git a/crates/apub/src/protocol/collections/empty_outbox.rs b/crates/apub/src/protocol/collections/empty_outbox.rs index 265575af4..8c9cf06ed 100644 --- a/crates/apub/src/protocol/collections/empty_outbox.rs +++ b/crates/apub/src/protocol/collections/empty_outbox.rs @@ -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; diff --git a/crates/apub/src/protocol/collections/group_followers.rs b/crates/apub/src/protocol/collections/group_followers.rs index 777d19803..eeea8e073 100644 --- a/crates/apub/src/protocol/collections/group_followers.rs +++ b/crates/apub/src/protocol/collections/group_followers.rs @@ -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; diff --git a/crates/apub/src/protocol/collections/group_moderators.rs b/crates/apub/src/protocol/collections/group_moderators.rs index 6a72b9551..4d1042821 100644 --- a/crates/apub/src/protocol/collections/group_moderators.rs +++ b/crates/apub/src/protocol/collections/group_moderators.rs @@ -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; diff --git a/crates/apub/src/protocol/mod.rs b/crates/apub/src/protocol/mod.rs index 3206ac23e..c81a5c159 100644 --- a/crates/apub/src/protocol/mod.rs +++ b/crates/apub/src/protocol/mod.rs @@ -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); pub(crate) trait Id { - fn id(&self) -> &Url; + fn object_id(&self) -> &Url; } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -63,7 +64,7 @@ impl IdOrNestedObject { 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 IdOrNestedObject { request_counter: &mut i32, ) -> Result { 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 IdOrNestedObject { #[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}; diff --git a/crates/apub/src/protocol/objects/chat_message.rs b/crates/apub/src/protocol/objects/chat_message.rs index e0ac8db98..c2ee57e4e 100644 --- a/crates/apub/src/protocol/objects/chat_message.rs +++ b/crates/apub/src/protocol/objects/chat_message.rs @@ -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, pub(crate) attributed_to: ObjectId, - #[serde(deserialize_with = "crate::deserialize_one")] - pub(crate) to: [ObjectId; 1], + #[serde(deserialize_with = "deserialize_one")] + pub(crate) to: ObjectId, pub(crate) content: String, pub(crate) media_type: Option, - #[serde(deserialize_with = "crate::deserialize_skip_error", default)] + #[serde(deserialize_with = "deserialize_skip_error", default)] pub(crate) source: Option, pub(crate) published: Option>, pub(crate) updated: Option>, diff --git a/crates/apub/src/protocol/objects/group.rs b/crates/apub/src/protocol/objects/group.rs index 8f161c2da..ba01e12d5 100644 --- a/crates/apub/src/protocol/objects/group.rs +++ b/crates/apub/src/protocol/objects/group.rs @@ -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, pub(crate) summary: Option, - #[serde(deserialize_with = "crate::deserialize_skip_error", default)] + #[serde(deserialize_with = "deserialize_skip_error", default)] pub(crate) source: Option, pub(crate) icon: Option, /// 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(); diff --git a/crates/apub/src/protocol/objects/instance.rs b/crates/apub/src/protocol/objects/instance.rs index a18b72795..b921ad207 100644 --- a/crates/apub/src/protocol/objects/instance.rs +++ b/crates/apub/src/protocol/objects/instance.rs @@ -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, - #[serde(deserialize_with = "crate::deserialize_skip_error", default)] + #[serde(deserialize_with = "deserialize_skip_error", default)] pub(crate) source: Option, // short instance description pub(crate) summary: Option, diff --git a/crates/apub/src/protocol/objects/note.rs b/crates/apub/src/protocol/objects/note.rs index ac3e722c7..cd17e65d5 100644 --- a/crates/apub/src/protocol/objects/note.rs +++ b/crates/apub/src/protocol/objects/note.rs @@ -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, pub(crate) attributed_to: ObjectId, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, - #[serde(deserialize_with = "crate::deserialize_one_or_many", default)] + #[serde(deserialize_with = "deserialize_one_or_many", default)] pub(crate) cc: Vec, pub(crate) content: String, pub(crate) in_reply_to: ObjectId, pub(crate) media_type: Option, - #[serde(deserialize_with = "crate::deserialize_skip_error", default)] + #[serde(deserialize_with = "deserialize_skip_error", default)] pub(crate) source: Option, pub(crate) published: Option>, pub(crate) updated: Option>, @@ -49,7 +56,7 @@ impl Note { let parent = Box::pin( self .in_reply_to - .dereference(context, context.client(), request_counter) + .dereference::(context, local_instance(context), request_counter) .await?, ); match parent.deref() { diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs index 426de96f4..74db11afe 100644 --- a/crates/apub/src/protocol/objects/page.rs +++ b/crates/apub/src/protocol/objects/page.rs @@ -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 activitypub_federation::{ + core::object_id::ObjectId, + data::Data, + deser::{ + helpers::{deserialize_one_or_many, deserialize_skip_error}, + values::MediaTypeMarkdownOrHtml, + }, + traits::{ActivityHandler, ApubObject}, +}; use activitystreams_kinds::link::LinkType; use chrono::{DateTime, FixedOffset}; use itertools::Itertools; -use lemmy_apub_lib::{ - data::Data, - object_id::ObjectId, - traits::{ActivityHandler, ApubObject}, - values::MediaTypeMarkdownOrHtml, -}; 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, pub(crate) attributed_to: AttributedTo, - #[serde(deserialize_with = "crate::deserialize_one_or_many")] + #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, 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, pub(crate) content: Option, pub(crate) media_type: Option, - #[serde(deserialize_with = "crate::deserialize_skip_error", default)] + #[serde(deserialize_with = "deserialize_skip_error", default)] pub(crate) source: Option, /// deprecated, use attachment field - #[serde(deserialize_with = "crate::deserialize_skip_error", default)] + #[serde(deserialize_with = "deserialize_skip_error", default)] pub(crate) url: Option, /// 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 { let old_post = ObjectId::::new(self.id.clone()) - .dereference_local(context) + .dereference_local::(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::(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::::new(a.id.clone().into_inner())) .ok_or_else(|| LemmyError::from_message("page does not specify group"))? - .dereference(context, context.client(), request_counter) + .dereference::(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, diff --git a/crates/apub/src/protocol/objects/person.rs b/crates/apub/src/protocol/objects/person.rs index 75d20cf6d..ac52e46ac 100644 --- a/crates/apub/src/protocol/objects/person.rs +++ b/crates/apub/src/protocol/objects/person.rs @@ -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, pub(crate) summary: Option, - #[serde(deserialize_with = "crate::deserialize_skip_error", default)] + #[serde(deserialize_with = "deserialize_skip_error", default)] pub(crate) source: Option, /// user avatar pub(crate) icon: Option, diff --git a/crates/apub/src/protocol/objects/tombstone.rs b/crates/apub/src/protocol/objects/tombstone.rs index 0e60d6247..1b66f2a7e 100644 --- a/crates/apub/src/protocol/objects/tombstone.rs +++ b/crates/apub/src/protocol/objects/tombstone.rs @@ -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 index a94229ff4..000000000 --- a/crates/apub_lib/src/activity_queue.rs +++ /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::(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>>>; - 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::() - .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 index d366f0fbf..000000000 --- a/crates/apub_lib/src/data.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::{ops::Deref, sync::Arc}; - -#[derive(Debug)] -pub struct Data(Arc); - -impl Data { - /// Create new `Data` instance. - pub fn new(state: T) -> Data { - 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 - pub fn into_inner(self) -> Arc { - self.0 - } -} - -impl Deref for Data { - type Target = Arc; - - fn deref(&self) -> &Arc { - &self.0 - } -} - -impl Clone for Data { - fn clone(&self) -> Data { - Data(self.0.clone()) - } -} diff --git a/crates/apub_lib/src/lib.rs b/crates/apub_lib/src/lib.rs deleted file mode 100644 index 7c110169d..000000000 --- a/crates/apub_lib/src/lib.rs +++ /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 index da3896160..000000000 --- a/crates/apub_lib/src/object_id.rs +++ /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(Box, #[serde(skip)] PhantomData) -where - Kind: ApubObject + Send + 'static, - for<'de2> ::ApubType: serde::Deserialize<'de2>; - -impl ObjectId -where - Kind: ApubObject + Send + 'static, - for<'de2> ::ApubType: serde::Deserialize<'de2>, -{ - pub fn new(url: T) -> Self - where - T: Into, - { - ObjectId(Box::new(url.into()), PhantomData::) - } - - 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: &::DataType, - client: &ClientWithMiddleware, - request_counter: &mut i32, - ) -> Result { - 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: &::DataType, - ) -> Result { - 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: &::DataType, - ) -> Result, LemmyError> { - let id = self.0.clone(); - ApubObject::read_from_apub_id(*id, data).await - } - - async fn dereference_from_http( - &self, - data: &::DataType, - client: &ClientWithMiddleware, - request_counter: &mut i32, - db_object: Option, - ) -> Result { - 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 Display for ObjectId -where - Kind: ApubObject + Send + 'static, - for<'de2> ::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 From> for Url -where - Kind: ApubObject + Send + 'static, - for<'de2> ::ApubType: serde::Deserialize<'de2>, -{ - fn from(id: ObjectId) -> 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 index 6e5d6d251..000000000 --- a/crates/apub_lib/src/signatures.rs +++ /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 = Lazy::new(ConfigActix::new); -static HTTP_SIG_CONFIG: Lazy = 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 { - 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 { - 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, - 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 index 43fec524a..000000000 --- a/crates/apub_lib/src/traits.rs +++ /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, - request_counter: &mut i32, - ) -> Result<(), LemmyError>; - - async fn receive( - self, - data: &Data, - 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; - /// 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, 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; - fn to_tombstone(&self) -> Result; - - 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 - 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; - - fn inbox_url(&self) -> Url; - - fn shared_inbox_url(&self) -> Option; - - fn shared_inbox_or_inbox_url(&self) -> Url { - self.shared_inbox_url().unwrap_or_else(|| self.inbox_url()) - } - - fn get_public_key(&self) -> Result { - 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 index 391e01dfb..000000000 --- a/crates/apub_lib/src/utils.rs +++ /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( - url: &Url, - client: &ClientWithMiddleware, - request_counter: &mut i32, -) -> Result { - // 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 index bf1780a81..000000000 --- a/crates/apub_lib/src/values.rs +++ /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::(markdown_json); -//! assert!(from_markdown.is_ok()); -//! -//! let markdown_html = r#"{"content": "test", "media_type": "text/html"}"#; -//! let from_html = from_str::(markdown_html); -//! assert!(from_html.is_err()); -//! ``` - -use serde::{Deserialize, Serialize}; - -/// Media type for markdown text. -/// -/// -#[derive(Clone, Debug, Deserialize, Serialize)] -pub enum MediaTypeMarkdown { - #[serde(rename = "text/markdown")] - Markdown, -} - -/// Media type for HTML text. -/// -/// -#[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 index b7927758a..000000000 --- a/crates/apub_lib/src/verify.rs +++ /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 index d548af4c4..000000000 --- a/crates/apub_lib_derive/src/lib.rs +++ /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 = &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, - request_counter: &mut i32, - ) -> Result<(), lemmy_utils::LemmyError> { - match self { - #(#impl_verify)* - } - } - async fn receive( - self, - context: &lemmy_apub_lib::data::Data, - 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!(), - } -} diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml index 69101b682..483c9e945 100644 --- a/crates/db_schema/Cargo.toml +++ b/crates/db_schema/Cargo.toml @@ -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 } diff --git a/crates/db_schema/src/impls/private_message.rs b/crates/db_schema/src/impls/private_message.rs index e90ae5248..d5506990d 100644 --- a/crates/db_schema/src/impls/private_message.rs +++ b/crates/db_schema/src/impls/private_message.rs @@ -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 { diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 09c5ecdd8..c9ccc1700 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -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}; diff --git a/crates/routes/src/feeds.rs b/crates/routes/src/feeds.rs index 878c68b9a..c0010187b 100644 --- a/crates/routes/src/feeds.rs +++ b/crates/routes/src/feeds.rs @@ -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::{ diff --git a/crates/routes/src/images.rs b/crates/routes/src/images.rs index 6439c8b6a..23d2020b7 100644 --- a/crates/routes/src/images.rs +++ b/crates/routes/src/images.rs @@ -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() diff --git a/crates/routes/src/nodeinfo.rs b/crates/routes/src/nodeinfo.rs index 6ca2114e4..1841b1591 100644 --- a/crates/routes/src/nodeinfo.rs +++ b/crates/routes/src/nodeinfo.rs @@ -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; diff --git a/crates/routes/src/webfinger.rs b/crates/routes/src/webfinger.rs index 01ed2bc00..f3856eb5d 100644 --- a/crates/routes/src/webfinger.rs +++ b/crates/routes/src/webfinger.rs @@ -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; diff --git a/crates/utils/src/claims.rs b/crates/utils/src/claims.rs index d49ecfa8d..77a720694 100644 --- a/crates/utils/src/claims.rs +++ b/crates/utils/src/claims.rs @@ -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}; diff --git a/crates/utils/src/email.rs b/crates/utils/src/email.rs index 13aff6985..0bc3d71d3 100644 --- a/crates/utils/src/email.rs +++ b/crates/utils/src/email.rs @@ -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 index 000000000..441c0422e --- /dev/null +++ b/crates/utils/src/error.rs @@ -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, + 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(error: E, message: &str) -> Self + where + E: Into, + { + 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 { + 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 From for LemmyError +where + T: Into, +{ + 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::() { + 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()) + } + } +} diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index b8e301bd9..beaf173ba 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -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, - 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(error: E, message: &str) -> Self - where - E: Into, - { - 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 { - 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 From for LemmyError -where - T: Into, -{ - 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::() { - 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()) - } - } -} diff --git a/crates/utils/src/settings/mod.rs b/crates/utils/src/settings/mod.rs index bf1a8984d..50597f244 100644 --- a/crates/utils/src/settings/mod.rs +++ b/crates/utils/src/settings/mod.rs @@ -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; diff --git a/crates/utils/src/utils.rs b/crates/utils/src/utils.rs index f9c68f4ef..a7c42cca8 100644 --- a/crates/utils/src/utils.rs +++ b/crates/utils/src/utils.rs @@ -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; diff --git a/crates/websocket/src/chat_server.rs b/crates/websocket/src/chat_server.rs index 4328d2d39..2337cae32 100644 --- a/crates/websocket/src/chat_server.rs +++ b/crates/websocket/src/chat_server.rs @@ -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(), }; diff --git a/crates/websocket/src/lib.rs b/crates/websocket/src/lib.rs index 12f9783ab..2a7d1e8f4 100644 --- a/crates/websocket/src/lib.rs +++ b/crates/websocket/src/lib.rs @@ -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, client: ClientWithMiddleware, - activity_queue: QueueHandle, settings: Settings, secret: Secret, } @@ -29,7 +27,6 @@ impl LemmyContext { pool: DbPool, chat_server: Addr, 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(), } diff --git a/crates/websocket/src/send.rs b/crates/websocket/src/send.rs index 3b160e675..2e3cf0597 100644 --- a/crates/websocket/src/send.rs +++ b/crates/websocket/src/send.rs @@ -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( diff --git a/src/code_migrations.rs b/src/code_migrations.rs index 5a0b9eb6d..de6816315 100644 --- a/src/code_migrations.rs +++ b/src/code_migrations.rs @@ -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; diff --git a/src/lib.rs b/src/lib.rs index 1280934c9..b0bbd4bb0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/main.rs b/src/main.rs index be7d028cd..7f5946f5d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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 = 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 retry_policy = ExponentialBackoff { + max_n_retries: 3, + max_retry_interval: REQWEST_TIMEOUT, + min_retry_interval: Duration::from_millis(100), + backoff_exponent: 2, + }; - let queue_manager = create_activity_queue(client.clone(), settings.federation.worker_count); - - 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(()) } diff --git a/src/scheduled_tasks.rs b/src/scheduled_tasks.rs index 32bfd5e8c..5b1ae419b 100644 --- a/src/scheduled_tasks.rs +++ b/src/scheduled_tasks.rs @@ -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; diff --git a/src/telemetry.rs b/src/telemetry.rs index 9f8c9f3b4..2f758e062 100644 --- a/src/telemetry.rs +++ b/src/telemetry.rs @@ -1,5 +1,5 @@ use console_subscriber::ConsoleLayer; -use lemmy_utils::LemmyError; +use lemmy_utils::error::LemmyError; use opentelemetry::{ sdk::{propagation::TraceContextPropagator, Resource}, KeyValue,