"syn 1.0.103",
]
+[[package]]
+name = "async-io"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
+dependencies = [
+ "async-lock",
+ "autocfg",
+ "cfg-if",
+ "concurrent-queue",
+ "futures-lite",
+ "log",
+ "parking",
+ "polling",
+ "rustix 0.37.22",
+ "slab",
+ "socket2 0.4.9",
+ "waker-fn",
+]
+
+[[package]]
+name = "async-lock"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7"
+dependencies = [
+ "event-listener",
+]
+
[[package]]
name = "async-stream"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
+[[package]]
+name = "bytecount"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c"
+
[[package]]
name = "bytemuck"
version = "1.12.1"
"bytes",
]
+[[package]]
+name = "camino"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "captcha"
version = "0.0.9"
"serde_json",
]
+[[package]]
+name = "cargo-platform"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "cc"
version = "1.0.73"
"memchr",
]
+[[package]]
+name = "concurrent-queue"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c"
+dependencies = [
+ "crossbeam-utils",
+]
+
[[package]]
name = "config"
version = "0.13.3"
"winapi",
]
+[[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
"libc",
]
+[[package]]
+name = "error-chain"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
+dependencies = [
+ "version_check",
+]
+
+[[package]]
+name = "event-listener"
+version = "2.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
+
[[package]]
name = "eyre"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
+[[package]]
+name = "futures-lite"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
+dependencies = [
+ "fastrand",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "parking",
+ "pin-project-lite",
+ "waker-fn",
+]
+
[[package]]
name = "futures-macro"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
+[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
[[package]]
name = "h2"
version = "0.3.14"
"libc",
]
+[[package]]
+name = "hermit-abi"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
+
[[package]]
name = "hex"
version = "0.4.3"
[[package]]
name = "io-lifetimes"
-version = "1.0.3"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
+ "hermit-abi 0.3.2",
"libc",
- "windows-sys 0.42.0",
+ "windows-sys 0.48.0",
]
[[package]]
dependencies = [
"hermit-abi 0.2.6",
"io-lifetimes",
- "rustix",
+ "rustix 0.36.5",
"windows-sys 0.42.0",
]
"lemmy_db_views",
"lemmy_db_views_actor",
"lemmy_utils",
+ "moka",
"once_cell",
"reqwest",
"reqwest-middleware",
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
[[package]]
name = "local-channel"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
+[[package]]
+name = "mach2"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "markdown-it"
version = "0.5.0"
"windows-sys 0.36.1",
]
+[[package]]
+name = "moka"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "206bf83f415b0579fd885fe0804eb828e727636657dc1bf73d80d2f1218e14a1"
+dependencies = [
+ "async-io",
+ "async-lock",
+ "crossbeam-channel",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+ "futures-util",
+ "once_cell",
+ "parking_lot 0.12.1",
+ "quanta",
+ "rustc_version",
+ "scheduled-thread-pool",
+ "skeptic",
+ "smallvec",
+ "tagptr",
+ "thiserror",
+ "triomphe",
+ "uuid",
+]
+
[[package]]
name = "multimap"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
+[[package]]
+name = "parking"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e"
+
[[package]]
name = "parking_lot"
version = "0.11.2"
"miniz_oxide 0.5.4",
]
+[[package]]
+name = "polling"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
+dependencies = [
+ "autocfg",
+ "bitflags 1.3.2",
+ "cfg-if",
+ "concurrent-queue",
+ "libc",
+ "log",
+ "pin-project-lite",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "postgres-protocol"
version = "0.6.5"
"cc",
]
+[[package]]
+name = "pulldown-cmark"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
+dependencies = [
+ "bitflags 1.3.2",
+ "memchr",
+ "unicase",
+]
+
+[[package]]
+name = "quanta"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab"
+dependencies = [
+ "crossbeam-utils",
+ "libc",
+ "mach2",
+ "once_cell",
+ "raw-cpuid",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "web-sys",
+ "winapi",
+]
+
[[package]]
name = "quick-xml"
version = "0.27.1"
"rand_core 0.5.1",
]
+[[package]]
+name = "raw-cpuid"
+version = "10.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
[[package]]
name = "readonly"
version = "0.2.8"
checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
dependencies = [
"bitflags 1.3.2",
- "errno",
+ "errno 0.2.8",
"io-lifetimes",
"libc",
- "linux-raw-sys",
+ "linux-raw-sys 0.1.4",
"windows-sys 0.42.0",
]
+[[package]]
+name = "rustix"
+version = "0.37.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8818fa822adcc98b18fedbb3632a6a33213c070556b5aa7c4c8cc21cff565c4c"
+dependencies = [
+ "bitflags 1.3.2",
+ "errno 0.3.1",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys 0.3.8",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "rustls"
version = "0.20.7"
"windows-sys 0.36.1",
]
+[[package]]
+name = "scheduled-thread-pool"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19"
+dependencies = [
+ "parking_lot 0.12.1",
+]
+
[[package]]
name = "scoped-futures"
version = "0.1.3"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
+dependencies = [
+ "serde",
+]
[[package]]
name = "serde"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
+[[package]]
+name = "skeptic"
+version = "0.13.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8"
+dependencies = [
+ "bytecount",
+ "cargo_metadata",
+ "error-chain",
+ "glob",
+ "pulldown-cmark",
+ "tempfile",
+ "walkdir",
+]
+
[[package]]
name = "slab"
version = "0.4.7"
"yaml-rust",
]
+[[package]]
+name = "tagptr"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
+
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+[[package]]
+name = "waker-fn"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
+
[[package]]
name = "walkdir"
version = "2.3.2"
html2md = "0.2.14"
serde_with = { workspace = true }
enum_delegate = "0.2.0"
+moka = { version = "0.11", features = ["future"] }
[dev-dependencies]
serial_test = { workspace = true }
use crate::fetcher::post_or_comment::PostOrComment;
use activitypub_federation::config::{Data, UrlVerifier};
use async_trait::async_trait;
+use futures::future::join3;
use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::{
source::{
traits::Crud,
utils::DbPool,
};
-use lemmy_utils::{error::LemmyError, settings::structs::Settings};
+use lemmy_utils::error::{LemmyError, LemmyResult};
+use moka::future::Cache;
use once_cell::sync::Lazy;
use serde::Serialize;
+use std::{sync::Arc, time::Duration};
use url::Url;
pub mod activities;
pub mod protocol;
pub const FEDERATION_HTTP_FETCH_LIMIT: u32 = 50;
+/// All incoming and outgoing federation actions read the blocklist/allowlist and slur filters
+/// multiple times. This causes a huge number of database reads if we hit the db directly. So we
+/// cache these values for a short time, which will already make a huge difference and ensures that
+/// changes take effect quickly.
+const BLOCKLIST_CACHE_DURATION: Duration = Duration::from_secs(60);
static CONTEXT: Lazy<Vec<serde_json::Value>> = Lazy::new(|| {
serde_json::from_str(include_str!("../assets/lemmy/context.json")).expect("parse context")
#[async_trait]
impl UrlVerifier for VerifyUrlData {
async fn verify(&self, url: &Url) -> Result<(), &'static str> {
- let local_site_data = fetch_local_site_data(&self.0)
+ let local_site_data = local_site_data_cached(&self.0)
.await
.expect("read local site data");
check_apub_id_valid(url, &local_site_data)?;
/// - the correct scheme (either http or https)
/// - URL being in the allowlist (if it is active)
/// - URL not being in the blocklist (if it is active)
-///
-/// `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(local_site_data))]
fn check_apub_id_valid(apub_id: &Url, local_site_data: &LocalSiteData) -> Result<(), &'static str> {
let domain = apub_id.domain().expect("apud id has domain").to_string();
blocked_instances: Vec<Instance>,
}
-pub(crate) async fn fetch_local_site_data(
- pool: &DbPool,
-) -> Result<LocalSiteData, diesel::result::Error> {
- // LocalSite may be missing
- let local_site = LocalSite::read(pool).await.ok();
- let allowed_instances = Instance::allowlist(pool).await?;
- let blocked_instances = Instance::blocklist(pool).await?;
-
- Ok(LocalSiteData {
- local_site,
- allowed_instances,
- blocked_instances,
- })
+pub(crate) async fn local_site_data_cached(pool: &DbPool) -> LemmyResult<Arc<LocalSiteData>> {
+ static CACHE: Lazy<Cache<(), Arc<LocalSiteData>>> = Lazy::new(|| {
+ Cache::builder()
+ .max_capacity(1)
+ .time_to_live(BLOCKLIST_CACHE_DURATION)
+ .build()
+ });
+ Ok(
+ CACHE
+ .try_get_with((), async {
+ let (local_site, allowed_instances, blocked_instances) = join3(
+ LocalSite::read(pool),
+ Instance::allowlist(pool),
+ Instance::blocklist(pool),
+ )
+ .await;
+
+ Ok::<_, diesel::result::Error>(Arc::new(LocalSiteData {
+ // LocalSite may be missing
+ local_site: local_site.ok(),
+ allowed_instances: allowed_instances?,
+ blocked_instances: blocked_instances?,
+ }))
+ })
+ .await?,
+ )
}
-#[tracing::instrument(skip(settings, local_site_data))]
-pub(crate) fn check_apub_id_valid_with_strictness(
+pub(crate) async fn check_apub_id_valid_with_strictness(
apub_id: &Url,
is_strict: bool,
- local_site_data: &LocalSiteData,
- settings: &Settings,
+ context: &LemmyContext,
) -> Result<(), LemmyError> {
let domain = apub_id.domain().expect("apud id has domain").to_string();
- let local_instance = settings
+ let local_instance = context
+ .settings()
.get_hostname_without_port()
.expect("local hostname is valid");
if domain == local_instance {
return Ok(());
}
- check_apub_id_valid(apub_id, local_site_data).map_err(LemmyError::from_message)?;
+
+ let local_site_data = local_site_data_cached(context.pool()).await?;
+ check_apub_id_valid(apub_id, &local_site_data).map_err(LemmyError::from_message)?;
// Only check allowlist if this is a community, and there are instances in the allowlist
if is_strict && !local_site_data.allowed_instances.is_empty() {
.iter()
.map(|i| i.domain.clone())
.collect::<Vec<String>>();
- let local_instance = settings
+ let local_instance = context
+ .settings()
.get_hostname_without_port()
.expect("local hostname is valid");
allowed_and_local.push(local_instance);
use crate::{
activities::{verify_is_public, verify_person_in_community},
check_apub_id_valid_with_strictness,
- fetch_local_site_data,
mentions::collect_non_local_mentions,
objects::{read_from_string_or_source, verify_is_remote_object},
protocol::{
verify_domains_match(note.attributed_to.inner(), note.id.inner())?;
verify_is_public(¬e.to, ¬e.cc)?;
let community = note.community(context).await?;
- let local_site_data = fetch_local_site_data(context.pool()).await?;
- check_apub_id_valid_with_strictness(
- note.id.inner(),
- community.local,
- &local_site_data,
- context.settings(),
- )?;
+ check_apub_id_valid_with_strictness(note.id.inner(), community.local, context).await?;
verify_is_remote_object(note.id.inner(), context.settings())?;
verify_person_in_community(¬e.attributed_to, &community, context).await?;
let (post, _) = note.get_parents(context).await?;
use crate::{
- check_apub_id_valid_with_strictness,
- fetch_local_site_data,
+ check_apub_id_valid,
+ local_site_data_cached,
objects::instance::fetch_instance_actor_for_object,
protocol::{
objects::{group::Group, Endpoints, LanguageTag},
) -> Result<Vec<Url>, LemmyError> {
let id = self.id;
- let local_site_data = fetch_local_site_data(context.pool()).await?;
+ let local_site_data = local_site_data_cached(context.pool()).await?;
let follows = CommunityFollowerView::for_community(context.pool(), id).await?;
let inboxes: Vec<Url> = follows
.into_iter()
.unique()
.filter(|inbox: &Url| inbox.host_str() != Some(&context.settings().hostname))
// Don't send to blocked instances
- .filter(|inbox| {
- check_apub_id_valid_with_strictness(inbox, false, &local_site_data, context.settings())
- .is_ok()
- })
+ .filter(|inbox| check_apub_id_valid(inbox, &local_site_data).is_ok())
.collect();
Ok(inboxes)
use crate::{
check_apub_id_valid_with_strictness,
- fetch_local_site_data,
+ local_site_data_cached,
objects::read_from_string_or_source_opt,
protocol::{
objects::{instance::Instance, LanguageTag},
expected_domain: &Url,
data: &Data<Self::DataType>,
) -> Result<(), LemmyError> {
- let local_site_data = fetch_local_site_data(data.pool()).await?;
-
- check_apub_id_valid_with_strictness(apub.id.inner(), true, &local_site_data, data.settings())?;
+ check_apub_id_valid_with_strictness(apub.id.inner(), true, data).await?;
verify_domains_match(expected_domain, apub.id.inner())?;
+ let local_site_data = local_site_data_cached(data.pool()).await?;
let slur_regex = &local_site_opt_to_slur_regex(&local_site_data.local_site);
-
check_slurs(&apub.name, slur_regex)?;
check_slurs_opt(&apub.summary, slur_regex)?;
+
Ok(())
}
use crate::{
check_apub_id_valid_with_strictness,
- fetch_local_site_data,
+ local_site_data_cached,
objects::{instance::fetch_instance_actor_for_object, read_from_string_or_source_opt},
protocol::{
objects::{
expected_domain: &Url,
context: &Data<Self::DataType>,
) -> Result<(), LemmyError> {
- let local_site_data = fetch_local_site_data(context.pool()).await?;
+ let local_site_data = local_site_data_cached(context.pool()).await?;
let slur_regex = &local_site_opt_to_slur_regex(&local_site_data.local_site);
-
check_slurs(&person.preferred_username, slur_regex)?;
check_slurs_opt(&person.name, slur_regex)?;
verify_domains_match(person.id.inner(), expected_domain)?;
- check_apub_id_valid_with_strictness(
- person.id.inner(),
- false,
- &local_site_data,
- context.settings(),
- )?;
+ check_apub_id_valid_with_strictness(person.id.inner(), false, context).await?;
let bio = read_from_string_or_source_opt(&person.summary, &None, &person.source);
check_slurs_opt(&bio, slur_regex)?;
use crate::{
activities::{verify_is_public, verify_person_in_community},
check_apub_id_valid_with_strictness,
- fetch_local_site_data,
+ local_site_data_cached,
objects::{read_from_string_or_source_opt, verify_is_remote_object},
protocol::{
objects::{
verify_is_remote_object(page.id.inner(), context.settings())?;
};
- let local_site_data = fetch_local_site_data(context.pool()).await?;
-
let community = page.community(context).await?;
- check_apub_id_valid_with_strictness(
- page.id.inner(),
- community.local,
- &local_site_data,
- context.settings(),
- )?;
+ check_apub_id_valid_with_strictness(page.id.inner(), community.local, context).await?;
verify_person_in_community(&page.creator()?, &community, context).await?;
+ let local_site_data = local_site_data_cached(context.pool()).await?;
let slur_regex = &local_site_opt_to_slur_regex(&local_site_data.local_site);
check_slurs_opt(&page.name, slur_regex)?;
use crate::{
check_apub_id_valid_with_strictness,
- fetch_local_site_data,
objects::read_from_string_or_source,
protocol::{
objects::chat_message::{ChatMessage, ChatMessageType},
verify_domains_match(note.id.inner(), expected_domain)?;
verify_domains_match(note.attributed_to.inner(), note.id.inner())?;
- let local_site_data = fetch_local_site_data(context.pool()).await?;
-
- check_apub_id_valid_with_strictness(
- note.id.inner(),
- false,
- &local_site_data,
- context.settings(),
- )?;
+ check_apub_id_valid_with_strictness(note.id.inner(), false, context).await?;
let person = note.attributed_to.dereference(context).await?;
if person.banned {
return Err(LemmyError::from_message("Person is banned from site"));
community_moderators::ApubCommunityModerators,
community_outbox::ApubCommunityOutbox,
},
- fetch_local_site_data,
+ local_site_data_cached,
objects::{community::ApubCommunity, read_from_string_or_source_opt},
protocol::{
objects::{Endpoints, LanguageTag},
expected_domain: &Url,
context: &LemmyContext,
) -> Result<(), LemmyError> {
- let local_site_data = fetch_local_site_data(context.pool()).await?;
-
- check_apub_id_valid_with_strictness(
- self.id.inner(),
- true,
- &local_site_data,
- context.settings(),
- )?;
+ check_apub_id_valid_with_strictness(self.id.inner(), true, context).await?;
verify_domains_match(expected_domain, self.id.inner())?;
+ let local_site_data = local_site_data_cached(context.pool()).await?;
let slur_regex = &local_site_opt_to_slur_regex(&local_site_data.local_site);
check_slurs(&self.preferred_username, slur_regex)?;