mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-12-23 11:21:32 +00:00
Community outbox should only contain activities sent by community (fixes #1916)
This commit is contained in:
parent
8fc252ec55
commit
a2707e1c56
5 changed files with 63 additions and 199 deletions
|
@ -1,209 +1,61 @@
|
||||||
{
|
{
|
||||||
"type": "OrderedCollection",
|
"type": "OrderedCollection",
|
||||||
"id": "https://ds9.lemmy.ml/c/main/outbox",
|
"id": "https://ds9.lemmy.ml/c/testcom/outbox",
|
||||||
"totalItems": 7,
|
"totalItems": 2,
|
||||||
"orderedItems": [
|
"orderedItems": [
|
||||||
{
|
{
|
||||||
"actor": "https://ds9.lemmy.ml/u/dess_ds9",
|
"actor": "https://ds9.lemmy.ml/c/testcom",
|
||||||
"to": [
|
"to": [
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
],
|
],
|
||||||
"object": {
|
"object": {
|
||||||
"type": "Page",
|
"type": "Page",
|
||||||
"id": "https://ds9.lemmy.ml/post/1685",
|
"id": "https://ds9.lemmy.ml/post/2328",
|
||||||
"attributedTo": "https://ds9.lemmy.ml/u/dess_ds9",
|
|
||||||
"to": [
|
|
||||||
"https://ds9.lemmy.ml/c/main",
|
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
],
|
|
||||||
"name": "Test post",
|
|
||||||
"mediaType": "text/html",
|
|
||||||
"commentsEnabled": true,
|
|
||||||
"sensitive": false,
|
|
||||||
"stickied": false,
|
|
||||||
"published": "2021-09-30T16:37:58.425718+00:00",
|
|
||||||
"updated": "2021-09-30T16:39:50.934055+00:00"
|
|
||||||
},
|
|
||||||
"cc": [
|
|
||||||
"https://ds9.lemmy.ml/c/main"
|
|
||||||
],
|
|
||||||
"type": "Create",
|
|
||||||
"id": "https://ds9.lemmy.ml/activities/create/157bc329-05cb-4dc3-ad9e-5110fde3f3aa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"actor": "https://ds9.lemmy.ml/u/nutomic",
|
|
||||||
"to": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
],
|
|
||||||
"object": {
|
|
||||||
"type": "Page",
|
|
||||||
"id": "https://ds9.lemmy.ml/post/1665",
|
|
||||||
"attributedTo": "https://ds9.lemmy.ml/u/nutomic",
|
"attributedTo": "https://ds9.lemmy.ml/u/nutomic",
|
||||||
"to": [
|
"to": [
|
||||||
"https://ds9.lemmy.ml/c/main",
|
"https://ds9.lemmy.ml/c/testcom",
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
],
|
],
|
||||||
"name": "another webmention test",
|
"cc": [],
|
||||||
|
"name": "another outbox test",
|
||||||
"mediaType": "text/html",
|
"mediaType": "text/html",
|
||||||
"url": "https://webmention.rocks/test/1",
|
|
||||||
"commentsEnabled": true,
|
"commentsEnabled": true,
|
||||||
"sensitive": false,
|
"sensitive": false,
|
||||||
"stickied": false,
|
"stickied": false,
|
||||||
"published": "2021-09-17T13:22:15.026912+00:00"
|
"published": "2021-11-18T17:19:45.895163+00:00"
|
||||||
},
|
},
|
||||||
"cc": [
|
"cc": [
|
||||||
"https://ds9.lemmy.ml/c/main"
|
"https://ds9.lemmy.ml/c/testcom/followers"
|
||||||
],
|
],
|
||||||
"type": "Create",
|
"type": "Announce",
|
||||||
"id": "https://ds9.lemmy.ml/activities/create/c54e4509-16ac-42bf-b3b4-0bf8516f8152"
|
"id": "https://ds9.lemmy.ml/activities/announce/b204fe9f-b13d-4af2-9d22-239ac2d892e6"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"actor": "https://ds9.lemmy.ml/u/nutomic",
|
"actor": "https://ds9.lemmy.ml/c/testcom",
|
||||||
"to": [
|
"to": [
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
],
|
],
|
||||||
"object": {
|
"object": {
|
||||||
"type": "Page",
|
"type": "Page",
|
||||||
"id": "https://ds9.lemmy.ml/post/1664",
|
"id": "https://ds9.lemmy.ml/post/2327",
|
||||||
"attributedTo": "https://ds9.lemmy.ml/u/nutomic",
|
"attributedTo": "https://ds9.lemmy.ml/u/nutomic",
|
||||||
"to": [
|
"to": [
|
||||||
"https://ds9.lemmy.ml/c/main",
|
"https://ds9.lemmy.ml/c/testcom",
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
],
|
],
|
||||||
"name": "another test",
|
"cc": [],
|
||||||
"mediaType": "text/html",
|
"name": "outbox test",
|
||||||
"url": "https://webmention.rocks/test/1",
|
|
||||||
"commentsEnabled": true,
|
|
||||||
"sensitive": false,
|
|
||||||
"stickied": false,
|
|
||||||
"published": "2021-09-17T13:13:21.675891+00:00"
|
|
||||||
},
|
|
||||||
"cc": [
|
|
||||||
"https://ds9.lemmy.ml/c/main"
|
|
||||||
],
|
|
||||||
"type": "Create",
|
|
||||||
"id": "https://ds9.lemmy.ml/activities/create/25f7d2cb-11d5-4c9c-aa3c-85fbff9f9e0c"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"actor": "https://ds9.lemmy.ml/u/nutomic",
|
|
||||||
"to": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
],
|
|
||||||
"object": {
|
|
||||||
"type": "Page",
|
|
||||||
"id": "https://ds9.lemmy.ml/post/1663",
|
|
||||||
"attributedTo": "https://ds9.lemmy.ml/u/nutomic",
|
|
||||||
"to": [
|
|
||||||
"https://ds9.lemmy.ml/c/main",
|
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
],
|
|
||||||
"name": "Webmention test from Lemmy",
|
|
||||||
"mediaType": "text/html",
|
|
||||||
"url": "https://webmention.rocks/test/1",
|
|
||||||
"commentsEnabled": true,
|
|
||||||
"sensitive": false,
|
|
||||||
"stickied": false,
|
|
||||||
"published": "2021-09-17T13:00:15.392844+00:00"
|
|
||||||
},
|
|
||||||
"cc": [
|
|
||||||
"https://ds9.lemmy.ml/c/main"
|
|
||||||
],
|
|
||||||
"type": "Create",
|
|
||||||
"id": "https://ds9.lemmy.ml/activities/create/cfbd12b8-2e11-42b6-a609-b482decbaf11"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"actor": "https://ds9.lemmy.ml/u/dess_tester_3",
|
|
||||||
"to": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
],
|
|
||||||
"object": {
|
|
||||||
"type": "Page",
|
|
||||||
"id": "https://ds9.lemmy.ml/post/1644",
|
|
||||||
"attributedTo": "https://ds9.lemmy.ml/u/dess_tester_3",
|
|
||||||
"to": [
|
|
||||||
"https://ds9.lemmy.ml/c/main",
|
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
],
|
|
||||||
"name": "The best wireless earbuds you can buy right now | Engadget",
|
|
||||||
"mediaType": "text/html",
|
|
||||||
"url": "https://www.engadget.com/best-wireless-earbuds-120058222.html",
|
|
||||||
"image": {
|
|
||||||
"type": "Image",
|
|
||||||
"url": "https://ds9.lemmy.ml/pictrs/image/0WWsYOuwAE.jpg"
|
|
||||||
},
|
|
||||||
"commentsEnabled": true,
|
|
||||||
"sensitive": false,
|
|
||||||
"stickied": false,
|
|
||||||
"published": "2021-08-26T01:22:06.428368+00:00"
|
|
||||||
},
|
|
||||||
"cc": [
|
|
||||||
"https://ds9.lemmy.ml/c/main"
|
|
||||||
],
|
|
||||||
"type": "Create",
|
|
||||||
"id": "https://ds9.lemmy.ml/activities/create/76c94408-944a-4a2f-a88b-d10f12b472b0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"actor": "https://ds9.lemmy.ml/u/dess_ds9",
|
|
||||||
"to": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
],
|
|
||||||
"object": {
|
|
||||||
"type": "Page",
|
|
||||||
"id": "https://ds9.lemmy.ml/post/1643",
|
|
||||||
"attributedTo": "https://ds9.lemmy.ml/u/dess_ds9",
|
|
||||||
"to": [
|
|
||||||
"https://ds9.lemmy.ml/c/main",
|
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
],
|
|
||||||
"name": "First Look: Cadillac’s luxury EV debut seems like a winner | Engadges",
|
|
||||||
"content": "<p>test</p>\n",
|
|
||||||
"mediaType": "text/html",
|
|
||||||
"source": {
|
|
||||||
"content": "test",
|
|
||||||
"mediaType": "text/markdown"
|
|
||||||
},
|
|
||||||
"url": "https://www.engadget.com/cadillac-lyriq-luxury-ev-first-look-video-171543752.html",
|
|
||||||
"image": {
|
|
||||||
"type": "Image",
|
|
||||||
"url": "https://ds9.lemmy.ml/pictrs/image/gnmtvgXP31.jpg"
|
|
||||||
},
|
|
||||||
"commentsEnabled": true,
|
|
||||||
"sensitive": false,
|
|
||||||
"stickied": false,
|
|
||||||
"published": "2021-08-23T23:43:06.560543+00:00",
|
|
||||||
"updated": "2021-08-23T23:52:51.832606+00:00"
|
|
||||||
},
|
|
||||||
"cc": [
|
|
||||||
"https://ds9.lemmy.ml/c/main"
|
|
||||||
],
|
|
||||||
"type": "Create",
|
|
||||||
"id": "https://ds9.lemmy.ml/activities/create/b1f95918-f593-4951-91cf-2c3340cd9509"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"actor": "https://ds9.lemmy.ml/u/dess_ds9_2",
|
|
||||||
"to": [
|
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
],
|
|
||||||
"object": {
|
|
||||||
"type": "Page",
|
|
||||||
"id": "https://ds9.lemmy.ml/post/1642",
|
|
||||||
"attributedTo": "https://ds9.lemmy.ml/u/dess_ds9_2",
|
|
||||||
"to": [
|
|
||||||
"https://ds9.lemmy.ml/c/main",
|
|
||||||
"https://www.w3.org/ns/activitystreams#Public"
|
|
||||||
],
|
|
||||||
"name": "A test post from DS9",
|
|
||||||
"mediaType": "text/html",
|
"mediaType": "text/html",
|
||||||
"commentsEnabled": true,
|
"commentsEnabled": true,
|
||||||
"sensitive": false,
|
"sensitive": false,
|
||||||
"stickied": false,
|
"stickied": false,
|
||||||
"published": "2021-08-06T14:10:47.493075+00:00"
|
"published": "2021-11-18T17:19:05.763109+00:00"
|
||||||
},
|
},
|
||||||
"cc": [
|
"cc": [
|
||||||
"https://ds9.lemmy.ml/c/main"
|
"https://ds9.lemmy.ml/c/testcom/followers"
|
||||||
],
|
],
|
||||||
"type": "Create",
|
"type": "Announce",
|
||||||
"id": "https://ds9.lemmy.ml/activities/create/6359b2e7-badb-4241-b5ee-b093078361bd"
|
"id": "https://ds9.lemmy.ml/activities/announce/c6c960ce-c8d8-4231-925e-3ba367468f18"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -25,7 +25,7 @@ pub(crate) trait GetCommunity {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnnounceActivity {
|
impl AnnounceActivity {
|
||||||
fn new(
|
pub(crate) fn new(
|
||||||
object: AnnouncableActivities,
|
object: AnnouncableActivities,
|
||||||
community: &ApubCommunity,
|
community: &ApubCommunity,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
|
@ -103,13 +103,20 @@ impl ActivityHandler for AnnounceActivity {
|
||||||
context: &Data<LemmyContext>,
|
context: &Data<LemmyContext>,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let object_value = serde_json::to_value(&self.object)?;
|
// TODO: this can probably be implemented in a cleaner way
|
||||||
let object_data: ActivityCommonFields = serde_json::from_value(object_value.to_owned())?;
|
match self.object {
|
||||||
|
// Dont insert these into activities table, as they are not activities.
|
||||||
|
AnnouncableActivities::Page(_) | AnnouncableActivities::Note(_) => {}
|
||||||
|
_ => {
|
||||||
|
let object_value = serde_json::to_value(&self.object)?;
|
||||||
|
let object_data: ActivityCommonFields = serde_json::from_value(object_value.to_owned())?;
|
||||||
|
|
||||||
if is_activity_already_known(context.pool(), &object_data.id).await? {
|
if is_activity_already_known(context.pool(), &object_data.id).await? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
}
|
||||||
|
insert_activity(&object_data.id, object_value, false, true, context.pool()).await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
insert_activity(&object_data.id, object_value, false, true, context.pool()).await?;
|
|
||||||
self.object.receive(context, request_counter).await
|
self.object.receive(context, request_counter).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
|
activity_lists::AnnouncableActivities,
|
||||||
collections::CommunityContext,
|
collections::CommunityContext,
|
||||||
generate_outbox_url,
|
generate_outbox_url,
|
||||||
objects::{person::ApubPerson, post::ApubPost},
|
objects::post::ApubPost,
|
||||||
protocol::{
|
protocol::{
|
||||||
activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType},
|
activities::community::announce::AnnounceActivity,
|
||||||
collections::group_outbox::GroupOutbox,
|
collections::group_outbox::GroupOutbox,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -15,10 +16,7 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityHandler, ApubObject},
|
traits::{ActivityHandler, ApubObject},
|
||||||
verify::verify_domains_match,
|
verify::verify_domains_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::source::post::Post;
|
||||||
source::{person::Person, post::Post},
|
|
||||||
traits::Crud,
|
|
||||||
};
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -63,13 +61,10 @@ impl ApubObject for ApubCommunityOutbox {
|
||||||
async fn into_apub(self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
|
async fn into_apub(self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
|
||||||
let mut ordered_items = vec![];
|
let mut ordered_items = vec![];
|
||||||
for post in self.0 {
|
for post in self.0 {
|
||||||
let actor = post.creator_id;
|
let page = post.into_apub(&data.1).await?;
|
||||||
let actor: ApubPerson = blocking(data.1.pool(), move |conn| Person::read(conn, actor))
|
let announcable = AnnouncableActivities::Page(page);
|
||||||
.await??
|
let announce = AnnounceActivity::new(announcable, &data.0, &data.1)?;
|
||||||
.into();
|
ordered_items.push(announce);
|
||||||
let a =
|
|
||||||
CreateOrUpdatePost::new(post, &actor, &data.0, CreateOrUpdateType::Create, &data.1).await?;
|
|
||||||
ordered_items.push(a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(GroupOutbox {
|
Ok(GroupOutbox {
|
||||||
|
@ -108,11 +103,12 @@ impl ApubObject for ApubCommunityOutbox {
|
||||||
// We intentionally ignore errors here. This is because the outbox might contain posts from old
|
// We intentionally ignore errors here. This is because the outbox might contain posts from old
|
||||||
// Lemmy versions, or from other software which we cant parse. In that case, we simply skip the
|
// Lemmy versions, or from other software which we cant parse. In that case, we simply skip the
|
||||||
// item and only parse the ones that work.
|
// item and only parse the ones that work.
|
||||||
|
let data = Data::new(data.1.clone());
|
||||||
for activity in outbox_activities {
|
for activity in outbox_activities {
|
||||||
activity
|
let verify = activity.verify(&data, request_counter).await;
|
||||||
.receive(&Data::new(data.1.clone()), request_counter)
|
if verify.is_ok() {
|
||||||
.await
|
activity.receive(&data, request_counter).await.ok();
|
||||||
.ok();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This return value is unused, so just set an empty vec
|
// This return value is unused, so just set an empty vec
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::protocol::activities::create_or_update::post::CreateOrUpdatePost;
|
use crate::protocol::activities::community::announce::AnnounceActivity;
|
||||||
use activitystreams::collection::kind::OrderedCollectionType;
|
use activitystreams::collection::kind::OrderedCollectionType;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -9,5 +9,5 @@ pub struct GroupOutbox {
|
||||||
pub(crate) r#type: OrderedCollectionType,
|
pub(crate) r#type: OrderedCollectionType,
|
||||||
pub(crate) id: Url,
|
pub(crate) id: Url,
|
||||||
pub(crate) total_items: i32,
|
pub(crate) total_items: i32,
|
||||||
pub(crate) ordered_items: Vec<CreateOrUpdatePost>,
|
pub(crate) ordered_items: Vec<AnnounceActivity>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use chrono::{DateTime, FixedOffset};
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
data::Data,
|
data::Data,
|
||||||
object_id::ObjectId,
|
object_id::ObjectId,
|
||||||
traits::ActivityHandler,
|
traits::{ActivityHandler, ApubObject},
|
||||||
values::MediaTypeHtml,
|
values::MediaTypeHtml,
|
||||||
};
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
|
@ -79,14 +79,23 @@ impl Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For Pleroma/Mastodon compat. Unimplemented because its only used for sending.
|
// Used for community outbox, so that it can be compatible with Pleroma/Mastodon.
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ActivityHandler for Page {
|
impl ActivityHandler for Page {
|
||||||
type DataType = LemmyContext;
|
type DataType = LemmyContext;
|
||||||
async fn verify(&self, _: &Data<Self::DataType>, _: &mut i32) -> Result<(), LemmyError> {
|
async fn verify(
|
||||||
Err(anyhow!("Announce/Page can only be sent, not received").into())
|
&self,
|
||||||
|
data: &Data<Self::DataType>,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
ApubPost::verify(self, self.id.inner(), data, request_counter).await
|
||||||
}
|
}
|
||||||
async fn receive(self, _: &Data<Self::DataType>, _: &mut i32) -> Result<(), LemmyError> {
|
async fn receive(
|
||||||
unimplemented!()
|
self,
|
||||||
|
data: &Data<Self::DataType>,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
ApubPost::from_apub(self, data, request_counter).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue