diff --git a/CHANGELOG.md b/CHANGELOG.md index 68db7f41c5..dc81997d41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -91,6 +91,7 @@ - Fix: muteがapiからのuser list timeline取得で機能しない問題を修正 - Fix: ジョブキュー管理画面の認証を回避できる問題を修正 - Fix: 一部のサーバー内部エラーがスタックトレースを返さないように修正 +- Fix: 一部のリモートユーザーをフォローすることができない問題を修正 ## 13.14.2 diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts index 058869ca77..9ca63c9ec5 100644 --- a/packages/backend/src/core/activitypub/ApResolverService.ts +++ b/packages/backend/src/core/activitypub/ApResolverService.ts @@ -4,9 +4,10 @@ */ import { Inject, Injectable } from '@nestjs/common'; +import { IsNull, Not } from 'typeorm'; import type { MiLocalUser, MiRemoteUser } from '@/models/User.js'; import { InstanceActorService } from '@/core/InstanceActorService.js'; -import type { NotesRepository, PollsRepository, NoteReactionsRepository, UsersRepository } from '@/models/_.js'; +import type { NotesRepository, PollsRepository, NoteReactionsRepository, UsersRepository, FollowRequestsRepository } from '@/models/_.js'; import type { Config } from '@/config.js'; import { MetaService } from '@/core/MetaService.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; @@ -32,6 +33,7 @@ export class Resolver { private notesRepository: NotesRepository, private pollsRepository: PollsRepository, private noteReactionsRepository: NoteReactionsRepository, + private followRequestsRepository: FollowRequestsRepository, private utilityService: UtilityService, private instanceActorService: InstanceActorService, private metaService: MetaService, @@ -146,13 +148,24 @@ export class Resolver { return this.noteReactionsRepository.findOneByOrFail({ id: parsed.id }).then(async reaction => this.apRendererService.addContext(await this.apRendererService.renderLike(reaction, { uri: null }))); case 'follows': - // rest should be - if (parsed.rest == null || !/^\w+$/.test(parsed.rest)) throw new Error('resolveLocal: invalid follow URI'); - - return Promise.all( - [parsed.id, parsed.rest].map(id => this.usersRepository.findOneByOrFail({ id })), - ) - .then(([follower, followee]) => this.apRendererService.addContext(this.apRendererService.renderFollow(follower as MiLocalUser | MiRemoteUser, followee as MiLocalUser | MiRemoteUser, url))); + return this.followRequestsRepository.findOneBy({ id: parsed.id }) + .then(async followRequest => { + if (followRequest == null) throw new Error('resolveLocal: invalid follow request ID'); + const [follower, followee] = await Promise.all([ + this.usersRepository.findOneBy({ + id: followRequest.followerId, + host: IsNull(), + }), + this.usersRepository.findOneBy({ + id: followRequest.followeeId, + host: Not(IsNull()), + }), + ]); + if (follower == null || followee == null) { + throw new Error('resolveLocal: follower or followee does not exist'); + } + return this.apRendererService.addContext(this.apRendererService.renderFollow(follower as MiLocalUser | MiRemoteUser, followee as MiLocalUser | MiRemoteUser, url)); + }); default: throw new Error(`resolveLocal: type ${parsed.type} unhandled`); } @@ -177,6 +190,9 @@ export class ApResolverService { @Inject(DI.noteReactionsRepository) private noteReactionsRepository: NoteReactionsRepository, + @Inject(DI.followRequestsRepository) + private followRequestsRepository: FollowRequestsRepository, + private utilityService: UtilityService, private instanceActorService: InstanceActorService, private metaService: MetaService, @@ -196,6 +212,7 @@ export class ApResolverService { this.notesRepository, this.pollsRepository, this.noteReactionsRepository, + this.followRequestsRepository, this.utilityService, this.instanceActorService, this.metaService, diff --git a/packages/backend/test/misc/mock-resolver.ts b/packages/backend/test/misc/mock-resolver.ts index 07abe515c3..7cba7a2aa8 100644 --- a/packages/backend/test/misc/mock-resolver.ts +++ b/packages/backend/test/misc/mock-resolver.ts @@ -15,7 +15,7 @@ import type { LoggerService } from '@/core/LoggerService.js'; import type { MetaService } from '@/core/MetaService.js'; import type { UtilityService } from '@/core/UtilityService.js'; import { bindThis } from '@/decorators.js'; -import type { NoteReactionsRepository, NotesRepository, PollsRepository, UsersRepository } from '@/models/_.js'; +import type { NoteReactionsRepository, NotesRepository, PollsRepository, UsersRepository, FollowRequestsRepository } from '@/models/_.js'; type MockResponse = { type: string; @@ -33,6 +33,7 @@ export class MockResolver extends Resolver { {} as NotesRepository, {} as PollsRepository, {} as NoteReactionsRepository, + {} as FollowRequestsRepository, {} as UtilityService, {} as InstanceActorService, {} as MetaService,