diff --git a/index.js b/index.js index 3d4c474..243d864 100644 --- a/index.js +++ b/index.js @@ -434,7 +434,7 @@ export default class ActivityPubEndpoint { "properties.url": requestUrl, }); - if (!post) { + if (!post || post.properties?.deleted) { return next(); } diff --git a/lib/federation-setup.js b/lib/federation-setup.js index 5fb7ab0..920f225 100644 --- a/lib/federation-setup.js +++ b/lib/federation-setup.js @@ -609,10 +609,11 @@ function setupOutbox(federation, mountPath, handle, collections) { const pageSize = 20; const skip = cursor ? Number.parseInt(cursor, 10) : 0; - const total = await postsCollection.countDocuments(); + const notDeleted = { "properties.deleted": { $exists: false } }; + const total = await postsCollection.countDocuments(notDeleted); const posts = await postsCollection - .find() + .find(notDeleted) .sort({ "properties.published": -1 }) .skip(skip) .limit(pageSize) @@ -644,7 +645,9 @@ function setupOutbox(federation, mountPath, handle, collections) { if (identifier !== handle) return 0; const postsCollection = collections.posts; if (!postsCollection) return 0; - return await postsCollection.countDocuments(); + return await postsCollection.countDocuments({ + "properties.deleted": { $exists: false }, + }); }) .setFirstCursor(async () => "0"); } @@ -656,6 +659,8 @@ function setupObjectDispatchers(federation, mountPath, handle, collections, publ const postUrl = `${publicationUrl.replace(/\/$/, "")}/${id}`; const post = await collections.posts.findOne({ "properties.url": postUrl }); if (!post) return null; + // Soft-deleted posts should not be dereferenceable + if (post.properties?.deleted) return null; const actorUrl = ctx.getActorUri(handle).href; const activity = jf2ToAS2Activity(post.properties, actorUrl, publicationUrl); // Only Create activities wrap Note/Article objects