diff --git a/.drone.yml b/.drone.yml
index 382dfb924..001714545 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -80,7 +80,7 @@ steps:
- name: publish release docker manifest
image: plugins/manifest
- settings:
+ settings:
username:
from_secret: docker_username
password:
@@ -95,6 +95,23 @@ steps:
ref:
- refs/tags/*
+ - name: publish latest release docker manifest
+ image: plugins/manifest
+ settings:
+ username:
+ from_secret: docker_username
+ password:
+ from_secret: docker_password
+ target: "dessalines/lemmy:latest"
+ template: "dessalines/lemmy:${DRONE_TAG}-OS-ARCH"
+ platforms:
+ - linux/amd64
+ - linux/arm64
+ ignore_missing: true
+ when:
+ ref:
+ - refs/tags/*
+
# using https://github.com/pksunkara/cargo-workspaces
- name: publish to crates.io
image: rustlang/rust:nightly
@@ -192,7 +209,7 @@ steps:
- name: publish release docker manifest
image: plugins/manifest
- settings:
+ settings:
username:
from_secret: docker_username
password:
@@ -207,6 +224,23 @@ steps:
ref:
- refs/tags/*
+ - name: publish latest release docker manifest
+ image: plugins/manifest
+ settings:
+ username:
+ from_secret: docker_username
+ password:
+ from_secret: docker_password
+ target: "dessalines/lemmy:latest"
+ template: "dessalines/lemmy:${DRONE_TAG}-OS-ARCH"
+ platforms:
+ - linux/amd64
+ - linux/arm64
+ ignore_missing: true
+ when:
+ ref:
+ - refs/tags/*
+
# TODO temporarily disable arm tests
# services:
# - name: database
diff --git a/Cargo.lock b/Cargo.lock
index d6fd15a7f..5e879b8a2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1722,7 +1722,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lemmy_api"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"actix",
"actix-rt",
@@ -1765,7 +1765,7 @@ dependencies = [
[[package]]
name = "lemmy_api_common"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"actix-web",
"chrono",
@@ -1782,7 +1782,7 @@ dependencies = [
[[package]]
name = "lemmy_api_crud"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"actix",
"actix-rt",
@@ -1826,7 +1826,7 @@ dependencies = [
[[package]]
name = "lemmy_apub"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"activitystreams-kinds",
"actix",
@@ -1872,7 +1872,7 @@ dependencies = [
[[package]]
name = "lemmy_apub_lib"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"activitystreams",
"actix-web",
@@ -1898,7 +1898,7 @@ dependencies = [
[[package]]
name = "lemmy_apub_lib_derive"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"proc-macro2 1.0.32",
"quote 1.0.10",
@@ -1908,7 +1908,7 @@ dependencies = [
[[package]]
name = "lemmy_db_schema"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"bcrypt",
"chrono",
@@ -1930,7 +1930,7 @@ dependencies = [
[[package]]
name = "lemmy_db_views"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"diesel",
"lemmy_db_schema",
@@ -1942,7 +1942,7 @@ dependencies = [
[[package]]
name = "lemmy_db_views_actor"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"diesel",
"lemmy_db_schema",
@@ -1951,7 +1951,7 @@ dependencies = [
[[package]]
name = "lemmy_db_views_moderator"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"diesel",
"lemmy_db_schema",
@@ -1960,7 +1960,7 @@ dependencies = [
[[package]]
name = "lemmy_routes"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"actix",
"actix-http",
@@ -1987,7 +1987,7 @@ dependencies = [
[[package]]
name = "lemmy_server"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"activitystreams",
"actix",
@@ -2029,7 +2029,7 @@ dependencies = [
[[package]]
name = "lemmy_utils"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"actix-rt",
"actix-web",
@@ -2066,7 +2066,7 @@ dependencies = [
[[package]]
name = "lemmy_websocket"
-version = "0.14.3"
+version = "0.14.4-rc.4"
dependencies = [
"actix",
"actix-web",
diff --git a/Cargo.toml b/Cargo.toml
index 1a5c07cb2..0d38c2e7f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_server"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
@@ -31,18 +31,18 @@ members = [
]
[dependencies]
-lemmy_api = { version = "=0.14.3", path = "./crates/api" }
-lemmy_api_crud = { version = "=0.14.3", path = "./crates/api_crud" }
-lemmy_apub = { version = "=0.14.3", path = "./crates/apub" }
-lemmy_apub_lib = { version = "=0.14.3", path = "./crates/apub_lib" }
-lemmy_utils = { version = "=0.14.3", path = "./crates/utils" }
-lemmy_db_schema = { version = "=0.14.3", path = "./crates/db_schema" }
-lemmy_db_views = { version = "=0.14.3", path = "./crates/db_views" }
-lemmy_db_views_moderator = { version = "=0.14.3", path = "./crates/db_views_moderator" }
-lemmy_db_views_actor = { version = "=0.14.3", path = "./crates/db_views_actor" }
-lemmy_api_common = { version = "=0.14.3", path = "crates/api_common" }
-lemmy_websocket = { version = "=0.14.3", path = "./crates/websocket" }
-lemmy_routes = { version = "=0.14.3", path = "./crates/routes" }
+lemmy_api = { version = "=0.14.4-rc.4", path = "./crates/api" }
+lemmy_api_crud = { version = "=0.14.4-rc.4", path = "./crates/api_crud" }
+lemmy_apub = { version = "=0.14.4-rc.4", path = "./crates/apub" }
+lemmy_apub_lib = { version = "=0.14.4-rc.4", path = "./crates/apub_lib" }
+lemmy_utils = { version = "=0.14.4-rc.4", path = "./crates/utils" }
+lemmy_db_schema = { version = "=0.14.4-rc.4", path = "./crates/db_schema" }
+lemmy_db_views = { version = "=0.14.4-rc.4", path = "./crates/db_views" }
+lemmy_db_views_moderator = { version = "=0.14.4-rc.4", path = "./crates/db_views_moderator" }
+lemmy_db_views_actor = { version = "=0.14.4-rc.4", path = "./crates/db_views_actor" }
+lemmy_api_common = { version = "=0.14.4-rc.4", path = "crates/api_common" }
+lemmy_websocket = { version = "=0.14.4-rc.4", path = "./crates/websocket" }
+lemmy_routes = { version = "=0.14.4-rc.4", path = "./crates/routes" }
diesel = "1.4.8"
diesel_migrations = "1.4.0"
chrono = { version = "0.4.19", features = ["serde"] }
diff --git a/config/defaults.hjson b/config/defaults.hjson
index d894d25b3..2bae8855f 100644
--- a/config/defaults.hjson
+++ b/config/defaults.hjson
@@ -115,4 +115,6 @@
slur_filter: "(\bThis\b)|(\bis\b)|(\bsample\b)"
# Maximum length of local community and user names
actor_name_max_length: 20
+ # Maximum number of HTTP requests allowed to handle a single incoming activity (or a single object fetch through the search).
+ http_fetch_retry_limit: 25
}
diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml
index 823591454..96b47f464 100644
--- a/crates/api/Cargo.toml
+++ b/crates/api/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_api"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
@@ -13,15 +13,15 @@ path = "src/lib.rs"
doctest = false
[dependencies]
-lemmy_apub = { version = "=0.14.3", path = "../apub" }
-lemmy_apub_lib = { version = "=0.14.3", path = "../apub_lib" }
-lemmy_utils = { version = "=0.14.3", path = "../utils" }
-lemmy_db_schema = { version = "=0.14.3", path = "../db_schema" }
-lemmy_db_views = { version = "=0.14.3", path = "../db_views" }
-lemmy_db_views_moderator = { version = "=0.14.3", path = "../db_views_moderator" }
-lemmy_db_views_actor = { version = "=0.14.3", path = "../db_views_actor" }
-lemmy_api_common = { version = "=0.14.3", path = "../api_common" }
-lemmy_websocket = { version = "=0.14.3", path = "../websocket" }
+lemmy_apub = { version = "=0.14.4-rc.4", path = "../apub" }
+lemmy_apub_lib = { version = "=0.14.4-rc.4", path = "../apub_lib" }
+lemmy_utils = { version = "=0.14.4-rc.4", path = "../utils" }
+lemmy_db_schema = { version = "=0.14.4-rc.4", path = "../db_schema" }
+lemmy_db_views = { version = "=0.14.4-rc.4", path = "../db_views" }
+lemmy_db_views_moderator = { version = "=0.14.4-rc.4", path = "../db_views_moderator" }
+lemmy_db_views_actor = { version = "=0.14.4-rc.4", path = "../db_views_actor" }
+lemmy_api_common = { version = "=0.14.4-rc.4", path = "../api_common" }
+lemmy_websocket = { version = "=0.14.4-rc.4", path = "../websocket" }
diesel = "1.4.8"
bcrypt = "0.10.1"
chrono = { version = "0.4.19", features = ["serde"] }
diff --git a/crates/api_common/Cargo.toml b/crates/api_common/Cargo.toml
index 93290bb14..078987eb2 100644
--- a/crates/api_common/Cargo.toml
+++ b/crates/api_common/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_api_common"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
@@ -13,11 +13,11 @@ path = "src/lib.rs"
doctest = false
[dependencies]
-lemmy_db_views = { version = "=0.14.3", path = "../db_views" }
-lemmy_db_views_moderator = { version = "=0.14.3", path = "../db_views_moderator" }
-lemmy_db_views_actor = { version = "=0.14.3", path = "../db_views_actor" }
-lemmy_db_schema = { version = "=0.14.3", path = "../db_schema" }
-lemmy_utils = { version = "=0.14.3", path = "../utils" }
+lemmy_db_views = { version = "=0.14.4-rc.4", path = "../db_views" }
+lemmy_db_views_moderator = { version = "=0.14.4-rc.4", path = "../db_views_moderator" }
+lemmy_db_views_actor = { version = "=0.14.4-rc.4", path = "../db_views_actor" }
+lemmy_db_schema = { version = "=0.14.4-rc.4", path = "../db_schema" }
+lemmy_utils = { version = "=0.14.4-rc.4", path = "../utils" }
serde = { version = "1.0.130", features = ["derive"] }
diesel = "1.4.8"
actix-web = { version = "4.0.0-beta.9", default-features = false, features = ["cookies"] }
diff --git a/crates/api_crud/Cargo.toml b/crates/api_crud/Cargo.toml
index 33954e6ec..a6d116573 100644
--- a/crates/api_crud/Cargo.toml
+++ b/crates/api_crud/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_api_crud"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
@@ -8,15 +8,15 @@ homepage = "https://join-lemmy.org/"
documentation = "https://join-lemmy.org/docs/en/index.html"
[dependencies]
-lemmy_apub = { version = "=0.14.3", path = "../apub" }
-lemmy_apub_lib = { version = "=0.14.3", path = "../apub_lib" }
-lemmy_utils = { version = "=0.14.3", path = "../utils" }
-lemmy_db_schema = { version = "=0.14.3", path = "../db_schema" }
-lemmy_db_views = { version = "=0.14.3", path = "../db_views" }
-lemmy_db_views_moderator = { version = "=0.14.3", path = "../db_views_moderator" }
-lemmy_db_views_actor = { version = "=0.14.3", path = "../db_views_actor" }
-lemmy_api_common = { version = "=0.14.3", path = "../api_common" }
-lemmy_websocket = { version = "=0.14.3", path = "../websocket" }
+lemmy_apub = { version = "=0.14.4-rc.4", path = "../apub" }
+lemmy_apub_lib = { version = "=0.14.4-rc.4", path = "../apub_lib" }
+lemmy_utils = { version = "=0.14.4-rc.4", path = "../utils" }
+lemmy_db_schema = { version = "=0.14.4-rc.4", path = "../db_schema" }
+lemmy_db_views = { version = "=0.14.4-rc.4", path = "../db_views" }
+lemmy_db_views_moderator = { version = "=0.14.4-rc.4", path = "../db_views_moderator" }
+lemmy_db_views_actor = { version = "=0.14.4-rc.4", path = "../db_views_actor" }
+lemmy_api_common = { version = "=0.14.4-rc.4", path = "../api_common" }
+lemmy_websocket = { version = "=0.14.4-rc.4", path = "../websocket" }
diesel = "1.4.8"
bcrypt = "0.10.1"
chrono = { version = "0.4.19", features = ["serde"] }
diff --git a/crates/apub/Cargo.toml b/crates/apub/Cargo.toml
index 8a5b2edc4..fb4e5f100 100644
--- a/crates/apub/Cargo.toml
+++ b/crates/apub/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_apub"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
@@ -13,13 +13,13 @@ path = "src/lib.rs"
doctest = false
[dependencies]
-lemmy_utils = { version = "=0.14.3", path = "../utils" }
-lemmy_apub_lib = { version = "=0.14.3", path = "../apub_lib" }
-lemmy_db_schema = { version = "=0.14.3", path = "../db_schema" }
-lemmy_db_views = { version = "=0.14.3", path = "../db_views" }
-lemmy_db_views_actor = { version = "=0.14.3", path = "../db_views_actor" }
-lemmy_api_common = { version = "=0.14.3", path = "../api_common" }
-lemmy_websocket = { version = "=0.14.3", path = "../websocket" }
+lemmy_utils = { version = "=0.14.4-rc.4", path = "../utils" }
+lemmy_apub_lib = { version = "=0.14.4-rc.4", path = "../apub_lib" }
+lemmy_db_schema = { version = "=0.14.4-rc.4", path = "../db_schema" }
+lemmy_db_views = { version = "=0.14.4-rc.4", path = "../db_views" }
+lemmy_db_views_actor = { version = "=0.14.4-rc.4", path = "../db_views_actor" }
+lemmy_api_common = { version = "=0.14.4-rc.4", path = "../api_common" }
+lemmy_websocket = { version = "=0.14.4-rc.4", path = "../websocket" }
diesel = "1.4.8"
activitystreams-kinds = "0.1.2"
bcrypt = "0.10.1"
diff --git a/crates/apub/assets/lotide/activities/create_note_reply.json b/crates/apub/assets/lotide/activities/create_note_reply.json
new file mode 100644
index 000000000..b6b2a13fa
--- /dev/null
+++ b/crates/apub/assets/lotide/activities/create_note_reply.json
@@ -0,0 +1,30 @@
+{
+ "actor": "https://c.tide.tk/users/1",
+ "object": {
+ "@context": "https://www.w3.org/ns/activitystreams",
+ "id": "https://c.tide.tk/comments/52",
+ "type": "Note",
+ "mediaType": "text/html",
+ "source": {
+ "content": "test comment",
+ "mediaType": "text/markdown"
+ },
+ "attributedTo": "https://c.tide.tk/users/1",
+ "content": "
test comment
\n",
+ "published": "2021-09-16T01:20:27.558063+00:00",
+ "inReplyTo": "https://c.tide.tk/posts/51",
+ "to": "https://c.tide.tk/users/1",
+ "cc": [
+ "https://www.w3.org/ns/activitystreams#Public",
+ "https://c.tide.tk/communities/1"
+ ]
+ },
+ "to": "https://c.tide.tk/users/1",
+ "cc": [
+ "https://www.w3.org/ns/activitystreams#Public",
+ "https://c.tide.tk/communities/1"
+ ],
+ "@context": "https://www.w3.org/ns/activitystreams",
+ "id": "https://c.tide.tk/comments/52/create",
+ "type": "Create"
+}
diff --git a/crates/apub/assets/lotide/activities/create_page.json b/crates/apub/assets/lotide/activities/create_page.json
new file mode 100644
index 000000000..d39e42553
--- /dev/null
+++ b/crates/apub/assets/lotide/activities/create_page.json
@@ -0,0 +1,20 @@
+{
+ "actor": "https://b.tide.tk/apub/users/1",
+ "object": {
+ "@context": "https://www.w3.org/ns/activitystreams",
+ "id": "https://b.tide.tk/apub/posts/60",
+ "type": "Page",
+ "name": "test post from b",
+ "summary": "test post from b",
+ "to": "https://c.tide.tk/communities/1",
+ "cc": "https://www.w3.org/ns/activitystreams#Public",
+ "published": "2020-12-19T19:20:26.941381+00:00",
+ "attributedTo": "https://b.tide.tk/apub/users/1",
+ "url": "https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake.html"
+ },
+ "to": "https://c.tide.tk/communities/1",
+ "cc": "https://www.w3.org/ns/activitystreams#Public",
+ "@context": "https://www.w3.org/ns/activitystreams",
+ "id": "https://b.tide.tk/apub/posts/60/create",
+ "type": "Create"
+}
diff --git a/crates/apub/src/activities/comment/create_or_update.rs b/crates/apub/src/activities/comment/create_or_update.rs
index 14fc14014..649f566c2 100644
--- a/crates/apub/src/activities/comment/create_or_update.rs
+++ b/crates/apub/src/activities/comment/create_or_update.rs
@@ -108,7 +108,15 @@ impl ActivityHandler for CreateOrUpdateComment {
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let comment = ApubComment::from_apub(self.object, context, request_counter).await?;
- let recipients = get_notif_recipients(&self.actor, &comment, context, request_counter).await?;
+ let do_send_email = self.kind == CreateOrUpdateType::Create;
+ let recipients = get_notif_recipients(
+ &self.actor,
+ &comment,
+ do_send_email,
+ context,
+ request_counter,
+ )
+ .await?;
let notif_type = match self.kind {
CreateOrUpdateType::Create => UserOperationCrud::CreateComment,
CreateOrUpdateType::Update => UserOperationCrud::EditComment,
diff --git a/crates/apub/src/activities/comment/mod.rs b/crates/apub/src/activities/comment/mod.rs
index b42538587..17b4f50cf 100644
--- a/crates/apub/src/activities/comment/mod.rs
+++ b/crates/apub/src/activities/comment/mod.rs
@@ -14,6 +14,7 @@ pub mod create_or_update;
async fn get_notif_recipients(
actor: &ObjectId,
comment: &Comment,
+ do_send_email: bool,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result, LemmyError> {
@@ -27,5 +28,5 @@ async fn get_notif_recipients(
// anyway.
// TODO: for compatibility with other projects, it would be much better to read this from cc or tags
let mentions = scrape_text_for_mentions(&comment.content);
- send_local_notifs(mentions, comment, &*actor, &post, true, context).await
+ send_local_notifs(mentions, comment, &*actor, &post, do_send_email, context).await
}
diff --git a/crates/apub/src/context.rs b/crates/apub/src/context.rs
index 3ec444e33..9d2d3d42c 100644
--- a/crates/apub/src/context.rs
+++ b/crates/apub/src/context.rs
@@ -8,6 +8,7 @@ static CONTEXT: Lazy> = Lazy::new(|| {
#[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,
diff --git a/crates/apub/src/fetcher/webfinger.rs b/crates/apub/src/fetcher/webfinger.rs
index 93986a50f..b44030b06 100644
--- a/crates/apub/src/fetcher/webfinger.rs
+++ b/crates/apub/src/fetcher/webfinger.rs
@@ -81,6 +81,11 @@ where
);
debug!("Fetching webfinger url: {}", &fetch_url);
+ *request_counter += 1;
+ if *request_counter > context.settings().http_fetch_retry_limit {
+ return Err(LemmyError::from(anyhow!("Request retry limit reached")));
+ }
+
let response = retry(|| context.client().get(&fetch_url).send()).await?;
let res: WebfingerResponse = response
diff --git a/crates/apub/src/lib.rs b/crates/apub/src/lib.rs
index 984d722e8..b3c7eff72 100644
--- a/crates/apub/src/lib.rs
+++ b/crates/apub/src/lib.rs
@@ -3,6 +3,7 @@ use anyhow::{anyhow, Context};
use lemmy_api_common::blocking;
use lemmy_db_schema::{newtypes::DbUrl, source::activity::Activity, DbPool};
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
+use serde::{Deserialize, Deserializer};
use std::net::IpAddr;
use url::{ParseError, Url};
@@ -85,6 +86,25 @@ pub(crate) fn check_is_apub_id_valid(
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),
+ }
+
+ let result: OneOrMany = Deserialize::deserialize(deserializer)?;
+ Ok(match result {
+ OneOrMany::Many(list) => list,
+ OneOrMany::One(value) => vec![value],
+ })
+}
+
pub enum EndpointType {
Community,
Person,
diff --git a/crates/apub/src/protocol/activities/community/add_mod.rs b/crates/apub/src/protocol/activities/community/add_mod.rs
index 0d6edc0a6..915c24668 100644
--- a/crates/apub/src/protocol/activities/community/add_mod.rs
+++ b/crates/apub/src/protocol/activities/community/add_mod.rs
@@ -8,9 +8,11 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct AddMod {
pub(crate) actor: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec,
pub(crate) object: ObjectId,
pub(crate) target: Url,
+ #[serde(deserialize_with = "crate::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 11890c680..0bda9ebc5 100644
--- a/crates/apub/src/protocol/activities/community/announce.rs
+++ b/crates/apub/src/protocol/activities/community/announce.rs
@@ -12,8 +12,10 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct AnnounceActivity {
pub(crate) actor: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec,
pub(crate) object: AnnouncableActivities,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec,
#[serde(rename = "type")]
pub(crate) kind: AnnounceType,
diff --git a/crates/apub/src/protocol/activities/community/block_user.rs b/crates/apub/src/protocol/activities/community/block_user.rs
index c904fc218..ecde0ce3a 100644
--- a/crates/apub/src/protocol/activities/community/block_user.rs
+++ b/crates/apub/src/protocol/activities/community/block_user.rs
@@ -11,8 +11,10 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct BlockUserFromCommunity {
pub(crate) actor: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec,
pub(crate) object: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec,
pub(crate) target: ObjectId,
#[serde(rename = "type")]
diff --git a/crates/apub/src/protocol/activities/community/remove_mod.rs b/crates/apub/src/protocol/activities/community/remove_mod.rs
index dc456b0b0..74619c81d 100644
--- a/crates/apub/src/protocol/activities/community/remove_mod.rs
+++ b/crates/apub/src/protocol/activities/community/remove_mod.rs
@@ -8,8 +8,10 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct RemoveMod {
pub(crate) actor: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec,
pub(crate) object: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec,
#[serde(rename = "type")]
pub(crate) kind: RemoveType,
diff --git a/crates/apub/src/protocol/activities/community/undo_block_user.rs b/crates/apub/src/protocol/activities/community/undo_block_user.rs
index f08e0c352..02218367b 100644
--- a/crates/apub/src/protocol/activities/community/undo_block_user.rs
+++ b/crates/apub/src/protocol/activities/community/undo_block_user.rs
@@ -11,8 +11,10 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoBlockUserFromCommunity {
pub(crate) actor: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec,
pub(crate) object: BlockUserFromCommunity,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec,
#[serde(rename = "type")]
pub(crate) kind: UndoType,
diff --git a/crates/apub/src/protocol/activities/community/update.rs b/crates/apub/src/protocol/activities/community/update.rs
index 9bdcded9a..bb9b56114 100644
--- a/crates/apub/src/protocol/activities/community/update.rs
+++ b/crates/apub/src/protocol/activities/community/update.rs
@@ -13,9 +13,11 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UpdateCommunity {
pub(crate) actor: ObjectId,
+ #[serde(deserialize_with = "crate::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")]
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 deef4c862..091c0f97c 100644
--- a/crates/apub/src/protocol/activities/create_or_update/comment.rs
+++ b/crates/apub/src/protocol/activities/create_or_update/comment.rs
@@ -11,8 +11,10 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct CreateOrUpdateComment {
pub(crate) actor: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec,
pub(crate) object: Note,
+ #[serde(deserialize_with = "crate::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/mod.rs b/crates/apub/src/protocol/activities/create_or_update/mod.rs
index 6506c283b..63ddcf967 100644
--- a/crates/apub/src/protocol/activities/create_or_update/mod.rs
+++ b/crates/apub/src/protocol/activities/create_or_update/mod.rs
@@ -26,5 +26,8 @@ mod tests {
file_to_json_object::("assets/pleroma/activities/create_note.json");
file_to_json_object::("assets/smithereen/activities/create_note.json");
file_to_json_object::("assets/mastodon/activities/create_note.json");
+
+ file_to_json_object::("assets/lotide/activities/create_page.json");
+ file_to_json_object::("assets/lotide/activities/create_note_reply.json");
}
}
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 db159c860..2061c8815 100644
--- a/crates/apub/src/protocol/activities/create_or_update/post.rs
+++ b/crates/apub/src/protocol/activities/create_or_update/post.rs
@@ -10,8 +10,10 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct CreateOrUpdatePost {
pub(crate) actor: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec,
pub(crate) object: Page,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec,
#[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 49adb6e65..a999e58ec 100644
--- a/crates/apub/src/protocol/activities/deletion/delete.rs
+++ b/crates/apub/src/protocol/activities/deletion/delete.rs
@@ -13,6 +13,7 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct Delete {
pub(crate) actor: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec,
pub(crate) object: Tombstone,
#[serde(rename = "type")]
diff --git a/crates/apub/src/protocol/activities/deletion/undo_delete.rs b/crates/apub/src/protocol/activities/deletion/undo_delete.rs
index d76080170..ebd51f964 100644
--- a/crates/apub/src/protocol/activities/deletion/undo_delete.rs
+++ b/crates/apub/src/protocol/activities/deletion/undo_delete.rs
@@ -11,8 +11,10 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoDelete {
pub(crate) actor: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec,
pub(crate) object: Delete,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec,
#[serde(rename = "type")]
pub(crate) kind: UndoType,
diff --git a/crates/apub/src/protocol/activities/voting/undo_vote.rs b/crates/apub/src/protocol/activities/voting/undo_vote.rs
index 9a1767f2a..d3f4fb337 100644
--- a/crates/apub/src/protocol/activities/voting/undo_vote.rs
+++ b/crates/apub/src/protocol/activities/voting/undo_vote.rs
@@ -11,8 +11,10 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct UndoVote {
pub(crate) actor: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec,
pub(crate) object: Vote,
+ #[serde(deserialize_with = "crate::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 065e3b31f..ba5c629ce 100644
--- a/crates/apub/src/protocol/activities/voting/vote.rs
+++ b/crates/apub/src/protocol/activities/voting/vote.rs
@@ -15,8 +15,10 @@ use url::Url;
#[serde(rename_all = "camelCase")]
pub struct Vote {
pub(crate) actor: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec,
pub(crate) object: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec,
#[serde(rename = "type")]
pub(crate) kind: VoteType,
diff --git a/crates/apub/src/protocol/objects/note.rs b/crates/apub/src/protocol/objects/note.rs
index be21f8f57..39c606b00 100644
--- a/crates/apub/src/protocol/objects/note.rs
+++ b/crates/apub/src/protocol/objects/note.rs
@@ -23,8 +23,10 @@ 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")]
pub(crate) to: Vec,
#[serde(default)]
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec,
pub(crate) content: String,
pub(crate) media_type: Option,
diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs
index 2bd5cc6dd..1fca51e45 100644
--- a/crates/apub/src/protocol/objects/page.rs
+++ b/crates/apub/src/protocol/objects/page.rs
@@ -24,8 +24,10 @@ pub struct Page {
pub(crate) r#type: PageType,
pub(crate) id: ObjectId,
pub(crate) attributed_to: ObjectId,
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) to: Vec,
#[serde(default)]
+ #[serde(deserialize_with = "crate::deserialize_one_or_many")]
pub(crate) cc: Vec,
pub(crate) name: String,
pub(crate) content: Option,
diff --git a/crates/apub_lib/Cargo.toml b/crates/apub_lib/Cargo.toml
index 66ec3fc48..611c9fbc3 100644
--- a/crates/apub_lib/Cargo.toml
+++ b/crates/apub_lib/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_apub_lib"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
@@ -8,8 +8,8 @@ homepage = "https://join-lemmy.org/"
documentation = "https://join-lemmy.org/docs/en/index.html"
[dependencies]
-lemmy_utils = { version = "=0.14.3", path = "../utils" }
-lemmy_apub_lib_derive = { version = "=0.14.3", path = "../apub_lib_derive" }
+lemmy_utils = { version = "=0.14.4-rc.4", path = "../utils" }
+lemmy_apub_lib_derive = { version = "=0.14.4-rc.4", path = "../apub_lib_derive" }
activitystreams = "0.7.0-alpha.11"
serde = { version = "1.0.130", features = ["derive"] }
async-trait = "0.1.51"
diff --git a/crates/apub_lib/src/object_id.rs b/crates/apub_lib/src/object_id.rs
index 59898e669..e8d0bd6d2 100644
--- a/crates/apub_lib/src/object_id.rs
+++ b/crates/apub_lib/src/object_id.rs
@@ -18,10 +18,6 @@ use std::{
use tracing::info;
use url::Url;
-/// Maximum number of HTTP requests allowed to handle a single incoming activity (or a single object
-/// fetch through the search). This should be configurable.
-static REQUEST_LIMIT: i32 = 25;
-
static CLIENT: Lazy = Lazy::new(|| {
Client::builder()
.user_agent(build_user_agent(&Settings::get()))
@@ -119,8 +115,8 @@ where
info!("Fetching remote object {}", self.to_string());
*request_counter += 1;
- if *request_counter > REQUEST_LIMIT {
- return Err(LemmyError::from(anyhow!("Request limit reached")));
+ if *request_counter > Settings::get().http_fetch_retry_limit {
+ return Err(LemmyError::from(anyhow!("Request retry limit reached")));
}
let res = retry(|| {
diff --git a/crates/apub_lib_derive/Cargo.toml b/crates/apub_lib_derive/Cargo.toml
index 176e47b90..7fad6cfe2 100644
--- a/crates/apub_lib_derive/Cargo.toml
+++ b/crates/apub_lib_derive/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_apub_lib_derive"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml
index 2cdf74b01..3134faaf4 100644
--- a/crates/db_schema/Cargo.toml
+++ b/crates/db_schema/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_db_schema"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
@@ -11,8 +11,8 @@ documentation = "https://join-lemmy.org/docs/en/index.html"
doctest = false
[dependencies]
-lemmy_utils = { version = "=0.14.3", path = "../utils" }
-lemmy_apub_lib = { version = "=0.14.3", path = "../apub_lib" }
+lemmy_utils = { version = "=0.14.4-rc.4", path = "../utils" }
+lemmy_apub_lib = { version = "=0.14.4-rc.4", path = "../apub_lib" }
diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"] }
diesel_migrations = "1.4.0"
chrono = { version = "0.4.19", features = ["serde"] }
diff --git a/crates/db_views/Cargo.toml b/crates/db_views/Cargo.toml
index c831bcd28..4c4d31a6c 100644
--- a/crates/db_views/Cargo.toml
+++ b/crates/db_views/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_db_views"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
@@ -11,7 +11,7 @@ documentation = "https://join-lemmy.org/docs/en/index.html"
doctest = false
[dependencies]
-lemmy_db_schema = { version = "=0.14.3", path = "../db_schema" }
+lemmy_db_schema = { version = "=0.14.4-rc.4", path = "../db_schema" }
diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"] }
serde = { version = "1.0.130", features = ["derive"] }
tracing = "0.1.29"
diff --git a/crates/db_views_actor/Cargo.toml b/crates/db_views_actor/Cargo.toml
index 36a29081c..9eba071e8 100644
--- a/crates/db_views_actor/Cargo.toml
+++ b/crates/db_views_actor/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_db_views_actor"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
@@ -11,6 +11,6 @@ documentation = "https://join-lemmy.org/docs/en/index.html"
doctest = false
[dependencies]
-lemmy_db_schema = { version = "=0.14.3", path = "../db_schema" }
+lemmy_db_schema = { version = "=0.14.4-rc.4", path = "../db_schema" }
diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"] }
serde = { version = "1.0.130", features = ["derive"] }
diff --git a/crates/db_views_moderator/Cargo.toml b/crates/db_views_moderator/Cargo.toml
index 9128a955e..f22435fa0 100644
--- a/crates/db_views_moderator/Cargo.toml
+++ b/crates/db_views_moderator/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_db_views_moderator"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
@@ -11,6 +11,6 @@ documentation = "https://join-lemmy.org/docs/en/index.html"
doctest = false
[dependencies]
-lemmy_db_schema = { version = "=0.14.3", path = "../db_schema" }
+lemmy_db_schema = { version = "=0.14.4-rc.4", path = "../db_schema" }
diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"] }
serde = { version = "1.0.130", features = ["derive"] }
diff --git a/crates/routes/Cargo.toml b/crates/routes/Cargo.toml
index eee841846..c187ead65 100644
--- a/crates/routes/Cargo.toml
+++ b/crates/routes/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_routes"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
@@ -11,13 +11,13 @@ documentation = "https://join-lemmy.org/docs/en/index.html"
doctest = false
[dependencies]
-lemmy_utils = { version = "=0.14.3", path = "../utils" }
-lemmy_websocket = { version = "=0.14.3", path = "../websocket" }
-lemmy_db_views = { version = "=0.14.3", path = "../db_views" }
-lemmy_db_views_actor = { version = "=0.14.3", path = "../db_views_actor" }
-lemmy_db_schema = { version = "=0.14.3", path = "../db_schema" }
-lemmy_api_common = { version = "=0.14.3", path = "../api_common" }
-lemmy_apub = { version = "=0.14.3", path = "../apub" }
+lemmy_utils = { version = "=0.14.4-rc.4", path = "../utils" }
+lemmy_websocket = { version = "=0.14.4-rc.4", path = "../websocket" }
+lemmy_db_views = { version = "=0.14.4-rc.4", path = "../db_views" }
+lemmy_db_views_actor = { version = "=0.14.4-rc.4", path = "../db_views_actor" }
+lemmy_db_schema = { version = "=0.14.4-rc.4", path = "../db_schema" }
+lemmy_api_common = { version = "=0.14.4-rc.4", path = "../api_common" }
+lemmy_apub = { version = "=0.14.4-rc.4", path = "../apub" }
diesel = "1.4.8"
actix = "0.12.0"
actix-web = { version = "4.0.0-beta.9", default-features = false, features = ["rustls"] }
diff --git a/crates/routes/src/nodeinfo.rs b/crates/routes/src/nodeinfo.rs
index b30b9f977..0f2cf04c3 100644
--- a/crates/routes/src/nodeinfo.rs
+++ b/crates/routes/src/nodeinfo.rs
@@ -1,4 +1,4 @@
-use actix_web::{body::Body, error::ErrorBadRequest, *};
+use actix_web::{body::AnyBody, error::ErrorBadRequest, *};
use anyhow::anyhow;
use lemmy_api_common::blocking;
use lemmy_db_views::site_view::SiteView;
@@ -15,7 +15,7 @@ pub fn config(cfg: &mut web::ServiceConfig) {
async fn node_info_well_known(
context: web::Data,
-) -> Result, LemmyError> {
+) -> Result, LemmyError> {
let node_info = NodeInfoWellKnown {
links: vec![NodeInfoWellKnownLinks {
rel: Url::parse("http://nodeinfo.diaspora.software/ns/schema/2.0")?,
diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml
index e30df0481..3bd4a0ea8 100644
--- a/crates/utils/Cargo.toml
+++ b/crates/utils/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_utils"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
diff --git a/crates/utils/src/request.rs b/crates/utils/src/request.rs
index c2434f86b..88680c080 100644
--- a/crates/utils/src/request.rs
+++ b/crates/utils/src/request.rs
@@ -58,7 +58,7 @@ pub struct SiteMetadata {
/// Fetches the post link html tags (like title, description, image, etc)
pub async fn fetch_site_metadata(client: &Client, url: &Url) -> Result {
- let response = retry(|| client.get(url.as_str()).send()).await?;
+ let response = client.get(url.as_str()).send().await?;
let html = response
.text()
@@ -132,7 +132,7 @@ pub(crate) async fn fetch_pictrs(
utf8_percent_encode(image_url.as_str(), NON_ALPHANUMERIC) // TODO this might not be needed
);
- let response = retry(|| client.get(&fetch_url).send()).await?;
+ let response = client.get(&fetch_url).send().await?;
let response: PictrsResponse = response
.json()
@@ -201,8 +201,8 @@ pub async fn fetch_site_data(
}
}
-async fn is_image_content_type(client: &Client, test: &Url) -> Result<(), LemmyError> {
- let response = retry(|| client.get(test.to_owned()).send()).await?;
+async fn is_image_content_type(client: &Client, url: &Url) -> Result<(), LemmyError> {
+ let response = client.get(url.as_str()).send().await?;
if response
.headers()
.get("Content-Type")
diff --git a/crates/utils/src/settings/structs.rs b/crates/utils/src/settings/structs.rs
index 8f0085e93..23d717307 100644
--- a/crates/utils/src/settings/structs.rs
+++ b/crates/utils/src/settings/structs.rs
@@ -46,6 +46,9 @@ pub struct Settings {
/// Maximum length of local community and user names
#[default(20)]
pub actor_name_max_length: usize,
+ /// Maximum number of HTTP requests allowed to handle a single incoming activity (or a single object fetch through the search).
+ #[default(25)]
+ pub http_fetch_retry_limit: i32,
}
#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)]
diff --git a/crates/websocket/Cargo.toml b/crates/websocket/Cargo.toml
index 6e9a7bf91..0ee04c86e 100644
--- a/crates/websocket/Cargo.toml
+++ b/crates/websocket/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lemmy_websocket"
-version = "0.14.3"
+version = "0.14.4-rc.4"
edition = "2018"
description = "A link aggregator for the fediverse"
license = "AGPL-3.0"
@@ -13,11 +13,11 @@ path = "src/lib.rs"
doctest = false
[dependencies]
-lemmy_utils = { version = "=0.14.3", path = "../utils" }
-lemmy_api_common = { version = "=0.14.3", path = "../api_common" }
-lemmy_db_schema = { version = "=0.14.3", path = "../db_schema" }
-lemmy_db_views = { version = "=0.14.3", path = "../db_views" }
-lemmy_db_views_actor = { version = "=0.14.3", path = "../db_views_actor" }
+lemmy_utils = { version = "=0.14.4-rc.4", path = "../utils" }
+lemmy_api_common = { version = "=0.14.4-rc.4", path = "../api_common" }
+lemmy_db_schema = { version = "=0.14.4-rc.4", path = "../db_schema" }
+lemmy_db_views = { version = "=0.14.4-rc.4", path = "../db_views" }
+lemmy_db_views_actor = { version = "=0.14.4-rc.4", path = "../db_views_actor" }
reqwest = { version = "0.11.4", features = ["json"] }
tracing = "0.1.29"
rand = "0.8.4"
diff --git a/crates/websocket/src/chat_server.rs b/crates/websocket/src/chat_server.rs
index 9fa258ff4..2b58b2c1e 100644
--- a/crates/websocket/src/chat_server.rs
+++ b/crates/websocket/src/chat_server.rs
@@ -491,7 +491,10 @@ impl ChatServer {
} else {
let user_operation = UserOperation::from_str(op)?;
let fut = (message_handler)(context, msg.id, user_operation.clone(), data);
- rate_limiter.message().wrap(ip, fut).await
+ match user_operation {
+ UserOperation::GetCaptcha => rate_limiter.post().wrap(ip, fut).await,
+ _ => rate_limiter.message().wrap(ip, fut).await,
+ }
}
}
}
diff --git a/src/api_routes.rs b/src/api_routes.rs
index 6e3b368f7..35458d67a 100644
--- a/src/api_routes.rs
+++ b/src/api_routes.rs
@@ -161,6 +161,12 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
.wrap(rate_limit.register())
.route(web::post().to(route_post_crud::)),
)
+ .service(
+ // Handle captcha separately
+ web::resource("/user/get_captcha")
+ .wrap(rate_limit.post())
+ .route(web::get().to(route_get::)),
+ )
// User actions
.service(
web::scope("/user")
@@ -178,7 +184,6 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
.route("/block", web::post().to(route_post::))
// Account actions. I don't like that they're in /user maybe /accounts
.route("/login", web::post().to(route_post::))
- .route("/get_captcha", web::get().to(route_get::))
.route(
"/delete_account",
web::post().to(route_post_crud::),