From 428300de4f917865d45f415d4fcafbd3836d75a1 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 27 Feb 2025 13:34:11 -0500 Subject: [PATCH] fix: scheduled topics and posts should return 404 on AP request --- src/controllers/activitypub/actors.js | 14 +++-- test/activitypub/actors.js | 77 +++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/src/controllers/activitypub/actors.js b/src/controllers/activitypub/actors.js index c80f6e2867..8135fdcc73 100644 --- a/src/controllers/activitypub/actors.js +++ b/src/controllers/activitypub/actors.js @@ -55,12 +55,12 @@ Actors.userBySlug = async function (req, res) { Actors.user(req, res); }; -Actors.note = async function (req, res) { +Actors.note = async function (req, res, next) { // technically a note isn't an actor, but it is here purely for organizational purposes. // but also, wouldn't it be wild if you could follow a note? lol. const allowed = await privileges.posts.can('topics:read', req.params.pid, activitypub._constants.uid); if (!allowed) { - return res.sendStatus(404); + return next(); } // Handle requests for remote content @@ -72,8 +72,8 @@ Actors.note = async function (req, res) { parse: false, extraFields: ['edited'], })).pop(); - if (!post) { - return res.sendStatus(404); + if (!post || post.timestamp > Date.now()) { + return next(); } const payload = await activitypub.mocks.notes.public(post); @@ -120,8 +120,12 @@ Actors.topic = async function (req, res, next) { const page = parseInt(req.query.page, 10) || undefined; const perPage = meta.config.postsPerPage; - const { cid, titleRaw: name, mainPid, slug } = await topics.getTopicFields(req.params.tid, ['cid', 'title', 'mainPid', 'slug']); + const { cid, titleRaw: name, mainPid, slug, timestamp } = await topics.getTopicFields(req.params.tid, ['cid', 'title', 'mainPid', 'slug', 'timestamp']); try { + if (timestamp > Date.now()) { // Scheduled topic, no response + return next(); + } + let [collection, pids] = await Promise.all([ activitypub.helpers.generateCollection({ set: `tid:${req.params.tid}:posts`, diff --git a/test/activitypub/actors.js b/test/activitypub/actors.js index 08c109eb19..9da0380c27 100644 --- a/test/activitypub/actors.js +++ b/test/activitypub/actors.js @@ -253,7 +253,7 @@ describe('Controllers', () => { }); }); - describe.only('Topic', () => { + describe('Topic Collection endpoint', () => { let cid; let uid; @@ -265,12 +265,11 @@ describe('Controllers', () => { describe('Live', () => { let topicData; - let postData; let response; let body; before(async () => { - ({ topicData, postData } = await topics.post({ + ({ topicData } = await topics.post({ uid, cid, title: 'Lorem "Lipsum" Ipsum', @@ -299,12 +298,11 @@ describe('Controllers', () => { describe('Scheduled', () => { let topicData; - let postData; let response; let body; before(async () => { - ({ topicData, postData } = await topics.post({ + ({ topicData } = await topics.post({ uid, cid, title: 'Lorem "Lipsum" Ipsum', @@ -325,4 +323,73 @@ describe('Controllers', () => { }); }); }); + + describe('Post Object endpoint', () => { + let cid; + let uid; + + before(async () => { + ({ cid } = await categories.create({ name: utils.generateUUID().slice(0, 8) })); + const slug = slugify(utils.generateUUID().slice(0, 8)); + uid = await user.create({ username: slug }); + }); + + describe('Live', () => { + let postData; + let response; + let body; + + before(async () => { + ({ postData } = await topics.post({ + uid, + cid, + title: 'Lorem "Lipsum" Ipsum', + content: 'Lorem ipsum dolor sit amet', + })); + + ({ response, body } = await request.get(`${nconf.get('url')}/post/${postData.pid}`, { + headers: { + Accept: 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', + }, + })); + }); + + it('should respond properly', async () => { + assert(response); + assert.strictEqual(response.statusCode, 200); + }); + + it('should return a Note type object', () => { + assert.strictEqual(body.type, 'Note'); + }); + }); + + describe('Scheduled', () => { + let topicData; + let postData; + let response; + let body; + + before(async () => { + ({ topicData, postData } = await topics.post({ + uid, + cid, + title: 'Lorem "Lipsum" Ipsum', + content: 'Lorem ipsum dolor sit amet', + timestamp: Date.now() + (1000 * 60 * 60), // 1 hour in the future + })); + + ({ response, body } = await request.get(`${nconf.get('url')}/post/${postData.pid}`, { + headers: { + Accept: 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', + }, + })); + }); + + it('should respond with a 404 Not Found', async () => { + assert(response); + assert.strictEqual(response.statusCode, 404); + }); + }); + }); });