reimplement http signature verification and other checks

This commit is contained in:
Felix Ableitner 2021-06-29 05:28:18 +02:00
parent 8a071b7b07
commit 6d447c81cf
40 changed files with 229 additions and 264 deletions

View file

@ -10,10 +10,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateComment {
actor: Url,
to: PublicUrl,
object: NoteExt,
cc: Vec<Url>,
@ -24,9 +23,9 @@ pub struct CreateComment {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<CreateComment> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(self.id_unchecked(), &self.inner.actor)?;
self.inner.object.id(self.inner.actor.as_str())?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(&self.actor, self.id_unchecked())?;
self.inner.object.id(self.actor.as_str())?;
check_is_apub_id_valid(&self.actor, false)
}
}
@ -40,13 +39,12 @@ impl ReceiveActivity for Activity<CreateComment> {
let comment = Comment::from_apub(
&self.inner.object,
context,
self.inner.actor.clone(),
self.actor.clone(),
request_counter,
false,
)
.await?;
let recipients =
get_notif_recipients(&self.inner.actor, &comment, context, request_counter).await?;
let recipients = get_notif_recipients(&self.actor, &comment, context, request_counter).await?;
send_websocket_message(
comment.id,
recipients,

View file

@ -9,10 +9,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DeleteComment {
pub(in crate::activities::comment) actor: Url,
to: PublicUrl,
pub(in crate::activities::comment) object: Url,
cc: [Url; 1],
@ -23,9 +22,9 @@ pub struct DeleteComment {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<DeleteComment> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.actor, &self.inner.object)?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, &self.inner.object)?;
check_is_apub_id_valid(&self.actor, false)
}
}

View file

@ -6,10 +6,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DislikeComment {
actor: Url,
to: PublicUrl,
pub(in crate::activities::comment) object: Url,
cc: [Url; 1],
@ -20,8 +19,8 @@ pub struct DislikeComment {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<DislikeComment> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)
}
}
@ -34,7 +33,7 @@ impl ReceiveActivity for Activity<DislikeComment> {
) -> Result<(), LemmyError> {
like_or_dislike_comment(
-1,
&self.inner.actor,
&self.actor,
&self.inner.object,
context,
request_counter,

View file

@ -6,10 +6,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LikeComment {
actor: Url,
to: PublicUrl,
pub(in crate::activities::comment) object: Url,
cc: [Url; 1],
@ -20,8 +19,8 @@ pub struct LikeComment {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<LikeComment> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)
}
}
@ -34,7 +33,7 @@ impl ReceiveActivity for Activity<LikeComment> {
) -> Result<(), LemmyError> {
like_or_dislike_comment(
-1,
&self.inner.actor,
&self.actor,
&self.inner.object,
context,
request_counter,

View file

@ -12,10 +12,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RemoveComment {
actor: Url,
to: PublicUrl,
pub(in crate::activities::comment) object: Url,
cc: [Url; 1],
@ -26,9 +25,9 @@ pub struct RemoveComment {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<RemoveComment> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_mod_action(self.inner.actor.clone(), self.inner.cc[0].clone(), context).await
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)?;
verify_mod_action(self.actor.clone(), self.inner.cc[0].clone(), context).await
}
}

View file

@ -12,10 +12,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoDeleteComment {
actor: Url,
to: PublicUrl,
object: Activity<DeleteComment>,
cc: [Url; 1],
@ -26,9 +25,9 @@ pub struct UndoDeleteComment {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoDeleteComment> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.actor, &self.inner.object.inner.actor)?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, &self.inner.object.actor)?;
check_is_apub_id_valid(&self.actor, false)?;
self.inner.object.verify(context).await
}
}

View file

