fix: exclude soft-deleted posts from outbox and content negotiation
Deleted posts (with properties.deleted timestamp) were still served via the outbox dispatcher and content negotiation catch-all. Now: - Outbox find() and countDocuments() filter out deleted posts - Object dispatcher returns null for deleted posts (Fedify 404) - Content negotiation falls through to Express for deleted posts Confab-Link: http://localhost:8080/sessions/af5f8b45-6b8d-442d-8f25-78c326190709
This commit is contained in:
@@ -434,7 +434,7 @@ export default class ActivityPubEndpoint {
|
|||||||
"properties.url": requestUrl,
|
"properties.url": requestUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!post) {
|
if (!post || post.properties?.deleted) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -609,10 +609,11 @@ function setupOutbox(federation, mountPath, handle, collections) {
|
|||||||
|
|
||||||
const pageSize = 20;
|
const pageSize = 20;
|
||||||
const skip = cursor ? Number.parseInt(cursor, 10) : 0;
|
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
|
const posts = await postsCollection
|
||||||
.find()
|
.find(notDeleted)
|
||||||
.sort({ "properties.published": -1 })
|
.sort({ "properties.published": -1 })
|
||||||
.skip(skip)
|
.skip(skip)
|
||||||
.limit(pageSize)
|
.limit(pageSize)
|
||||||
@@ -644,7 +645,9 @@ function setupOutbox(federation, mountPath, handle, collections) {
|
|||||||
if (identifier !== handle) return 0;
|
if (identifier !== handle) return 0;
|
||||||
const postsCollection = collections.posts;
|
const postsCollection = collections.posts;
|
||||||
if (!postsCollection) return 0;
|
if (!postsCollection) return 0;
|
||||||
return await postsCollection.countDocuments();
|
return await postsCollection.countDocuments({
|
||||||
|
"properties.deleted": { $exists: false },
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.setFirstCursor(async () => "0");
|
.setFirstCursor(async () => "0");
|
||||||
}
|
}
|
||||||
@@ -656,6 +659,8 @@ function setupObjectDispatchers(federation, mountPath, handle, collections, publ
|
|||||||
const postUrl = `${publicationUrl.replace(/\/$/, "")}/${id}`;
|
const postUrl = `${publicationUrl.replace(/\/$/, "")}/${id}`;
|
||||||
const post = await collections.posts.findOne({ "properties.url": postUrl });
|
const post = await collections.posts.findOne({ "properties.url": postUrl });
|
||||||
if (!post) return null;
|
if (!post) return null;
|
||||||
|
// Soft-deleted posts should not be dereferenceable
|
||||||
|
if (post.properties?.deleted) return null;
|
||||||
const actorUrl = ctx.getActorUri(handle).href;
|
const actorUrl = ctx.getActorUri(handle).href;
|
||||||
const activity = jf2ToAS2Activity(post.properties, actorUrl, publicationUrl);
|
const activity = jf2ToAS2Activity(post.properties, actorUrl, publicationUrl);
|
||||||
// Only Create activities wrap Note/Article objects
|
// Only Create activities wrap Note/Article objects
|
||||||
|
|||||||
Reference in New Issue
Block a user