From 965ac0b21bc25e42cbbf96da9563bf00e2579663 Mon Sep 17 00:00:00 2001 From: Ricardo Garim Date: Tue, 25 Nov 2025 13:05:40 -0300 Subject: [PATCH] refactor: add StateID branded type on state_key from m.room.member --- .../src/services/invite.service.ts | 3 ++- .../src/services/profiles.service.ts | 3 ++- .../src/services/room.service.ts | 23 ++++++++++--------- .../controllers/internal/invite.controller.ts | 3 ++- .../controllers/internal/room.controller.ts | 3 ++- packages/room/src/types/_common.ts | 8 +++---- packages/room/src/types/v3-11.ts | 3 ++- 7 files changed, 26 insertions(+), 20 deletions(-) diff --git a/packages/federation-sdk/src/services/invite.service.ts b/packages/federation-sdk/src/services/invite.service.ts index 19117e496..0fea3996f 100644 --- a/packages/federation-sdk/src/services/invite.service.ts +++ b/packages/federation-sdk/src/services/invite.service.ts @@ -8,6 +8,7 @@ import { RoomVersion, UserID, extractDomainFromId, + stateIdSchema, } from '@rocket.chat/federation-room'; import { singleton } from 'tsyringe'; import { ConfigService } from './config.service'; @@ -82,7 +83,7 @@ export class InviteService { }), }, room_id: roomId, - state_key: userId, + state_key: stateIdSchema.parse(userId), auth_events: [], depth: 0, prev_events: [], diff --git a/packages/federation-sdk/src/services/profiles.service.ts b/packages/federation-sdk/src/services/profiles.service.ts index ac9fa965c..5eda7b08b 100644 --- a/packages/federation-sdk/src/services/profiles.service.ts +++ b/packages/federation-sdk/src/services/profiles.service.ts @@ -7,6 +7,7 @@ import { RoomID, RoomVersion, UserID, + stateIdSchema, } from '@rocket.chat/federation-room'; import { singleton } from 'tsyringe'; import { StateService } from './state.service'; @@ -90,7 +91,7 @@ export class ProfilesService { type: 'm.room.member', content: { membership: 'join' }, room_id: roomId, - state_key: userId, + state_key: stateIdSchema.parse(userId), auth_events: [], depth: 0, prev_events: [], diff --git a/packages/federation-sdk/src/services/room.service.ts b/packages/federation-sdk/src/services/room.service.ts index b546b78f4..4adbf45ef 100644 --- a/packages/federation-sdk/src/services/room.service.ts +++ b/packages/federation-sdk/src/services/room.service.ts @@ -28,6 +28,7 @@ import { RoomVersion, UserID, extractDomainFromId, + stateIdSchema, } from '@rocket.chat/federation-room'; import { EventStagingRepository } from '../repositories/event-staging.repository'; import { EventRepository } from '../repositories/event.repository'; @@ -261,7 +262,7 @@ export class RoomService { type: 'm.room.member', content: { membership: 'join' }, room_id: roomCreateEvent.roomId, - state_key: username, + state_key: stateIdSchema.parse(username), auth_events: [], depth: 0, prev_events: [], @@ -486,7 +487,7 @@ export class RoomService { const memberAuthResult = this.getEventByType( authEventIds, 'm.room.member', - (e) => e.event.state_key === senderId, + (e) => e.event.state_key === stateIdSchema.parse(senderId), ); // Ensure critical auth events were found @@ -616,7 +617,7 @@ export class RoomService { type: 'm.room.member', content: { membership: 'leave' }, room_id: roomId, - state_key: senderId, + state_key: stateIdSchema.parse(senderId), auth_events: [], depth: 0, prev_events: [], @@ -697,7 +698,7 @@ export class RoomService { reason: reason, }, room_id: roomId, - state_key: kickedUserId, + state_key: stateIdSchema.parse(kickedUserId), auth_events: [], depth: 0, prev_events: [], @@ -740,7 +741,7 @@ export class RoomService { }, room_id: roomId, sender: userId, - state_key: userId, + state_key: stateIdSchema.parse(userId), auth_events: [], depth: 0, prev_events: [], @@ -823,7 +824,7 @@ export class RoomService { reason: reason, }, room_id: roomId, - state_key: bannedUserId, + state_key: stateIdSchema.parse(bannedUserId), auth_events: [], depth: 0, prev_events: [], @@ -873,7 +874,7 @@ export class RoomService { type: 'm.room.member', content: { membership: 'join' }, room_id: roomId, - state_key: userId, + state_key: stateIdSchema.parse(userId), auth_events: [], depth: 0, prev_events: [], @@ -1423,7 +1424,7 @@ export class RoomService { displayname: creatorDisplayname, }, room_id: roomCreateEvent.roomId, - state_key: creatorUserId, + state_key: stateIdSchema.parse(creatorUserId), auth_events: [], depth: 0, prev_events: [], @@ -1540,7 +1541,7 @@ export class RoomService { displayname: displayname, }, room_id: roomCreateEvent.roomId, - state_key: targetUserId, + state_key: stateIdSchema.parse(targetUserId), auth_events: [], depth: 0, prev_events: [], @@ -1598,8 +1599,8 @@ export class RoomService { if ( currentUserIds.length === 2 && - currentUserIds.includes(userId1) && - currentUserIds.includes(userId2) + currentUserIds.includes(stateIdSchema.parse(userId1)) && + currentUserIds.includes(stateIdSchema.parse(userId2)) ) { return roomId; } diff --git a/packages/homeserver/src/controllers/internal/invite.controller.ts b/packages/homeserver/src/controllers/internal/invite.controller.ts index 197f25e13..475555faf 100644 --- a/packages/homeserver/src/controllers/internal/invite.controller.ts +++ b/packages/homeserver/src/controllers/internal/invite.controller.ts @@ -2,6 +2,7 @@ import { PersistentEventFactory, RoomID, UserID, + stateIdSchema, } from '@rocket.chat/federation-room'; import { federationSDK } from '@rocket.chat/federation-sdk'; import { Elysia } from 'elysia'; @@ -40,7 +41,7 @@ export const internalInvitePlugin = (app: Elysia) => { type: 'm.room.member', content: { membership: 'invite' }, room_id: roomId as RoomID, - state_key: username as UserID, + state_key: stateIdSchema.parse(username), auth_events: [], depth: 0, prev_events: [], diff --git a/packages/homeserver/src/controllers/internal/room.controller.ts b/packages/homeserver/src/controllers/internal/room.controller.ts index a91d93a86..ede695171 100644 --- a/packages/homeserver/src/controllers/internal/room.controller.ts +++ b/packages/homeserver/src/controllers/internal/room.controller.ts @@ -4,6 +4,7 @@ import { PersistentEventFactory, RoomID, UserID, + stateIdSchema, } from '@rocket.chat/federation-room'; import { federationSDK } from '@rocket.chat/federation-sdk'; import { Elysia, t } from 'elysia'; @@ -354,7 +355,7 @@ export const internalRoomPlugin = (app: Elysia) => { type: 'm.room.member', content: { membership: 'ban' }, room_id: roomId as RoomID, - state_key: userIdToBan as UserID, + state_key: stateIdSchema.parse(userIdToBan), auth_events: [], depth: 0, prev_events: [], diff --git a/packages/room/src/types/_common.ts b/packages/room/src/types/_common.ts index c6a092716..5026e4b47 100644 --- a/packages/room/src/types/_common.ts +++ b/packages/room/src/types/_common.ts @@ -7,10 +7,6 @@ export const eventIdSchema = z.string().brand('EventID'); export type EventID = z.infer; -const stateIdSchema = z.string().brand('StateID'); - -export type StateID = z.infer; - export const roomIdSchema = z.string().brand('RoomID'); export type RoomID = z.infer; @@ -19,6 +15,10 @@ export const userIdSchema = z.string().brand('UserID'); export type UserID = z.infer; +export const stateIdSchema = z.string().brand('StateID'); + +export type StateID = z.infer; + export type StateMapKey = `${PduType}:${StateKey}`; export type State = Map; diff --git a/packages/room/src/types/v3-11.ts b/packages/room/src/types/v3-11.ts index cfee2d9ac..537a14e2c 100644 --- a/packages/room/src/types/v3-11.ts +++ b/packages/room/src/types/v3-11.ts @@ -3,6 +3,7 @@ import { PduForType, eventIdSchema, roomIdSchema, + stateIdSchema, userIdSchema, } from './_common'; @@ -640,7 +641,7 @@ export const PduNoContentTimelineEventSchema = { export const PduNoContentStateEventSchema = { ...PduNoContentTimelineEventSchema, - state_key: userIdSchema.describe( + state_key: stateIdSchema.describe( 'The state key of the event. This is an optional field.', ), };