Skip to content
Merged
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: 5 additions & 18 deletions packages/federation-sdk/src/services/state.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export class StateService {
throw new Error('Create event not found for room version');
}

return createEvent.event.content?.room_version;
return createEvent.event.content.room_version;
}

private logState(label: string, state: State) {
Expand Down Expand Up @@ -438,7 +438,7 @@ export class StateService {
}

private async addPrevEvents(event: PersistentEventBase) {
const roomVersion = await this.getRoomVersion(event.roomId);
const roomVersion = event.version;
if (!roomVersion) {
throw new Error('Room version not found while filling prev events');
}
Expand Down Expand Up @@ -478,13 +478,7 @@ export class StateService {
event: PersistentEventBase,
state: State,
): Promise<void> {
const roomVersion = event.isCreateEvent()
? event.getContent().room_version
: await this.getRoomVersion(event.roomId);

if (!roomVersion) {
throw new Error('Room version not found');
}
const roomVersion = event.version;

// always check for conflicts at the prev_event state

Expand Down Expand Up @@ -594,9 +588,7 @@ export class StateService {
return;
}

const roomVersion = event.isCreateEvent()
? event.getContent().room_version
: await this.getRoomVersion(event.roomId);
const roomVersion = event.version;

if (!roomVersion) {
throw new Error('Room version not found');
Expand Down Expand Up @@ -748,12 +740,7 @@ export class StateService {
throw new Error('State events are not persisted with this method');
}

const roomVersion = await this.getRoomVersion(event.roomId);
if (!roomVersion) {
throw new Error(
'Room version not found when trying to persist a timeline event',
);
}
const roomVersion = event.version;

const { state: room, stateId } = await this.getFullRoomStateAndStateId(
event.roomId,
Expand Down
14 changes: 6 additions & 8 deletions packages/room/src/authorizartion-rules/rules.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import assert from 'node:assert';
import {
type PduCreateEventContent,
type PduMembershipEventContent,
type PduPowerLevelsEventContent,
type PduType,
} from '../types/v3-11';
import { type PduType } from '../types/v3-11';

import type { PersistentEventBase } from '../manager/event-wrapper';
import { PowerLevelEvent } from '../manager/power-level-event-wrapper';
import { RoomVersion } from '../manager/type';
import {
type EventStore,
getStateByMapKey,
Expand Down Expand Up @@ -173,7 +169,9 @@ async function isMembershipChangeAllowed(

const content = membershipEventToCheck.getContent();

const previousEvents = await membershipEventToCheck.getPreviousEvents(store);
const previousEvents = await store.getEvents(
membershipEventToCheck.getPreviousEventIds(),
);

switch (content.membership) {
case 'join': {
Expand Down Expand Up @@ -353,7 +351,7 @@ async function isMembershipChangeAllowed(

export function validatePowerLevelEvent(
powerLevelEvent: PowerLevelEvent,
roomCreateEvent: PersistentEventBase,
roomCreateEvent: PersistentEventBase<RoomVersion, 'm.room.create'>,
authEventMap: Map<StateMapKey, PersistentEventBase>,
) {
// If the users property in content is not an object with keys that are valid user IDs with values that are integers (or a string that is an integer), reject.
Expand Down
50 changes: 29 additions & 21 deletions packages/room/src/manager/event-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const REDACT_ALLOW_ALL_KEYS: unique symbol = Symbol.for('all');

// convinient wrapper to manage schema differences when working with same algorithms across different versions
export abstract class PersistentEventBase<
T extends RoomVersion = '11',
Version extends RoomVersion = RoomVersion,
Type extends PduType = PduType,
> {
private _rejectedReason?: string;
Expand All @@ -50,7 +50,10 @@ export abstract class PersistentEventBase<

protected rawEvent: PduWithHashesAndSignaturesOptional;

constructor(event: PduWithHashesAndSignaturesOptional) {
constructor(
event: PduWithHashesAndSignaturesOptional,
public readonly version: Version,
) {
this.rawEvent = JSON.parse(JSON.stringify(event));
if (this.rawEvent.signatures) {
this.signatures = this.rawEvent.signatures;
Expand Down Expand Up @@ -141,14 +144,13 @@ export abstract class PersistentEventBase<
throw new Error('Event is not a power level event');
}

// room version dependent
abstract getAuthorizationEvents(
store: EventStore,
): Promise<PersistentEventBase<T>[]>;
getAuthEventIds() {
return this.rawEvent.auth_events;
}

abstract getPreviousEvents(
store: EventStore,
): Promise<PersistentEventBase<T>[]>;
getPreviousEventIds() {
return this.rawEvent.prev_events;
}

isState() {
// spec wise this is the right way to check if an event is a state event
Expand All @@ -162,49 +164,55 @@ export abstract class PersistentEventBase<
return !this.isState();
}

isTopicEvent(): this is PersistentEventBase<T, 'm.room.topic'> {
isTopicEvent(): this is PersistentEventBase<Version, 'm.room.topic'> {
return this.isState() && this.type === 'm.room.topic';
}

isPowerLevelEvent(): this is PersistentEventBase<T, 'm.room.power_levels'> {
isPowerLevelEvent(): this is PersistentEventBase<
Version,
'm.room.power_levels'
> {
return this.isState() && this.type === 'm.room.power_levels';
}

isNameEvent(): this is PersistentEventBase<T, 'm.room.name'> {
isNameEvent(): this is PersistentEventBase<Version, 'm.room.name'> {
return this.isState() && this.type === 'm.room.name';
}

isJoinRuleEvent(): this is PersistentEventBase<T, 'm.room.join_rules'> {
isJoinRuleEvent(): this is PersistentEventBase<Version, 'm.room.join_rules'> {
return this.isState() && this.type === 'm.room.join_rules';
}

isMembershipEvent(): this is PersistentEventBase<T, 'm.room.member'> {
isMembershipEvent(): this is PersistentEventBase<Version, 'm.room.member'> {
return this.isState() && this.type === 'm.room.member';
}

isCreateEvent(): this is PersistentEventBase<T, 'm.room.create'> {
isCreateEvent(): this is PersistentEventBase<Version, 'm.room.create'> {
return this.isState() && this.type === 'm.room.create';
}

isServerAclEvent(): this is PersistentEventBase<T, 'm.room.server_acl'> {
isServerAclEvent(): this is PersistentEventBase<
Version,
'm.room.server_acl'
> {
return this.isState() && this.type === 'm.room.server_acl';
}

isHistoryVisibilityEvent(): this is PersistentEventBase<
T,
Version,
'm.room.history_visibility'
> {
return this.isState() && this.type === 'm.room.history_visibility';
}

isCanonicalAliasEvent(): this is PersistentEventBase<
T,
Version,
'm.room.canonical_alias'
> {
return this.isState() && this.type === 'm.room.canonical_alias';
}

isAliasEvent(): this is PersistentEventBase<T, 'm.room.aliases'> {
isAliasEvent(): this is PersistentEventBase<Version, 'm.room.aliases'> {
return this.isState() && this.type === 'm.room.aliases';
}

Expand Down Expand Up @@ -412,15 +420,15 @@ export abstract class PersistentEventBase<
return this._rejectedReason;
}

addPrevEvents(events: PersistentEventBase<T>[]) {
addPrevEvents(events: PersistentEventBase<Version>[]) {
this.rawEvent.prev_events.push(...events.map((e) => e.eventId));
if (this.rawEvent.depth <= events[events.length - 1].depth) {
this.rawEvent.depth = events[events.length - 1].depth + 1;
}
return this;
}

authedBy(event: PersistentEventBase<T>) {
authedBy(event: PersistentEventBase<Version>) {
this.rawEvent.auth_events.push(event.eventId);
return this;
}
Expand Down
36 changes: 7 additions & 29 deletions packages/room/src/manager/factory.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import {
Pdu,
type PduCreateEventContent,
type PduJoinRuleEventContent,
type PduMembershipEventContent,
PduPowerLevelsEventContent,
PduType,
} from '../types/v3-11';
import { Pdu, type PduCreateEventContent, PduType } from '../types/v3-11';

import { PersistentEventV3 } from './v3';

Expand Down Expand Up @@ -59,7 +52,7 @@ export class PersistentEventFactory {

static createFromRawEvent<Type extends PduType>(
event: PduWithHashesAndSignaturesOptional,
roomVersion: RoomVersion,
roomVersion: string,
): PersistentEventBase<RoomVersion, Type> {
if (!PersistentEventFactory.isSupportedRoomVersion(roomVersion)) {
throw new Error(`Room version ${roomVersion} is not supported`);
Expand All @@ -69,32 +62,17 @@ export class PersistentEventFactory {
case '3':
case '4':
case '5':
return new PersistentEventV3(event) as PersistentEventBase<
RoomVersion,
Type
>;
return new PersistentEventV3(event, roomVersion);
case '6':
case '7':
return new PersistentEventV6(event) as PersistentEventBase<
RoomVersion,
Type
>;
return new PersistentEventV6(event, roomVersion);
case '8':
return new PersistentEventV8(event) as PersistentEventBase<
RoomVersion,
Type
>;
return new PersistentEventV8(event, roomVersion);
case '9':
case '10':
return new PersistentEventV9(event) as PersistentEventBase<
RoomVersion,
Type
>;
return new PersistentEventV9(event, roomVersion);
case '11':
return new PersistentEventV11(event) as PersistentEventBase<
RoomVersion,
Type
>;
return new PersistentEventV11(event, roomVersion);
default:
throw new Error(`Unknown room version: ${roomVersion}`);
}
Expand Down
5 changes: 4 additions & 1 deletion packages/room/src/manager/power-level-event-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ class PowerLevelEvent<
return this._content.redact ?? 50;
}

getPowerLevelForUser(userId: string, createEvent?: PersistentEventBase) {
getPowerLevelForUser(
userId: string,
createEvent?: PersistentEventBase<RoomVersion, 'm.room.create'>,
) {
if (!this._content) {
if (createEvent?.sender === userId) {
return 100;
Expand Down
2 changes: 1 addition & 1 deletion packages/room/src/manager/room-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,6 @@ export class RoomState {
throw new Error('Room create event not found');
}

return createEvent.getContent().room_version;
return createEvent.getContent().room_version as RoomVersion;
}
}
6 changes: 4 additions & 2 deletions packages/room/src/manager/v11.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {} from '../types/v3-11';
import { type PduType } from '../types/v3-11';
import { REDACT_ALLOW_ALL_KEYS } from './event-wrapper';
import { PersistentEventV9 } from './v9';

export class PersistentEventV11 extends PersistentEventV9 {
export class PersistentEventV11<
Type extends PduType = PduType,
> extends PersistentEventV9<Type> {
getAllowedKeys(): string[] {
return [
'event_id',
Expand Down
13 changes: 4 additions & 9 deletions packages/room/src/manager/v3.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { toUnpaddedBase64 } from '@rocket.chat/federation-crypto';
import type { EventID } from '../types/_common';
import {} from '../types/v3-11';
import { PduType } from '../types/v3-11';
import {
type EventStore,
PersistentEventBase,
Expand All @@ -9,16 +9,11 @@ import {
import type { RoomVersion3To11 } from './type';

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

async getAuthorizationEvents(store: EventStore) {
return store.getEvents(this.rawEvent.auth_events);
}

async getPreviousEvents(store: EventStore) {
return store.getEvents(this.rawEvent.prev_events);
}
get eventId(): EventID {
if (this._eventId) {
return this._eventId;
Expand Down
6 changes: 4 additions & 2 deletions packages/room/src/manager/v6.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {} from '../types/v3-11';
import { PduType } from '../types/v3-11';
import { PersistentEventV3 } from './v3';

export class PersistentEventV6 extends PersistentEventV3 {
export class PersistentEventV6<
Type extends PduType = PduType,
> extends PersistentEventV3<Type> {
getAllowedContentKeys() {
const resp = super.getAllowedContentKeys();

Expand Down
6 changes: 4 additions & 2 deletions packages/room/src/manager/v8.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {} from '../types/v3-11';
import { PduType } from '../types/v3-11';
import { PersistentEventV6 } from './v6';

export class PersistentEventV8 extends PersistentEventV6 {
export class PersistentEventV8<
Type extends PduType = PduType,
> extends PersistentEventV6<Type> {
getAllowedContentKeys() {
const resp = super.getAllowedContentKeys();

Expand Down
Loading