@ -9,10 +9,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoDislikeComment {
actor: Url,
to: PublicUrl,
object: Activity<DislikeComment>,
cc: [Url; 1],
@ -23,9 +22,9 @@ pub struct UndoDislikeComment {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoDislikeComment> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.actor, &self.inner.object.inner.object)?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, &self.inner.object.inner.object)?;
check_is_apub_id_valid(&self.actor, false)?;
self.inner.object.verify(context).await
}
}
@ -38,7 +37,7 @@ impl ReceiveActivity for Activity<UndoDislikeComment> {
request_counter: &mut i32,
) -> Result<(), LemmyError> {
undo_like_or_dislike_comment(
&self.inner.actor,
&self.actor,
&self.inner.object.inner.object,
context,
request_counter,

View file

@ -9,10 +9,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoLikeComment {
actor: Url,
to: PublicUrl,
object: Activity<LikeComment>,
cc: [Url; 1],
@ -23,9 +22,9 @@ pub struct UndoLikeComment {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoLikeComment> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.actor, &self.inner.object.inner.object)?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, &self.inner.object.inner.object)?;
check_is_apub_id_valid(&self.actor, false)?;
self.inner.object.verify(context).await
}
}
@ -38,7 +37,7 @@ impl ReceiveActivity for Activity<UndoLikeComment> {
request_counter: &mut i32,
) -> Result<(), LemmyError> {
undo_like_or_dislike_comment(
&self.inner.actor,
&self.actor,
&self.inner.object.inner.object,
context,
request_counter,

View file

@ -15,10 +15,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoRemoveComment {
actor: Url,
to: PublicUrl,
object: Activity<RemoveComment>,
cc: [Url; 1],
@ -29,9 +28,9 @@ pub struct UndoRemoveComment {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoRemoveComment> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_mod_action(self.inner.actor.clone(), self.inner.cc[0].clone(), context).await?;
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)?;
verify_mod_action(self.actor.clone(), self.inner.cc[0].clone(), context).await?;
self.inner.object.verify(context).await
}
}

View file

@ -10,10 +10,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateComment {
actor: Url,
to: PublicUrl,
object: NoteExt,
cc: Vec<Url>,
@ -24,9 +23,9 @@ pub struct UpdateComment {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UpdateComment> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(self.id_unchecked(), &self.inner.actor)?;
self.inner.object.id(self.inner.actor.as_str())?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(&self.actor, self.id_unchecked())?;
self.inner.object.id(self.actor.as_str())?;
check_is_apub_id_valid(&self.actor, false)
}
}
@ -40,14 +39,13 @@ impl ReceiveActivity for Activity<UpdateComment> {
let comment = Comment::from_apub(
&self.inner.object,
context,
self.inner.actor.clone(),
self.actor.clone(),
request_counter,
false,
)
.await?;
let recipients =
get_notif_recipients(&self.inner.actor, &comment, context, request_counter).await?;
let recipients = get_notif_recipients(&self.actor, &comment, context, request_counter).await?;
send_websocket_message(
comment.id,
recipients,

View file

@ -16,10 +16,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AddModToCommunity {
actor: Url,
to: PublicUrl,
object: Url,
target: Url,
@ -31,10 +30,10 @@ pub struct AddModToCommunity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<AddModToCommunity> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.target, &self.inner.cc[0])?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_mod_action(self.inner.actor.clone(), self.inner.cc[0].clone(), context).await?;
check_is_apub_id_valid(&self.actor, false)?;
verify_mod_action(self.actor.clone(), self.inner.cc[0].clone(), context).await?;
verify_add_remove_moderator_target(&self.inner.target, self.inner.cc[0].clone())
}
}

View file

@ -43,7 +43,7 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub enum AnnouncableActivities {
CreateComment(CreateComment),
UpdateComment(UpdateComment),
@ -93,10 +93,9 @@ impl ReceiveActivity for AnnouncableActivities {
}
}
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AnnounceActivity {
actor: Url,
to: PublicUrl,
object: Activity<AnnouncableActivities>,
cc: [Url; 1],
@ -107,9 +106,9 @@ pub struct AnnounceActivity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<AnnounceActivity> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.actor, &self.inner.cc[0])?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, &self.inner.cc[0])?;
check_is_apub_id_valid(&self.actor, false)?;
self.inner.object.inner.verify(context).await
}
}

View file

