feat: remote group actors migrated to categories if they were previous asserted as remote users

This commit is contained in:
Julian Lam
2025-03-24 11:53:39 -04:00
parent c6f2c87478
commit d19f692b8d
2 changed files with 33 additions and 3 deletions

View File

@@ -74,13 +74,24 @@ Actors.qualify = async (ids, options = {}) => {
ids = ids.filter(uri => uri !== 'loopback' && new URL(uri).host !== nconf.get('url_parsed').host);
}
// Separate those who need migration from user to category
const migrate = new Set();
if (options.qualifyGroup) {
const exists = await db.exists(ids.map(id => `userRemote:${id}`));
ids.forEach((id, idx) => {
if (exists[idx]) {
migrate.add(id);
}
});
}
// Only assert those who haven't been seen recently (configurable), unless update flag passed in (force refresh)
if (!options.update) {
const upperBound = Date.now() - (1000 * 60 * 60 * 24 * meta.config.activitypubUserPruneDays);
const lastCrawled = await db.sortedSetScores('usersRemote:lastCrawled', ids.map(id => ((typeof id === 'object' && id.hasOwnProperty('id')) ? id.id : id)));
ids = ids.filter((id, idx) => {
const timestamp = lastCrawled[idx];
return !timestamp || timestamp < upperBound;
return migrate.has(id) || !timestamp || timestamp < upperBound;
});
}
@@ -267,7 +278,10 @@ Actors.assertGroup = async (ids, options = {}) => {
* - true: no new IDs processed; all passed-in IDs present.
*/
ids = await Actors.qualify(ids, options);
ids = await Actors.qualify(ids, {
qualifyGroup: true,
...options,
});
if (!ids) {
return ids;
}

View File

@@ -76,6 +76,20 @@ describe('Actor asserton', () => {
assert.strictEqual(assertion[0].cid, actor.id);
});
it('should not migrate a user to a category if .assert is called', async () => {
// ... because the user isn't due for an update and so is filtered out during qualification
const { id } = helpers.mocks.person();
await activitypub.actors.assert([id]);
const { actor } = helpers.mocks.group({ id });
const assertion = await activitypub.actors.assertGroup([id]);
assert(assertion.length, 0);
const exists = await user.exists(id);
assert.strictEqual(exists, false);
});
it('should migrate a user to a category if on re-assertion it identifies as an as:Group', async () => {
// This is to handle previous behaviour that saved all as:Group actors as NodeBB users.
const { id } = helpers.mocks.person();
@@ -91,7 +105,9 @@ describe('Actor asserton', () => {
}
const { actor } = helpers.mocks.group({ id });
const assertion = await activitypub.actors.assert([id], { update: true });
const assertion = await activitypub.actors.assertGroup([id]);
assert(assertion && Array.isArray(assertion) && assertion.length === 1);
const { topic_count, post_count } = await categories.getCategoryData(id);
assert.strictEqual(topic_count, 2);