diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts index 7ae58973df..3a84789e49 100644 --- a/packages/backend/src/core/activitypub/ApDbResolverService.ts +++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts @@ -7,7 +7,7 @@ import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import * as misskey from 'misskey-js'; import { IsNull } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { NotesRepository, UserPublickeysRepository, UsersRepository } from '@/models/_.js'; +import type { MiMeta, NotesRepository, UserPublickeysRepository, UsersRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import { MemoryKVCache } from '@/misc/cache.js'; import type { MiUserPublickey } from '@/models/UserPublickey.js'; @@ -51,6 +51,9 @@ export class ApDbResolverService implements OnApplicationShutdown { @Inject(DI.config) private config: Config, + @Inject(DI.meta) + private meta: MiMeta, + @Inject(DI.usersRepository) private usersRepository: UsersRepository, @@ -128,14 +131,25 @@ export class ApDbResolverService implements OnApplicationShutdown { * AP Person => Misskey User in DB */ @bindThis - public async getUserFromApId(value: string | IObject, acceptAcct: boolean = false): Promise { + public async getUserFromApId(value: string | IObject, acceptAcct = false): Promise { const parsed = this.parseLocalUri(value); if (acceptAcct && 'acct' in parsed) { - return await this.usersRepository.findOneBy({ - usernameLower: parsed.acct.username.toLowerCase(), - host: (parsed.acct.host == null || parsed.local) ? IsNull() : this.utilityService.toPuny(parsed.acct.host), - }) as MiLocalUser | MiRemoteUser | null; + if (parsed.acct.host == null || parsed.local) { + return await this.usersRepository.findOneBy({ + usernameLower: parsed.acct.username.toLowerCase(), + host: IsNull(), + }) as MiLocalUser | null; + } + + if (this.meta.allowExternalApRedirect) { + return await this.usersRepository.findOneBy({ + usernameLower: parsed.acct.username.toLowerCase(), + host: this.utilityService.toPuny(parsed.acct.host), + }) as MiRemoteUser | null; + } + + return null; } if ('uri' in parsed) { diff --git a/packages/backend/test-federation/test/api/ap/show.test.ts b/packages/backend/test-federation/test/api/ap/show.test.ts index 1effbf4cf9..04fffdece5 100644 --- a/packages/backend/test-federation/test/api/ap/show.test.ts +++ b/packages/backend/test-federation/test/api/ap/show.test.ts @@ -1,5 +1,5 @@ import { strictEqual, rejects } from 'node:assert'; -import { createAccount, resolveRemoteUser, sleep, type LoginUser } from '../../utils.js'; +import { createAccount, resolveRemoteUser, sleep, type LoginUser } from '../../uatils.js'; describe('API ap/show', () => { let alice: LoginUser, bob: LoginUser; @@ -37,15 +37,30 @@ describe('API ap/show', () => { }); test('resolve a fetched remote user by local profile url (https://a.test/@bob@b.test)', async () => { + await alice.client.request('admin/update-meta', { allowExternalApRedirect: true }); await resolveRemoteUser('b.test', bob.id, alice); const res = await alice.client.request('ap/show', { uri: `https://a.test/@${bob.username}@b.test` }); strictEqual(res.type, 'User'); strictEqual(res.object.uri, `https://b.test/users/${bob.id}`); }); + test('throws in resolving a fetched remote user by local profile url when allowExternalApRedirect: false', async () => { + await alice.client.request('admin/update-meta', { allowExternalApRedirect: false }); + await resolveRemoteUser('b.test', bob.id, alice); + + await rejects( + async () => await alice.client.request('ap/show', { uri: `https://a.test/@${bob.username}@b.test` }), + (err: any) => { + strictEqual(err.code, 'NO_SUCH_OBJECT'); + return true; + }, + ); + }); + test('throws in resolving a non-fetched remote user by local profile url (https://a.test/@bob@b.test)', async () => { // ユーザーがこのような問い合わせをすることは、ない! + await alice.client.request('admin/update-meta', { allowExternalApRedirect: true }); await rejects( async () => await alice.client.request('ap/show', { uri: `https://a.test/@${bob.username}@b.test` }), (err: any) => {