@ -17,10 +17,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BlockUserFromCommunity {
actor: Url,
to: PublicUrl,
pub(in crate::activities::community) object: Url,
cc: [Url; 1],
@ -31,9 +30,9 @@ pub struct BlockUserFromCommunity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<BlockUserFromCommunity> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_mod_action(self.inner.actor.clone(), self.inner.cc[0].clone(), context).await
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)?;
verify_mod_action(self.actor.clone(), self.inner.cc[0].clone(), context).await
}
}

View file

@ -20,10 +20,9 @@ use url::Url;
// We have two possibilities which need to be handled:
// 1. actor is remote mod, community id in object
// 2. actor is community, cc is followers collection
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DeleteCommunity {
actor: Url,
to: PublicUrl,
pub(in crate::activities::community) object: Url,
cc: [Url; 1],
@ -34,7 +33,7 @@ pub struct DeleteCommunity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<DeleteCommunity> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, self.id_unchecked())?;
let object = self.inner.object.clone();
let community = blocking(context.pool(), move |conn| {
Community::read_from_apub_id(conn, &object.into())
@ -43,13 +42,13 @@ impl VerifyActivity for Activity<DeleteCommunity> {
// remote mod action on local community
if let Ok(c) = community {
verify_domains_match(&self.inner.object, &self.inner.cc[0])?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_is_community_mod(self.inner.actor.clone(), c.actor_id(), context).await
check_is_apub_id_valid(&self.actor, false)?;
verify_is_community_mod(self.actor.clone(), c.actor_id(), context).await
}
// community action sent to followers
else {
verify_domains_match(&self.inner.actor, &self.inner.object)?;
verify_domains_match(&self.inner.actor, &self.inner.cc[0])
verify_domains_match(&self.actor, &self.inner.object)?;
verify_domains_match(&self.actor, &self.inner.cc[0])
}
}
}
@ -69,8 +68,7 @@ impl ReceiveActivity for Activity<DeleteCommunity> {
let community_id = match community {
Ok(c) => {
// remote mod sent delete to local community, forward it to followers
let actor =
get_or_fetch_and_upsert_person(&self.inner.actor, context, request_counter).await?;
let actor = get_or_fetch_and_upsert_person(&self.actor, context, request_counter).await?;
c.send_delete(actor, context).await?;
c.id
}

View file

@ -9,10 +9,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RemoveCommunity {
actor: Url,
to: PublicUrl,
pub(in crate::activities::community) object: Url,
cc: [Url; 1],
@ -23,10 +22,10 @@ pub struct RemoveCommunity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<RemoveCommunity> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_domains_match(&self.inner.actor, &self.inner.object)?;
verify_domains_match(&self.inner.actor, &self.inner.cc[0])
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)?;
verify_domains_match(&self.actor, &self.inner.object)?;
verify_domains_match(&self.actor, &self.inner.cc[0])
}
}

View file

@ -16,10 +16,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RemoveModToCommunity {
actor: Url,
to: PublicUrl,
object: Url,
target: Url,
@ -31,10 +30,10 @@ pub struct RemoveModToCommunity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<RemoveModToCommunity> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.target, &self.inner.cc[0])?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_mod_action(self.inner.actor.clone(), self.inner.cc[0].clone(), context).await?;
check_is_apub_id_valid(&self.actor, false)?;
verify_mod_action(self.actor.clone(), self.inner.cc[0].clone(), context).await?;
verify_add_remove_moderator_target(&self.inner.target, self.inner.cc[0].clone())
}
}

View file

@ -15,10 +15,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoBlockUserFromCommunity {
actor: Url,
to: PublicUrl,
object: Activity<BlockUserFromCommunity>,
cc: [Url; 1],
@ -29,9 +28,9 @@ pub struct UndoBlockUserFromCommunity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoBlockUserFromCommunity> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_mod_action(self.inner.actor.clone(), self.inner.cc[0].clone(), context).await?;
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)?;
verify_mod_action(self.actor.clone(), self.inner.cc[0].clone(), context).await?;
self.inner.object.verify(context).await
}
}

