From d86b8c8752bb9eb5f6b4431403ed4bb0bc615c59 Mon Sep 17 00:00:00 2001 From: tamaina Date: Fri, 1 Mar 2024 18:29:30 +0000 Subject: [PATCH] =?UTF-8?q?getAuthUserFromApId=E3=81=A7updatePerson?= =?UTF-8?q?=E3=81=AE=E9=A0=BB=E5=BA=A6=E3=82=92=E5=A2=97=E3=82=84=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/activitypub/ApDbResolverService.ts | 80 ++++++++++--------- .../activitypub/models/ApPersonService.ts | 9 +-- 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts index 25a37ca096..9111906538 100644 --- a/packages/backend/src/core/activitypub/ApDbResolverService.ts +++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts @@ -116,6 +116,8 @@ export class ApDbResolverService implements OnApplicationShutdown { /** * AP Actor id => Misskey User and Key + * @param uri AP Actor id + * @param keyId Key id to find. If not specified, main key will be selected. */ @bindThis public async getAuthUserFromApId(uri: string, keyId?: string): Promise<{ @@ -125,50 +127,56 @@ export class ApDbResolverService implements OnApplicationShutdown { const user = await this.apPersonService.resolvePerson(uri, undefined, true) as MiRemoteUser; if (user.isDeleted) return null; - const keys = await this.publicKeyByUserIdCache.fetch( - user.id, - () => this.userPublickeysRepository.find({ where: { userId: user.id } }), - v => v != null, - ); + const keys = await this.getPublicKeyByUserId(user.id); - if (keys == null || !Array.isArray(keys)) return null; + if (keys == null || !Array.isArray(keys)) return { user, key: null }; - if (keys.length === 0) { - return { - user, - key: keys[0], - }; + if (!keyId) { + // mainっぽいのを選ぶ + const mainKey = keys.find(x => { + try { + const url = new URL(x.keyId); + const path = url.pathname.split('/').pop()?.toLowerCase(); + if (url.hash) { + if (url.hash.toLowerCase().includes('main')) { + return true; + } + } else if (path?.includes('main') || path === 'publickey') { + return true; + } + } catch { /* noop */ } + + return false; + }); + return { user, key: mainKey ?? keys[0] }; } const exactKey = keys.find(x => x.keyId === keyId); - if (exactKey) { - return { - user, - key: exactKey, - }; + if (exactKey) return { user, key: exactKey }; + + // keyIdで見つからない場合、lastFetchedAtでの更新制限を弱めて再取得 + if (user.lastFetchedAt == null || user.lastFetchedAt < new Date(Date.now() - 1000 * 60 * 12)) { + const renewed = await this.apPersonService.fetchPersonWithRenewal(uri, 0); + if (renewed == null || renewed.isDeleted) return null; + + this.refreshCacheByUserId(user.id); + const keys = await this.getPublicKeyByUserId(user.id); + if (keys == null || !Array.isArray(keys)) return null; + + const exactKey = keys.find(x => x.keyId === keyId); + if (exactKey) return { user, key: exactKey }; } - // 公開鍵は複数あるが、mainっぽいのを選ぶ - const mainKey = keys.find(x => { - try { - if (x.keyId === keyId) return true; - const url = new URL(x.keyId); - const path = url.pathname.split('/').pop()?.toLowerCase(); - if (url.hash) { - if (url.hash.toLowerCase().includes('main')) { - return true; - } - } else if (path?.includes('main') || path === 'publickey') { - return true; - } - } catch { /* noop */ } + return { user, key: null }; + } - return false; - }); - return { - user, - key: mainKey ?? keys[0], - }; + @bindThis + public async getPublicKeyByUserId(userId: MiUser['id']): Promise { + return await this.publicKeyByUserIdCache.fetch( + userId, + () => this.userPublickeysRepository.find({ where: { userId } }), + v => v != null, + ); } @bindThis diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 97abfcbde8..e331ea5395 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -250,18 +250,17 @@ export class ApPersonService implements OnModuleInit { } @bindThis - async fetchPersonWithRenewal(uri: string): Promise { + async fetchPersonWithRenewal(uri: string, TTL = REMOTE_USER_CACHE_TTL): Promise { const exist = await this.fetchPerson(uri); if (exist == null) return null; - // ついでにリモートユーザーの情報が古かったら更新しておく if (this.userEntityService.isRemoteUser(exist)) { - if (exist.lastFetchedAt == null || Date.now() - exist.lastFetchedAt.getTime() > REMOTE_USER_CACHE_TTL) { - this.logger.debug('fetchPersonWithRenewal: renew', { uri, lastFetchedAt: exist.lastFetchedAt }); + if (TTL === 0 || exist.lastFetchedAt == null || Date.now() - exist.lastFetchedAt.getTime() > TTL) { + this.logger.debug('fetchPersonWithRenewal: renew', { uri, TTL, lastFetchedAt: exist.lastFetchedAt }); await this.updatePerson(exist.uri); return await this.fetchPerson(uri); } - this.logger.debug('fetchPersonWithRenewal: use cache', { uri, lastFetchedAt: exist.lastFetchedAt }); + this.logger.debug('fetchPersonWithRenewal: use cache', { uri, TTL, lastFetchedAt: exist.lastFetchedAt }); } return exist;