diff --git a/packages/federation-sdk/src/index.ts b/packages/federation-sdk/src/index.ts index fa5ac504..ced12d86 100644 --- a/packages/federation-sdk/src/index.ts +++ b/packages/federation-sdk/src/index.ts @@ -1,11 +1,7 @@ import 'reflect-metadata'; import type { Emitter } from '@rocket.chat/emitter'; -import type { - EventStagingStore, - Membership, - MessageType, -} from '@rocket.chat/federation-core'; +import type { EventStagingStore } from '@rocket.chat/federation-core'; import type { EventID, EventStore, @@ -91,6 +87,10 @@ export type HomeserverEventSignatures = { event_id: EventID; event: PduForType<'m.room.encrypted'>; }; + 'homeserver.matrix.room.create': { + event: PduForType<'m.room.create'>; + event_id: EventID; + }; 'homeserver.matrix.message': { event_id: EventID; event: PduForType<'m.room.message'>; diff --git a/packages/federation-sdk/src/services/invite.service.ts b/packages/federation-sdk/src/services/invite.service.ts index db8b32eb..19117e49 100644 --- a/packages/federation-sdk/src/services/invite.service.ts +++ b/packages/federation-sdk/src/services/invite.service.ts @@ -12,8 +12,14 @@ import { import { singleton } from 'tsyringe'; import { ConfigService } from './config.service'; import { EventAuthorizationService } from './event-authorization.service'; +import { EventEmitterService } from './event-emitter.service'; +import { EventService } from './event.service'; import { FederationService } from './federation.service'; -import { StateService, UnknownRoomError } from './state.service'; +import { + RoomInfoNotReadyError, + StateService, + UnknownRoomError, +} from './state.service'; // TODO: Have better (detailed/specific) event input type export type ProcessInviteEvent = { event: EventBase; @@ -37,6 +43,7 @@ export class InviteService { private readonly stateService: StateService, private readonly configService: ConfigService, private readonly eventAuthorizationService: EventAuthorizationService, + private readonly emitterService: EventEmitterService, ) {} /** @@ -103,6 +110,11 @@ export class InviteService { // without it join events will not be processed if /event/{eventId} causes problems void federationService.sendEventToAllServersInRoom(inviteEvent); + this.emitterService.emit('homeserver.matrix.membership', { + event_id: inviteEvent.eventId, + event: inviteEvent.event, + }); + return { event_id: inviteEvent.eventId, event: PersistentEventFactory.createFromRawEvent( @@ -133,6 +145,11 @@ export class InviteService { // let everyone know void federationService.sendEventToAllServersInRoom(inviteEvent); + this.emitterService.emit('homeserver.matrix.membership', { + event_id: inviteEvent.eventId, + event: inviteEvent.event, + }); + return { event_id: inviteEvent.eventId, event: PersistentEventFactory.createFromRawEvent( @@ -226,6 +243,11 @@ export class InviteService { // we do not send transaction here // the asking server will handle the transactions + + this.emitterService.emit('homeserver.matrix.membership', { + event_id: inviteEvent.eventId, + event: inviteEvent.event, + }); } // we are not the host of the server diff --git a/packages/federation-sdk/src/services/room.service.ts b/packages/federation-sdk/src/services/room.service.ts index 35baf041..b546b78f 100644 --- a/packages/federation-sdk/src/services/room.service.ts +++ b/packages/federation-sdk/src/services/room.service.ts @@ -8,7 +8,6 @@ import { roomPowerLevelsEvent, } from '@rocket.chat/federation-core'; import { delay, inject, singleton } from 'tsyringe'; -import { FederationService } from './federation.service'; import { ForbiddenError, @@ -34,11 +33,17 @@ import { EventStagingRepository } from '../repositories/event-staging.repository import { EventRepository } from '../repositories/event.repository'; import { RoomRepository } from '../repositories/room.repository'; import { ConfigService } from './config.service'; +import { EventAuthorizationService } from './event-authorization.service'; import { EventEmitterService } from './event-emitter.service'; import { EventFetcherService } from './event-fetcher.service'; import { EventService } from './event.service'; +import { FederationService } from './federation.service'; import { InviteService } from './invite.service'; -import { StateService, UnknownRoomError } from './state.service'; +import { + RoomInfoNotReadyError, + StateService, + UnknownRoomError, +} from './state.service'; @singleton() export class RoomService { @@ -57,6 +62,7 @@ export class RoomService { private readonly eventRepository: EventRepository, @inject(delay(() => EventStagingRepository)) private readonly eventStagingRepository: EventStagingRepository, + private readonly emitterService: EventEmitterService, ) {} private validatePowerLevelChange( @@ -890,6 +896,11 @@ export class RoomService { void federationService.sendEventToAllServersInRoom(membershipEvent); + this.emitterService.emit('homeserver.matrix.membership', { + event_id: membershipEvent.eventId, + event: membershipEvent.event, + }); + return membershipEvent.eventId; } @@ -1268,6 +1279,7 @@ export class RoomService { await this.roomRepository.markRoomAsDeleted(roomId, event.eventId); + // TODO: check if all sendEventToAllServersInRoom should be followed by an emitter void this.federationService.sendEventToAllServersInRoom(event); logger.info(`Successfully marked room ${roomId} as tombstone`); diff --git a/packages/federation-sdk/src/services/staging-area.service.ts b/packages/federation-sdk/src/services/staging-area.service.ts index a64a0a68..df8d3ae3 100644 --- a/packages/federation-sdk/src/services/staging-area.service.ts +++ b/packages/federation-sdk/src/services/staging-area.service.ts @@ -268,12 +268,17 @@ export class StagingAreaService { private async processNotificationStage(event: EventStagingStore) { this.logger.debug(`Notifying clients about event ${event._id}`); - const { - _id: eventId, - event: { room_id: roomId }, - } = event; + const { _id: eventId, roomId } = event; switch (true) { + case event.event.type === 'm.room.create': + { + this.eventEmitterService.emit('homeserver.matrix.room.create', { + event_id: eventId, + event: event.event, + }); + } + break; case event.event.type === 'm.room.message': this.eventEmitterService.emit('homeserver.matrix.message', { event_id: eventId, diff --git a/packages/federation-sdk/src/services/state.service.ts b/packages/federation-sdk/src/services/state.service.ts index a744402b..82b40dbf 100644 --- a/packages/federation-sdk/src/services/state.service.ts +++ b/packages/federation-sdk/src/services/state.service.ts @@ -58,6 +58,13 @@ export class PartialStateResolutionError extends Error { export class UnknownRoomError extends Error { constructor(roomId: RoomID) { super(`Room ${roomId} does not exist`); + this.name = 'UnknownRoomError'; + } +} +export class RoomInfoNotReadyError extends Error { + constructor(message: string) { + super(message); + this.name = 'RoomInfoNotReadyError'; } } @@ -82,7 +89,9 @@ export class StateService { 'm.room.create', )) ?? {}; if (event?.type !== 'm.room.create') { - throw new Error('Create event mapping not found for room information'); + throw new RoomInfoNotReadyError( + 'Create event mapping not found for room information', + ); } if (!stateId) {