1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-06 01:15:56 +02:00

fix(backend): handle relay-delivered Announce activities correctly (#17308)

* fix(backend): handle relay-delivered Announce activities correctly

Relay Announce activities now use the target note URI instead of the
Announce URI for federation allowlist checks, dedup locking, and
existence lookups. Notes delivered via relay are published directly to
the notes stream without creating a renote.

Closes #11056

* Update packages/backend/src/core/RelayService.ts

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>

---------

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
Jaehong Kang
2026-04-15 23:05:36 +09:00
committed by GitHub
parent 8e536eb4b9
commit 277a1ef31f
3 changed files with 30 additions and 5 deletions

View File

@@ -91,13 +91,27 @@ export class RelayService {
return JSON.stringify(result);
}
@bindThis
private getAcceptedRelays(): Promise<MiRelay[]> {
return this.relaysCache.fetch(() => this.relaysRepository.findBy({
status: 'accepted',
}));
}
@bindThis
public async isRelayActor(actor: { inbox: string | null; sharedInbox: string | null }): Promise<boolean> {
const relays = await this.getAcceptedRelays();
return relays.some(relay =>
(actor.inbox != null && relay.inbox === actor.inbox)
|| (actor.sharedInbox != null && relay.inbox === actor.sharedInbox),
);
}
@bindThis
public async deliverToRelays(user: { id: MiUser['id']; host: null; }, activity: any): Promise<void> {
if (activity == null) return;
const relays = await this.relaysCache.fetch(() => this.relaysRepository.findBy({
status: 'accepted',
}));
const relays = await this.getAcceptedRelays();
if (relays.length === 0) return;
const copy = deepClone(activity);

View File

@@ -302,12 +302,14 @@ export class ApInboxService {
@bindThis
private async announceNote(actor: MiRemoteUser, activity: IAnnounce, target: IPost, resolver?: Resolver): Promise<string | void> {
const uri = getApId(activity);
if (actor.isSuspended) {
return;
}
// リレーからのAnnounceかチェック
const fromRelay = await this.relayService.isRelayActor(actor);
const uri = getApId(fromRelay ? target : activity);
// アナウンス先が許可されているかチェック
if (!this.utilityService.isFederationAllowedUri(uri)) return;
@@ -336,6 +338,14 @@ export class ApInboxService {
throw err;
}
// リレーからのAnnounceはリートを作成せず、ートを直接公開する
if (fromRelay) {
this.logger.info(`Publishing relay-delivered note: ${uri}`);
const noteObj = await this.noteEntityService.pack(renote, null, { skipHide: true, withReactionAndUserPairCache: true });
this.globalEventService.publishNotesStream(noteObj);
return;
}
if (!await this.noteEntityService.isVisibleForMe(renote, actor.id)) {
return 'skip: invalid actor for this activity';
}