diff --git a/src/activitypub/actors.js b/src/activitypub/actors.js index 40a3052e56..917efa4531 100644 --- a/src/activitypub/actors.js +++ b/src/activitypub/actors.js @@ -30,7 +30,7 @@ Actors.assert = async (ids, options = {}) => { const actors = await Promise.all(ids.map(async (id) => { try { - const actor = (typeof id === 'object' && id.hasOwnProperty('id')) ? await activitypub.get(0, id) : id; + const actor = (typeof id === 'object' && id.hasOwnProperty('id')) ? id : await activitypub.get(0, id); // Follow counts try { diff --git a/src/activitypub/index.js b/src/activitypub/index.js index 3df01c0ca6..6f276a4f06 100644 --- a/src/activitypub/index.js +++ b/src/activitypub/index.js @@ -26,6 +26,7 @@ ActivityPub.actors = require('./actors'); ActivityPub.resolveInboxes = async (ids) => { const inboxes = new Set(); + await ActivityPub.actors.assert(ids); await Promise.all(ids.map(async (id) => { const { inbox, sharedInbox } = await user.getUserFields(id, ['inbox', 'sharedInbox']); if (sharedInbox || inbox) { @@ -190,7 +191,7 @@ ActivityPub.send = async (uid, targets, payload) => { } const userslug = await user.getUserField(uid, 'userslug'); - const inboxes = await ActivityPub.resolveInboxes(uid, targets); + const inboxes = await ActivityPub.resolveInboxes(targets); payload = { '@context': 'https://www.w3.org/ns/activitystreams', diff --git a/src/activitypub/mocks.js b/src/activitypub/mocks.js index 74c577725d..374d4dc994 100644 --- a/src/activitypub/mocks.js +++ b/src/activitypub/mocks.js @@ -5,6 +5,7 @@ const mime = require('mime'); const user = require('../user'); const posts = require('../posts'); +const topics = require('../topics'); const activitypub = module.parent.exports; const Mocks = module.exports; @@ -53,7 +54,7 @@ Mocks.profile = async (actors) => { followingCount, inbox, - sharedInbox: endpoints.sharedInbox, + sharedInbox: endpoints ? endpoints.sharedInbox : null, }; return payload; @@ -174,13 +175,16 @@ Mocks.note = async (post) => { const cc = [`${nconf.get('url')}/user/${userslug}/followers`]; let inReplyTo = null; - if (post.toPid) { + let name = null; + if (post.toPid) { // direct reply inReplyTo = activitypub.helpers.isUri(post.toPid) ? post.toPid : `${nconf.get('url')}/post/${post.toPid}`; const parentId = await posts.getPostField(post.toPid, 'uid'); to.unshift(activitypub.helpers.isUri(parentId) ? parentId : `${nconf.get('url')}/uid/${parentId}`); - } else if (!post.isMainPost) { + } else if (!post.isMainPost) { // reply to OP inReplyTo = `${nconf.get('url')}/post/${post.topic.mainPid}`; to.unshift(activitypub.helpers.isUri(post.topic.uid) ? post.topic.uid : `${nconf.get('url')}/uid/${post.topic.uid}`); + } else { // new topic + name = await topics.getTitleByPid(post.pid); } const object = { @@ -194,6 +198,7 @@ Mocks.note = async (post) => { attributedTo: `${nconf.get('url')}/uid/${post.user.uid}`, sensitive: false, // todo summary: null, + name, content: post.content, source: { content: raw, diff --git a/src/controllers/activitypub/index.js b/src/controllers/activitypub/index.js index b718c55eb2..9f1c4f32a1 100644 --- a/src/controllers/activitypub/index.js +++ b/src/controllers/activitypub/index.js @@ -99,4 +99,6 @@ Controller.postInbox = async (req, res) => { break; } } + + res.sendStatus(200); }; diff --git a/src/topics/data.js b/src/topics/data.js index 18e68dcb26..572a86f2be 100644 --- a/src/topics/data.js +++ b/src/topics/data.js @@ -100,6 +100,7 @@ function modifyTopic(topic, fields) { if (validator.isUUID(String(topic.tid))) { intFields.splice(intFields.indexOf('uid'), 1); intFields.splice(intFields.indexOf('tid'), 1); + intFields.splice(intFields.indexOf('mainPid'), 1); } db.parseIntFields(topic, intFields, fields); diff --git a/test/activitypub.js b/test/activitypub.js index ac5d4574ce..ca28f3423e 100644 --- a/test/activitypub.js +++ b/test/activitypub.js @@ -11,6 +11,9 @@ const request = require('../src/request'); const meta = require('../src/meta'); const user = require('../src/user'); +const categories = require('../src/categories'); +const topics = require('../src/topics'); +const posts = require('../src/posts'); const privileges = require('../src/privileges'); const activitypub = require('../src/activitypub'); @@ -389,4 +392,57 @@ describe('ActivityPub integration', () => { }); }); }); + + describe.only('Receipt of ActivityPub events to inboxes (federating IN)', () => { + describe('Create', () => { + describe('Note', () => { + let category; + let uid; + let note; + let topic; + + before(async () => { + category = await categories.create({ name: 'test' }); + const slug = slugify(utils.generateUUID().slice(0, 8)); + uid = await user.create({ username: slug }); + + const { postData, topicData } = await topics.post({ + uid, + cid: category.cid, + title: 'Lipsum title', + content: 'Lorem ipsum dolor sit amet', + }); + + const post = (await posts.getPostSummaryByPids([postData.pid], uid, { stripTags: false })).pop(); + note = await activitypub.mocks.note(post); + + await activitypub.send(uid, [`${nconf.get('url')}/uid/${uid}`], { + type: 'Create', + object: note, + }); + + const tid = await posts.getPostField(note.id, 'tid'); + topic = await topics.getTopicData(tid); + }); + + it('should create a new topic if Note is at root-level or its parent has not been seen before', async () => { + const saved = await db.getObject(`post:${note.id}`); + + assert(saved); + assert(topic); + assert.strictEqual(saved.uid, `${nconf.get('url')}/uid/${uid}`); + assert.strictEqual(saved.content, 'Lorem ipsum dolor sit amet'); + assert(saved.tid); + }); + + it('should properly save the topic title in the topic hash', async () => { + assert.strictEqual(topic.title, 'Lipsum title'); + }); + + it('should properly save the mainPid in the topic hash', async () => { + assert.strictEqual(topic.mainPid, note.id); + }); + }); + }); + }); });