diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts index 87e3b7ed5f..a5259b1c4a 100644 --- a/packages/backend/src/core/activitypub/ApDbResolverService.ts +++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts @@ -10,11 +10,13 @@ import type { Config } from '@/config.js'; import { MemoryKVCache } from '@/misc/cache.js'; import type { MiUserPublickey } from '@/models/UserPublickey.js'; import { CacheService } from '@/core/CacheService.js'; +import { TimeService } from '@/global/TimeService.js'; import { UtilityService } from '@/core/UtilityService.js'; import type { MiNote } from '@/models/Note.js'; import { bindThis } from '@/decorators.js'; import type { MiLocalUser, MiRemoteUser } from '@/models/User.js'; import { ApLoggerService } from '@/core/activitypub/ApLoggerService.js'; +import { IdService } from '@/core/IdService.js'; import { getApId } from './type.js'; import { ApPersonService } from './models/ApPersonService.js'; import type { IObject } from './type.js'; @@ -40,6 +42,8 @@ export class ApDbResolverService implements OnApplicationShutdown { private apPersonService: ApPersonService, private apLoggerService: ApLoggerService, private utilityService: UtilityService, + private readonly idService: IdService, + private readonly timeService: TimeService, ) { // Caches moved to ApPersonService to avoid circular dependency } @@ -125,20 +129,36 @@ export class ApDbResolverService implements OnApplicationShutdown { */ @bindThis public async refetchPublicKeyForApId(user: MiRemoteUser): Promise { + const oldKey = await this.apPersonService.findPublicKeyByUserId(user.id); + + // Don't re-fetch if we've updated the user recently + const maxUpdatedTime = this.timeService.now - (1000 * 60 * 60); // 1 hour + if ((user.lastFetchedAt && user.lastFetchedAt.valueOf() > maxUpdatedTime) || + (user.updatedAt && user.updatedAt.valueOf() > maxUpdatedTime) || + this.idService.parse(user.id).date.valueOf() > maxUpdatedTime + ) { + this.apLoggerService.logger.debug(`Not updating public key for user ${user.id} (${user.uri}): already checked recently`); + return oldKey; + } + this.apLoggerService.logger.debug(`Updating public key for user ${user.id} (${user.uri})`); - const oldKey = await this.apPersonService.findPublicKeyByUserId(user.id); + // updatePerson will update the public key cache if there's any changes. await this.apPersonService.updatePerson(user.uri); const newKey = await this.apPersonService.findPublicKeyByUserId(user.id); - if (newKey) { - if (oldKey && newKey.keyPem === oldKey.keyPem) { + if (newKey && oldKey) { + if (newKey.keyPem === oldKey.keyPem) { this.apLoggerService.logger.debug(`Public key is up-to-date for user ${user.id} (${user.uri})`); } else { this.apLoggerService.logger.info(`Updated public key for user ${user.id} (${user.uri})`); } + } else if (newKey) { + this.apLoggerService.logger.info(`Registered public key for user ${user.id} (${user.uri})`); + } else if (oldKey) { + this.apLoggerService.logger.info(`Deleted public key for user ${user.id} (${user.uri})`); } else { - this.apLoggerService.logger.warn(`Failed to update public key for user ${user.id} (${user.uri})`); + this.apLoggerService.logger.warn(`Could not find any public key for user ${user.id} (${user.uri})`); } return newKey ?? oldKey; diff --git a/packages/backend/src/queue/processors/InboxProcessorService.ts b/packages/backend/src/queue/processors/InboxProcessorService.ts index 4efbb088c6..13b2885263 100644 --- a/packages/backend/src/queue/processors/InboxProcessorService.ts +++ b/packages/backend/src/queue/processors/InboxProcessorService.ts @@ -164,7 +164,12 @@ export class InboxProcessorService implements OnApplicationShutdown { // publicKey がなくても終了 if (authUser.key == null) { - throw new Bull.UnrecoverableError(`skip: failed to resolve user publicKey ${actorId}`); + // See if a key has become available since we fetched the actor + authUser.key = await this.apDbResolverService.refetchPublicKeyForApId(authUser.user); + if (authUser.key == null) { + // If it's still missing, then give up + throw new Bull.UnrecoverableError(`skip: failed to resolve user publicKey ${actorId}`); + } } // HTTP-Signatureの検証