View file

@ -24,10 +24,9 @@ use url::Url;
// We have two possibilities which need to be handled:
// 1. actor is remote mod, community id in object
// 2. actor is community, cc is followers collection
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoDeleteCommunity {
actor: Url,
to: PublicUrl,
object: Activity<DeleteCommunity>,
cc: [Url; 1],
@ -38,7 +37,7 @@ pub struct UndoDeleteCommunity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoDeleteCommunity> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, self.id_unchecked())?;
let object = self.inner.object.inner.object.clone();
let community = blocking(context.pool(), move |conn| {
Community::read_from_apub_id(conn, &object.into())
@ -47,13 +46,13 @@ impl VerifyActivity for Activity<UndoDeleteCommunity> {
// remote mod action on local community
if let Ok(c) = community {
verify_domains_match(&self.inner.object.inner.object, &self.inner.cc[0])?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_is_community_mod(self.inner.actor.clone(), c.actor_id(), context).await?;
check_is_apub_id_valid(&self.actor, false)?;
verify_is_community_mod(self.actor.clone(), c.actor_id(), context).await?;
}
// community action sent to followers
else {
verify_domains_match(&self.inner.actor, &self.inner.object.inner.object)?;
verify_domains_match(&self.inner.actor, &self.inner.cc[0])?;
verify_domains_match(&self.actor, &self.inner.object.inner.object)?;
verify_domains_match(&self.actor, &self.inner.cc[0])?;
}
self.inner.object.verify(context).await
}
@ -74,8 +73,7 @@ impl ReceiveActivity for Activity<UndoDeleteCommunity> {
let community_id = match community {
Ok(c) => {
// remote mod sent undo to local community, forward it to followers
let actor =
get_or_fetch_and_upsert_person(&self.inner.actor, context, request_counter).await?;
let actor = get_or_fetch_and_upsert_person(&self.actor, context, request_counter).await?;
c.send_delete(actor, context).await?;
c.id
}

View file

@ -12,10 +12,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoRemoveCommunity {
actor: Url,
to: PublicUrl,
object: Activity<RemoveCommunity>,
cc: [Url; 1],
@ -26,10 +25,10 @@ pub struct UndoRemoveCommunity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoRemoveCommunity> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_domains_match(&self.inner.actor, &self.inner.object.inner.object)?;
verify_domains_match(&self.inner.actor, &self.inner.cc[0])?;
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)?;
verify_domains_match(&self.actor, &self.inner.object.inner.object)?;
verify_domains_match(&self.actor, &self.inner.cc[0])?;
self.inner.object.verify(context).await
}
}

View file

@ -14,10 +14,9 @@ use url::Url;
/// This activity is received from a remote community mod, and updates the description or other
/// fields of a local community.
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateCommunity {
actor: Url,
to: PublicUrl,
object: GroupExt,
cc: [Url; 1],
@ -28,10 +27,10 @@ pub struct UpdateCommunity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UpdateCommunity> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, self.id_unchecked())?;
self.inner.object.id(self.inner.cc[0].as_str())?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_is_community_mod(self.inner.actor.clone(), self.inner.cc[0].clone(), context).await
check_is_apub_id_valid(&self.actor, false)?;
verify_is_community_mod(self.actor.clone(), self.inner.cc[0].clone(), context).await
}
}

View file

