From a9a5ab5e4bfef9acde8d45d04322081f44a3da47 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 8 May 2025 13:41:43 -0400 Subject: [PATCH 1/3] fix: #13397, update getCidByHandle to work with remote categories, fix sync with handles causing issues with null entries --- src/api/activitypub.js | 10 +++++++++- src/categories/index.js | 8 +++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/api/activitypub.js b/src/api/activitypub.js index be6600d3a2..ed9e6f2f64 100644 --- a/src/api/activitypub.js +++ b/src/api/activitypub.js @@ -13,6 +13,7 @@ const winston = require('winston'); const db = require('../database'); const user = require('../user'); +const categories = require('../categories'); const meta = require('../meta'); const privileges = require('../privileges'); const activitypub = require('../activitypub'); @@ -43,7 +44,14 @@ activitypubApi.follow = enabledCheck(async (caller, { type, id, actor } = {}) => throw new Error('[[error:activitypub.invalid-id]]'); } - actor = actor.includes('@') ? await user.getUidByUserslug(actor) : actor; + if (actor.includes('@')) { + const [uid, cid] = await Promise.all([ + user.getUidByUserslug(actor), + categories.getCidByHandle(actor), + ]); + + actor = uid || cid; + } const [handle, isFollowing] = await Promise.all([ user.getUserField(actor, 'username'), db.isSortedSetMember(type === 'uid' ? `followingRemote:${id}` : `cid:${id}:following`, actor), diff --git a/src/categories/index.js b/src/categories/index.js index 308516cd97..de7ff6d769 100644 --- a/src/categories/index.js +++ b/src/categories/index.js @@ -85,7 +85,13 @@ Categories.getCategoryById = async function (data) { }; Categories.getCidByHandle = async function (handle) { - return await db.sortedSetScore('categoryhandle:cid', handle); + let cid = await db.sortedSetScore('categoryhandle:cid', handle); + if (!cid) { + // remote cids + cid = await db.getObjectField('handle:cid', handle); + } + + return cid; }; Categories.getAllCidsFromSet = async function (key) { From 401ff797c91217c4887b86f013f038b7d4e09b13 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 8 May 2025 13:55:17 -0400 Subject: [PATCH 2/3] fix: #13392, regression from c6f2c87, unable to unfollow from pending follows --- src/api/activitypub.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/api/activitypub.js b/src/api/activitypub.js index ed9e6f2f64..2752a50bc6 100644 --- a/src/api/activitypub.js +++ b/src/api/activitypub.js @@ -84,13 +84,22 @@ activitypubApi.unfollow = enabledCheck(async (caller, { type, id, actor }) => { throw new Error('[[error:activitypub.invalid-id]]'); } - actor = actor.includes('@') ? await user.getUidByUserslug(actor) : actor; - const [handle, isFollowing] = await Promise.all([ + if (actor.includes('@')) { + const [uid, cid] = await Promise.all([ + user.getUidByUserslug(actor), + categories.getCidByHandle(actor), + ]); + + actor = uid || cid; + } + + const [handle, isFollowing, isPending] = await Promise.all([ user.getUserField(actor, 'username'), db.isSortedSetMember(type === 'uid' ? `followingRemote:${id}` : `cid:${id}:following`, actor), + db.isSortedSetMember(`followRequests:${type === 'uid' ? 'uid' : 'cid'}.${id}`, actor), ]); - if (!isFollowing) { // already not following + if (!isFollowing && !isPending) { // already not following/pending return; } From 26e6a22278c426802e8f80e70cefcffc73653a25 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 8 May 2025 13:55:42 -0400 Subject: [PATCH 3/3] fix: #13397, null values in category sync list --- src/upgrades/4.3.2/fix_category_sync_null_values.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/upgrades/4.3.2/fix_category_sync_null_values.js diff --git a/src/upgrades/4.3.2/fix_category_sync_null_values.js b/src/upgrades/4.3.2/fix_category_sync_null_values.js new file mode 100644 index 0000000000..e81590cf27 --- /dev/null +++ b/src/upgrades/4.3.2/fix_category_sync_null_values.js @@ -0,0 +1,12 @@ +'use strict'; + +const db = require('../../database'); + +module.exports = { + name: 'Fix null values in category synchronization list', + timestamp: Date.UTC(2025, 4, 8), + method: async () => { + const cids = await db.getSortedSetMembers('categories:cid'); + await db.sortedSetsRemove(cids.map(cid => `followRequests:cid.${cid}`), 'null'); + }, +};