mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 16:46:12 +01:00
fix: #13375, plus additional tests
This commit is contained in:
@@ -41,6 +41,7 @@ inbox.create = async (req) => {
|
|||||||
return await activitypub.notes.assertPrivate(object);
|
return await activitypub.notes.assertPrivate(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Category sync, remove when cross-posting available
|
||||||
const { cids } = await activitypub.actors.getLocalFollowers(actor);
|
const { cids } = await activitypub.actors.getLocalFollowers(actor);
|
||||||
let cid = null;
|
let cid = null;
|
||||||
if (cids.size > 0) {
|
if (cids.size > 0) {
|
||||||
@@ -262,12 +263,19 @@ inbox.announce = async (req) => {
|
|||||||
let tid;
|
let tid;
|
||||||
let pid;
|
let pid;
|
||||||
|
|
||||||
|
// Category sync, remove when cross-posting available
|
||||||
const { cids } = await activitypub.actors.getLocalFollowers(actor);
|
const { cids } = await activitypub.actors.getLocalFollowers(actor);
|
||||||
let cid = null;
|
let cid = null;
|
||||||
if (cids.size > 0) {
|
if (cids.size > 0) {
|
||||||
cid = Array.from(cids)[0];
|
cid = Array.from(cids)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1b12 announce
|
||||||
|
const categoryActor = await categories.exists(actor);
|
||||||
|
if (categoryActor) {
|
||||||
|
cid = actor;
|
||||||
|
}
|
||||||
|
|
||||||
switch(true) {
|
switch(true) {
|
||||||
case object.type === 'Like': {
|
case object.type === 'Like': {
|
||||||
const id = object.object.id || object.object;
|
const id = object.object.id || object.object;
|
||||||
@@ -318,13 +326,7 @@ inbox.announce = async (req) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle case where Announce(Create(Note-ish)) is received
|
pid = object.id;
|
||||||
if (object.type === 'Create' && activitypub._constants.acceptedPostTypes.includes(object.object.type)) {
|
|
||||||
pid = object.object.id;
|
|
||||||
} else {
|
|
||||||
pid = object.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
pid = await activitypub.resolveId(0, pid); // in case wrong id is passed-in; unlikely, but still.
|
pid = await activitypub.resolveId(0, pid); // in case wrong id is passed-in; unlikely, but still.
|
||||||
if (!pid) {
|
if (!pid) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -115,24 +115,18 @@ Notes.assert = async (uid, input, options = { skipChecks: false }) => {
|
|||||||
if (hasTid) {
|
if (hasTid) {
|
||||||
mainPid = await topics.getTopicField(tid, 'mainPid');
|
mainPid = await topics.getTopicField(tid, 'mainPid');
|
||||||
} else {
|
} else {
|
||||||
// Check recipients/audience for category (local or remote)
|
// Check recipients/audience for local category
|
||||||
const set = activitypub.helpers.makeSet(_activitypub, ['to', 'cc', 'audience']);
|
const set = activitypub.helpers.makeSet(_activitypub, ['to', 'cc', 'audience']);
|
||||||
await activitypub.actors.assert(Array.from(set));
|
await activitypub.actors.assert(Array.from(set));
|
||||||
|
|
||||||
// Local
|
|
||||||
const resolved = await Promise.all(Array.from(set).map(async id => await activitypub.helpers.resolveLocalId(id)));
|
const resolved = await Promise.all(Array.from(set).map(async id => await activitypub.helpers.resolveLocalId(id)));
|
||||||
const recipientCids = resolved
|
const recipientCids = resolved
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.filter(({ type }) => type === 'category')
|
.filter(({ type }) => type === 'category')
|
||||||
.map(obj => obj.id);
|
.map(obj => obj.id);
|
||||||
|
|
||||||
// Remote
|
if (recipientCids.length) {
|
||||||
const assertedGroups = await db.exists(Array.from(set).map(id => `categoryRemote:${id}`));
|
|
||||||
const remoteCid = Array.from(set).filter((_, idx) => assertedGroups[idx]).shift();
|
|
||||||
|
|
||||||
if (remoteCid || recipientCids.length) {
|
|
||||||
// Overrides passed-in value, respect addressing from main post over booster
|
// Overrides passed-in value, respect addressing from main post over booster
|
||||||
options.cid = remoteCid || recipientCids.shift();
|
options.cid = recipientCids.shift();
|
||||||
}
|
}
|
||||||
|
|
||||||
// mainPid ok to leave as-is
|
// mainPid ok to leave as-is
|
||||||
|
|||||||
@@ -83,33 +83,6 @@ describe('Notes', () => {
|
|||||||
assert.strictEqual(topic.cid, cid);
|
assert.strictEqual(topic.cid, cid);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should slot newly created topic in remote category if addressed', async () => {
|
|
||||||
const { id: cid, actor } = helpers.mocks.group();
|
|
||||||
await activitypub.actors.assertGroup([cid]);
|
|
||||||
|
|
||||||
const { id } = helpers.mocks.note({
|
|
||||||
cc: [cid],
|
|
||||||
});
|
|
||||||
|
|
||||||
const assertion = await activitypub.notes.assert(0, id);
|
|
||||||
assert(assertion);
|
|
||||||
|
|
||||||
const { tid, count } = assertion;
|
|
||||||
assert(tid);
|
|
||||||
assert.strictEqual(count, 1);
|
|
||||||
|
|
||||||
const topic = await topics.getTopicData(tid);
|
|
||||||
assert.strictEqual(topic.cid, cid);
|
|
||||||
|
|
||||||
const tids = await db.getSortedSetMembers(`cid:${cid}:tids`);
|
|
||||||
assert(tids.includes(tid));
|
|
||||||
|
|
||||||
const category = await categories.getCategoryData(cid);
|
|
||||||
['topic_count', 'post_count', 'totalPostCount', 'totalTopicCount'].forEach((prop) => {
|
|
||||||
assert.strictEqual(category[prop], 1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add a remote category topic to a user\'s inbox if they are following the category', async () => {
|
it('should add a remote category topic to a user\'s inbox if they are following the category', async () => {
|
||||||
const { id: cid, actor } = helpers.mocks.group();
|
const { id: cid, actor } = helpers.mocks.group();
|
||||||
await activitypub.actors.assertGroup([cid]);
|
await activitypub.actors.assertGroup([cid]);
|
||||||
@@ -120,7 +93,7 @@ describe('Notes', () => {
|
|||||||
const { id } = helpers.mocks.note({
|
const { id } = helpers.mocks.note({
|
||||||
cc: [cid],
|
cc: [cid],
|
||||||
});
|
});
|
||||||
const { tid } = await activitypub.notes.assert(0, id);
|
const { tid } = await activitypub.notes.assert(0, id, { cid });
|
||||||
|
|
||||||
const inInbox = await db.isSortedSetMember(`uid:${uid}:inbox`, tid);
|
const inInbox = await db.isSortedSetMember(`uid:${uid}:inbox`, tid);
|
||||||
assert(inInbox);
|
assert(inInbox);
|
||||||
@@ -161,7 +134,7 @@ describe('Notes', () => {
|
|||||||
const { id } = helpers.mocks.note({
|
const { id } = helpers.mocks.note({
|
||||||
cc: [remoteCid],
|
cc: [remoteCid],
|
||||||
});
|
});
|
||||||
const assertion = await activitypub.notes.assert(0, id);
|
const assertion = await activitypub.notes.assert(0, id, { cid: remoteCid });
|
||||||
assert(assertion);
|
assert(assertion);
|
||||||
|
|
||||||
const unread = await topics.getTotalUnread(uid);
|
const unread = await topics.getTotalUnread(uid);
|
||||||
@@ -180,7 +153,7 @@ describe('Notes', () => {
|
|||||||
const { id, note } = helpers.mocks.note({
|
const { id, note } = helpers.mocks.note({
|
||||||
cc: [remoteCid],
|
cc: [remoteCid],
|
||||||
});
|
});
|
||||||
const assertion = await activitypub.notes.assert(0, id);
|
const assertion = await activitypub.notes.assert(0, id, { cid: remoteCid });
|
||||||
assert(assertion);
|
assert(assertion);
|
||||||
|
|
||||||
const unread = await topics.getTotalUnread(uid);
|
const unread = await topics.getTotalUnread(uid);
|
||||||
@@ -203,7 +176,7 @@ describe('Notes', () => {
|
|||||||
const { id, note } = helpers.mocks.note({
|
const { id, note } = helpers.mocks.note({
|
||||||
cc: [remoteCid],
|
cc: [remoteCid],
|
||||||
});
|
});
|
||||||
const assertion = await activitypub.notes.assert(0, id);
|
const assertion = await activitypub.notes.assert(0, id, { cid: remoteCid });
|
||||||
assert(assertion);
|
assert(assertion);
|
||||||
|
|
||||||
const unread = await topics.getTotalUnread(uid);
|
const unread = await topics.getTotalUnread(uid);
|
||||||
@@ -457,6 +430,44 @@ describe('Notes', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Create', () => {
|
||||||
|
let uid;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
uid = await user.create({ username: utils.generateUUID() });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('(Note)', () => {
|
||||||
|
it('should create a new topic in cid -1', async () => {
|
||||||
|
const { note, id } = helpers.mocks.note();
|
||||||
|
const { activity } = helpers.mocks.create(note);
|
||||||
|
|
||||||
|
await db.sortedSetAdd(`followersRemote:${note.attributedTo}`, Date.now(), uid);
|
||||||
|
await activitypub.inbox.create({ body: activity });
|
||||||
|
|
||||||
|
assert(await posts.exists(id));
|
||||||
|
|
||||||
|
const cid = await posts.getCidByPid(id);
|
||||||
|
assert.strictEqual(cid, -1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a new topic in cid -1 even if a remote category is addressed', async () => {
|
||||||
|
const { id: remoteCid } = helpers.mocks.group();
|
||||||
|
const { note, id } = helpers.mocks.note({
|
||||||
|
audience: [remoteCid],
|
||||||
|
});
|
||||||
|
const { activity } = helpers.mocks.create(note);
|
||||||
|
|
||||||
|
await activitypub.inbox.create({ body: activity });
|
||||||
|
|
||||||
|
assert(await posts.exists(id));
|
||||||
|
|
||||||
|
const cid = await posts.getCidByPid(id);
|
||||||
|
assert.strictEqual(cid, -1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('Announce', () => {
|
describe('Announce', () => {
|
||||||
let cid;
|
let cid;
|
||||||
|
|
||||||
@@ -464,6 +475,24 @@ describe('Notes', () => {
|
|||||||
({ cid } = await categories.create({ name: utils.generateUUID().slice(0, 8) }));
|
({ cid } = await categories.create({ name: utils.generateUUID().slice(0, 8) }));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('(Create)', () => {
|
||||||
|
it('should create a new topic in a remote category if addressed', async () => {
|
||||||
|
const { id: remoteCid } = helpers.mocks.group();
|
||||||
|
const { id, note } = helpers.mocks.note({
|
||||||
|
audience: [remoteCid],
|
||||||
|
});
|
||||||
|
let { activity } = helpers.mocks.create(note);
|
||||||
|
({ activity } = helpers.mocks.announce({ actor: remoteCid, object: activity }));
|
||||||
|
|
||||||
|
await activitypub.inbox.announce({ body: activity });
|
||||||
|
|
||||||
|
assert(await posts.exists(id));
|
||||||
|
|
||||||
|
const cid = await posts.getCidByPid(id);
|
||||||
|
assert.strictEqual(cid, remoteCid);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('(Note)', () => {
|
describe('(Note)', () => {
|
||||||
it('should create a new topic in cid -1 if category not addressed', async () => {
|
it('should create a new topic in cid -1 if category not addressed', async () => {
|
||||||
const { note } = helpers.mocks.note();
|
const { note } = helpers.mocks.note();
|
||||||
|
|||||||
Reference in New Issue
Block a user