@ -12,10 +12,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AcceptFollowCommunity {
actor: Url,
to: Url,
object: Activity<FollowCommunity>,
#[serde(rename = "type")]
@ -25,8 +24,8 @@ pub struct AcceptFollowCommunity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<AcceptFollowCommunity> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)?;
self.inner.object.verify(context).await
}
}
@ -40,7 +39,7 @@ impl ReceiveActivity for Activity<AcceptFollowCommunity> {
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let community =
get_or_fetch_and_upsert_community(&self.inner.actor, context, request_counter).await?;
get_or_fetch_and_upsert_community(&self.actor, context, request_counter).await?;
let person = get_or_fetch_and_upsert_person(&self.inner.to, context, request_counter).await?;
// This will throw an error if no follow was requested
blocking(&context.pool(), move |conn| {

View file

@ -17,10 +17,9 @@ use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FollowCommunity {
actor: Url,
to: Url,
pub(in crate::activities::follow) object: Url,
#[serde(rename = "type")]
@ -30,9 +29,9 @@ pub struct FollowCommunity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<FollowCommunity> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.to, &self.inner.object)?;
check_is_apub_id_valid(&self.inner.actor, false)
check_is_apub_id_valid(&self.actor, false)
}
}
@ -45,8 +44,7 @@ impl ReceiveActivity for Activity<FollowCommunity> {
) -> Result<(), LemmyError> {
let community =
get_or_fetch_and_upsert_community(&self.inner.object, context, request_counter).await?;
let person =
get_or_fetch_and_upsert_person(&self.inner.actor, context, request_counter).await?;
let person = get_or_fetch_and_upsert_person(&self.actor, context, request_counter).await?;
let community_follower_form = CommunityFollowerForm {
community_id: community.id,
person_id: person.id,

View file

@ -12,10 +12,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoFollowCommunity {
actor: Url,
to: Url,
object: Activity<FollowCommunity>,
#[serde(rename = "type")]
@ -25,9 +24,9 @@ pub struct UndoFollowCommunity {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoFollowCommunity> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.to, &self.inner.object.inner.object)?;
check_is_apub_id_valid(&self.inner.actor, false)?;
check_is_apub_id_valid(&self.actor, false)?;
self.inner.object.verify(context).await
}
}
@ -41,8 +40,7 @@ impl ReceiveActivity for Activity<UndoFollowCommunity> {
) -> Result<(), LemmyError> {
let community =
get_or_fetch_and_upsert_community(&self.inner.to, context, request_counter).await?;
let person =
get_or_fetch_and_upsert_person(&self.inner.actor, context, request_counter).await?;
let person = get_or_fetch_and_upsert_person(&self.actor, context, request_counter).await?;
let community_follower_form = CommunityFollowerForm {
community_id: community.id,

View file

@ -13,10 +13,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreatePost {
actor: Url,
to: PublicUrl,
object: PageExt,
cc: Vec<Url>,
@ -27,9 +26,9 @@ pub struct CreatePost {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<CreatePost> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(self.id_unchecked(), &self.inner.actor)?;
self.inner.object.id(self.inner.actor.as_str())?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(self.id_unchecked(), &self.actor)?;
self.inner.object.id(self.actor.as_str())?;
check_is_apub_id_valid(&self.actor, false)
}
}
@ -40,8 +39,7 @@ impl ReceiveActivity for Activity<CreatePost> {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let person =
get_or_fetch_and_upsert_person(&self.inner.actor, context, request_counter).await?;
let person = get_or_fetch_and_upsert_person(&self.actor, context, request_counter).await?;
let post = Post::from_apub(
&self.inner.object,

View file

@ -9,10 +9,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DeletePost {
pub(in crate::activities::post) actor: Url,
to: PublicUrl,
pub(in crate::activities::post) object: Url,
cc: [Url; 1],
@ -23,9 +22,9 @@ pub struct DeletePost {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<DeletePost> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.actor, &self.inner.object)?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, &self.inner.object)?;
check_is_apub_id_valid(&self.actor, false)
}
}

View file

@ -6,10 +6,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DislikePost {
actor: Url,
to: PublicUrl,
pub(in crate::activities::post) object: Url,
cc: [Url; 1],
@ -20,8 +19,8 @@ pub struct DislikePost {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<DislikePost> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)
}
}
@ -34,7 +33,7 @@ impl ReceiveActivity for Activity<DislikePost> {
) -> Result<(), LemmyError> {
like_or_dislike_post(
-1,
&self.inner.actor,
&self.actor,
&self.inner.object,
context,
request_counter,

View file

@ -6,10 +6,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LikePost {
actor: Url,
to: PublicUrl,
pub(in crate::activities::post) object: Url,
cc: [Url; 1],
@ -20,8 +19,8 @@ pub struct LikePost {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<LikePost> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)
}
}
@ -32,13 +31,6 @@ impl ReceiveActivity for Activity<LikePost> {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
like_or_dislike_post(
1,
&self.inner.actor,
&self.inner.object,
context,
request_counter,
)
.await
like_or_dislike_post(1, &self.actor, &self.inner.object, context, request_counter).await
}
}

View file

@ -12,10 +12,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RemovePost {
actor: Url,
to: PublicUrl,
pub(in crate::activities::post) object: Url,
cc: [Url; 1],
@ -26,9 +25,9 @@ pub struct RemovePost {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<RemovePost> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_mod_action(self.inner.actor.clone(), self.inner.cc[0].clone(), context).await
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)?;
verify_mod_action(self.actor.clone(), self.inner.cc[0].clone(), context).await
}
}

View file

@ -12,10 +12,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoDeletePost {
actor: Url,
to: PublicUrl,
object: Activity<DeletePost>,
cc: [Url; 1],
@ -26,9 +25,9 @@ pub struct UndoDeletePost {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoDeletePost> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.actor, &self.inner.object.inner.actor)?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, &self.inner.object.actor)?;
check_is_apub_id_valid(&self.actor, false)?;
self.inner.object.verify(context).await
}
}

