Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions packages/room/src/authorizartion-rules/rules-v2.1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { PersistentEventFactory } from "..";
import { PersistentEventBase } from "../manager/event-wrapper";


function isCreateAllowed(event: PersistentEventBase<'12', 'm.room.create'>): boolean {
if (event.getPreviousEventIds().length > 0) {
return false;
}

if (event.event.room_id) {
// changed in this version
return false;
}

// SPEC: If content.room_version is present and is not a recognised version, reject.
if (!PersistentEventFactory.isSupportedRoomVersion( event.getContent().room_version)) {
return false;
}
// SPEC: [New in this version] If additional_creators is present in content and is not an array of strings where each string passes the same user ID validation applied to sender, reject.
// ^ TODO

return true;
}
7 changes: 2 additions & 5 deletions packages/room/src/manager/event-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { PowerLevelEvent } from './power-level-event-wrapper';
import { type RoomVersion } from './type';
import { type RejectCode, RejectCodes } from '../authorizartion-rules/errors';
import { type EventStore, getStateMapKey } from '../state_resolution/definitions/definitions';
import type { EventID, PduForType, StateMapKey } from '../types/_common';
import type { EventID, RoomID, PduForType, StateMapKey } from '../types/_common';
import type { Pdu, PduContent, PduType, Signature, PduJoinRuleEventContent, PduMembershipEventContent } from '../types/v3-11';

export function extractDomainFromId(identifier: string) {
Expand Down Expand Up @@ -85,10 +85,6 @@ export abstract class PersistentEventBase<Version extends RoomVersion = RoomVers
return this.rawEvent.type as Type;
}

get roomId() {
return this.rawEvent.room_id;
}

get sender() {
return this.rawEvent.sender;
}
Expand Down Expand Up @@ -147,6 +143,7 @@ export abstract class PersistentEventBase<Version extends RoomVersion = RoomVers

// v1 should have this already, others, generates it
abstract get eventId(): EventID;
abstract get roomId(): RoomID;

getContent<T extends PduContent<Type>>(): T {
return this.rawEvent.content as T;
Expand Down
6 changes: 5 additions & 1 deletion packages/room/src/manager/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { PersistentEventV9 } from './v9';
import { RoomID, roomIdSchema } from '../types/_common';
import type { PduForType, UserID } from '../types/_common';
import type { Pdu, PduType, PduCreateEventContent } from '../types/v3-11';
import { PersistentEventV12 } from './v12';

// Utility function to create a random ID for room creation
function createRoomIdPrefix(length: number) {
Expand Down Expand Up @@ -36,9 +37,10 @@ export class PersistentEventFactory {
'9',
'10',
'11',
'12',
];

static defaultRoomVersion = '10' as const; // same as synapse
static defaultRoomVersion = '12' as const; // same as synapse

static isSupportedRoomVersion(roomVersion: string): roomVersion is RoomVersion {
return PersistentEventFactory.supportedRoomVersions.includes(roomVersion);
Expand Down Expand Up @@ -68,6 +70,8 @@ export class PersistentEventFactory {
return new PersistentEventV9(event, roomVersion, partial);
case '11':
return new PersistentEventV11(event, roomVersion, partial);
case '12':
return new PersistentEventV12(event, roomVersion, partial);
default:
throw new Error(`Unknown room version: ${roomVersion}`);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/room/src/manager/type.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export type RoomVersion1And2 = '1' | '2';

export type RoomVersion3To11 = '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11';
export type RoomVersion3To12 = '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12';

export type RoomVersion = RoomVersion1And2 | RoomVersion3To11;
export type RoomVersion = RoomVersion1And2 | RoomVersion3To12;
13 changes: 13 additions & 0 deletions packages/room/src/manager/v12.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { REDACT_ALLOW_ALL_KEYS } from './event-wrapper';
import { PersistentEventV9 } from './v9';
import { type PduType } from '../types/v3-11';
import { RoomID } from '../types/_common';
import { PersistentEventV11 } from './v11';

export class PersistentEventV12<Type extends PduType = PduType> extends PersistentEventV11<Type> {
get roomId(): RoomID {
const eid = this.eventId;
// SPEC: Note: The room ID is the event ID of the event with sigil ! instead of $.
return eid.replace(/^\$/, '!') as RoomID;
}
}
10 changes: 7 additions & 3 deletions packages/room/src/manager/v3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { toUnpaddedBase64 } from '@rocket.chat/federation-crypto';

import { PersistentEventBase } from './event-wrapper';
import type { REDACT_ALLOW_ALL_KEYS } from './event-wrapper';
import type { RoomVersion3To11 } from './type';
import type { EventID } from '../types/_common';
import type { RoomVersion3To12 } from './type';
import type { EventID, RoomID } from '../types/_common';
import type { PduType } from '../types/v3-11';

// v3 is where it changes first
export class PersistentEventV3<Type extends PduType = PduType> extends PersistentEventBase<RoomVersion3To11, Type> {
export class PersistentEventV3<Type extends PduType = PduType> extends PersistentEventBase<RoomVersion3To12, Type> {
private _eventId?: EventID;

get eventId(): EventID {
Expand All @@ -22,6 +22,10 @@ export class PersistentEventV3<Type extends PduType = PduType> extends Persisten
this._eventId = `\$${toUnpaddedBase64(referenceHash, { urlSafe: true })}` as EventID;
return this._eventId;
}

get roomId(): RoomID {
return this.rawEvent.room_id as RoomID;
}

getAllowedKeys(): string[] {
return [
Expand Down
23 changes: 20 additions & 3 deletions packages/room/src/types/v3-11.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as z from 'zod';

import type { PduForType } from './_common';
import type { PduForType, UserID } from './_common';
import { eventIdSchema, roomIdSchema, userIdSchema } from './_common';
import type { RoomVersion } from '../manager/type';

// Copied from: https://github.com/element-hq/synapse/blob/2277df2a1eb685f85040ef98fa21d41aa4cdd389/synapse/api/constants.py#L103-L141

Expand Down Expand Up @@ -116,7 +117,7 @@ export const PduCreateEventContentSchema = z.object({
})
.optional(),
'room_version': z
.enum(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'])
.enum(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'])
.describe(" The version of the room. Defaults to '1' if the key does not exist.")
.optional()
.default('1'),
Expand Down Expand Up @@ -623,6 +624,22 @@ export const PduTimelineSchema = z.discriminatedUnion('type', [

export const PduSchema = z.discriminatedUnion('type', [...PduTimelineSchema.options, ...PduStateEventSchema.options]);

export type Pdu = z.infer<typeof PduSchema>;
type PduV3To11 = z.infer<typeof PduSchema>;

// SPEC: https://spec.matrix.org/v1.19/rooms/v12/
// - `room_id` is derived from the m.room.create event's own event ID, so it is omitted from that event.
// - `content.additional_creators` may list extra user IDs who are also treated as room creators.
type PduCreateEventContentV12 = Omit<PduCreateEventContent, 'room_version'> & {
room_version: '12';
additional_creators?: UserID[];
};

type PduCreateEventV12 = Omit<Extract<PduV3To11, { type: 'm.room.create' }>, 'room_id' | 'content'> & {
content: PduCreateEventContentV12;
};

export type Pdu<V extends RoomVersion = Exclude<RoomVersion, '12'>> = V extends '12'
? Exclude<PduV3To11, { type: 'm.room.create' }> | PduCreateEventV12
: PduV3To11;

export type PduContent<T extends PduType = PduType> = PduForType<T>['content'];
Loading