View file

@ -9,10 +9,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoDislikePost {
actor: Url,
to: PublicUrl,
object: Activity<DislikePost>,
cc: [Url; 1],
@ -23,9 +22,9 @@ pub struct UndoDislikePost {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoDislikePost> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.actor, &self.inner.object.inner.object)?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, &self.inner.object.inner.object)?;
check_is_apub_id_valid(&self.actor, false)?;
self.inner.object.verify(context).await
}
}
@ -38,7 +37,7 @@ impl ReceiveActivity for Activity<UndoDislikePost> {
request_counter: &mut i32,
) -> Result<(), LemmyError> {
undo_like_or_dislike_post(
&self.inner.actor,
&self.actor,
&self.inner.object.inner.object,
context,
request_counter,

View file

@ -9,10 +9,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoLikePost {
actor: Url,
to: PublicUrl,
object: Activity<LikePost>,
cc: [Url; 1],
@ -23,9 +22,9 @@ pub struct UndoLikePost {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoLikePost> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.actor, &self.inner.object.inner.object)?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, &self.inner.object.inner.object)?;
check_is_apub_id_valid(&self.actor, false)?;
self.inner.object.verify(context).await
}
}
@ -38,7 +37,7 @@ impl ReceiveActivity for Activity<UndoLikePost> {
request_counter: &mut i32,
) -> Result<(), LemmyError> {
undo_like_or_dislike_post(
&self.inner.actor,
&self.actor,
&self.inner.object.inner.object,
context,
request_counter,

View file

@ -15,10 +15,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoRemovePost {
actor: Url,
to: PublicUrl,
object: Activity<RemovePost>,
cc: [Url; 1],
@ -29,9 +28,9 @@ pub struct UndoRemovePost {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoRemovePost> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_mod_action(self.inner.actor.clone(), self.inner.cc[0].clone(), context).await?;
verify_domains_match(&self.actor, self.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)?;
verify_mod_action(self.actor.clone(), self.inner.cc[0].clone(), context).await?;
self.inner.object.verify(context).await
}
}

View file

@ -22,10 +22,9 @@ use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdatePost {
actor: Url,
to: PublicUrl,
object: PageExt,
cc: Vec<Url>,
@ -36,9 +35,9 @@ pub struct UpdatePost {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UpdatePost> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(self.id_unchecked(), &self.inner.actor)?;
self.inner.object.id(self.inner.actor.as_str())?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(&self.actor, self.id_unchecked())?;
self.inner.object.id(self.actor.as_str())?;
check_is_apub_id_valid(&self.actor, false)
}
}
@ -49,8 +48,7 @@ impl ReceiveActivity for Activity<UpdatePost> {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let person =
get_or_fetch_and_upsert_person(&self.inner.actor, context, request_counter).await?;
let person = get_or_fetch_and_upsert_person(&self.actor, context, request_counter).await?;
let temp_post = PostForm::from_apub(
&self.inner.object,
context,

View file

@ -10,10 +10,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreatePrivateMessage {
actor: Url,
to: Url,
object: NoteExt,
#[serde(rename = "type")]
@ -23,9 +22,9 @@ pub struct CreatePrivateMessage {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<CreatePrivateMessage> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(self.id_unchecked(), &self.inner.actor)?;
self.inner.object.id(self.inner.actor.as_str())?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(self.id_unchecked(), &self.actor)?;
self.inner.object.id(self.actor.as_str())?;
check_is_apub_id_valid(&self.actor, false)
}
}
@ -39,7 +38,7 @@ impl ReceiveActivity for Activity<CreatePrivateMessage> {
let private_message = PrivateMessage::from_apub(
&self.inner.object,
context,
self.inner.actor.clone(),
self.actor.clone(),
request_counter,
false,
)

View file

@ -12,10 +12,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DeletePrivateMessage {
actor: Url,
to: Url,
pub(in crate::activities::private_message) object: Url,
#[serde(rename = "type")]
@ -25,9 +24,9 @@ pub struct DeletePrivateMessage {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<DeletePrivateMessage> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.actor, &self.inner.object)?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, &self.inner.object)?;
check_is_apub_id_valid(&self.actor, false)
}
}

View file

@ -12,10 +12,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoDeletePrivateMessage {
actor: Url,
to: Url,
object: Activity<DeletePrivateMessage>,
#[serde(rename = "type")]
@ -25,9 +24,9 @@ pub struct UndoDeletePrivateMessage {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UndoDeletePrivateMessage> {
async fn verify(&self, context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
verify_domains_match(&self.inner.actor, &self.inner.object.id_unchecked())?;
check_is_apub_id_valid(&self.inner.actor, false)?;
verify_domains_match(&self.actor, self.id_unchecked())?;
verify_domains_match(&self.actor, &self.inner.object.id_unchecked())?;
check_is_apub_id_valid(&self.actor, false)?;
self.inner.object.verify(context).await
}
}

View file

@ -10,10 +10,9 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdatePrivateMessage {
actor: Url,
to: Url,
object: NoteExt,
#[serde(rename = "type")]
@ -23,9 +22,9 @@ pub struct UpdatePrivateMessage {
#[async_trait::async_trait(?Send)]
impl VerifyActivity for Activity<UpdatePrivateMessage> {
async fn verify(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
verify_domains_match(self.id_unchecked(), &self.inner.actor)?;
self.inner.object.id(self.inner.actor.as_str())?;
check_is_apub_id_valid(&self.inner.actor, false)
verify_domains_match(self.id_unchecked(), &self.actor)?;
self.inner.object.id(self.actor.as_str())?;
check_is_apub_id_valid(&self.actor, false)
}
}
@ -39,7 +38,7 @@ impl ReceiveActivity for Activity<UpdatePrivateMessage> {
let private_message = PrivateMessage::from_apub(
&self.inner.object,
context,
self.inner.actor.clone(),
self.actor.clone(),
request_counter,
false,
)

View file

@ -1,22 +1,10 @@
use activitystreams::{
activity::ActorAndObjectRefExt,
base::{AsBase, Extends},
object::AsObject,
};
use actix_web::HttpRequest;
use anyhow::Context;
use crate::inbox::new_inbox_routing::Activity;
use anyhow::{anyhow, Context};
use lemmy_api_common::blocking;
use lemmy_apub::{
check_is_apub_id_valid,
extensions::signatures::verify_signature,
fetcher::get_or_fetch_and_upsert_actor,
ActorType,
};
use lemmy_db_queries::{source::activity::Activity_, DbPool};
use lemmy_db_schema::source::activity::Activity;
use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::LemmyContext;
use serde::Serialize;
use lemmy_db_schema::source::activity::Activity as DbActivity;
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
use std::fmt::Debug;
use url::Url;
pub mod community_inbox;
@ -30,7 +18,7 @@ pub(crate) async fn is_activity_already_known(
) -> Result<bool, LemmyError> {
let activity_id = activity_id.to_owned().into();
let existing = blocking(pool, move |conn| {
Activity::read_from_apub_id(&conn, &activity_id)
DbActivity::read_from_apub_id(&conn, &activity_id)
})
.await?;
match existing {
@ -39,24 +27,19 @@ pub(crate) async fn is_activity_already_known(
}
}
pub(crate) async fn inbox_verify_http_signature<T, Kind>(
activity: &T,
context: &LemmyContext,
request: HttpRequest,
request_counter: &mut i32,
) -> Result<Box<dyn ActorType>, LemmyError>
where
T: AsObject<Kind> + ActorAndObjectRefExt + Extends<Kind> + AsBase<Kind>,
Kind: Serialize,
<T as Extends<Kind>>::Error: From<serde_json::Error> + Send + Sync + 'static,
{
let actor_id = activity
.actor()?
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
check_is_apub_id_valid(&actor_id, false)?;
let actor = get_or_fetch_and_upsert_actor(&actor_id, &context, request_counter).await?;
verify_signature(&request, actor.as_ref())?;
Ok(actor)
pub(in crate::inbox) fn assert_activity_not_local<T: Debug>(
activity: &Activity<T>,
) -> Result<(), LemmyError> {
let activity_domain = activity.id_unchecked().domain().context(location_info!())?;
if activity_domain == Settings::get().hostname() {
return Err(
anyhow!(
"Error: received activity which was sent by local instance: {:?}",
activity
)
.into(),
);
}
Ok(())
}

View file

@ -49,12 +49,13 @@ use url::Url;
// TODO: would be nice if we could move this to lemmy_apub_lib crate. doing that gives error:
// "only traits defined in the current crate can be implemented for arbitrary types"
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Activity<Kind> {
#[serde(rename = "@context")]
context: OneOrMany<AnyBase>,
id: Url,
pub(crate) actor: Url,
/// type-specific fields
#[serde(flatten)]
@ -71,7 +72,7 @@ impl<Kind> Activity<Kind> {
}
}
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub enum SharedInboxActivities {
FollowCommunity(FollowCommunity),
AcceptFollowCommunity(AcceptFollowCommunity),

View file

@ -1,17 +1,50 @@
use crate::inbox::new_inbox_routing::{Activity, SharedInboxActivities};
use crate::inbox::{
assert_activity_not_local,
is_activity_already_known,
new_inbox_routing::{Activity, SharedInboxActivities},
};
use actix_web::{web, HttpRequest, HttpResponse};
use lemmy_apub::{
check_is_apub_id_valid,
extensions::signatures::verify_signature,
fetcher::get_or_fetch_and_upsert_actor,
insert_activity,
};
use lemmy_apub_lib::{ReceiveActivity, VerifyActivity};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
pub async fn shared_inbox(
_request: HttpRequest,
request: HttpRequest,
input: web::Json<Activity<SharedInboxActivities>>,
context: web::Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> {
let activity = input.into_inner();
activity.inner.verify(&context).await?;
let request_counter = &mut 0;
activity.inner.receive(&context, request_counter).await?;
todo!()
// Do nothing if we received the same activity before
if is_activity_already_known(context.pool(), &activity.id_unchecked()).await? {
return Ok(HttpResponse::Ok().finish());
}
assert_activity_not_local(&activity)?;
check_is_apub_id_valid(&activity.actor, false)?;
activity.inner.verify(&context).await?;
let request_counter = &mut 0;
let actor = get_or_fetch_and_upsert_actor(&activity.actor, &context, request_counter).await?;
verify_signature(&request, actor.as_ref())?;
// 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.
insert_activity(
&activity.id_unchecked(),
activity.clone(),
false,
true,
context.pool(),
)
.await?;
// TODO: pass the actor in somehow
activity.inner.receive(&context, request_counter).await?;
return Ok(HttpResponse::Ok().finish());
}