Skip to content
Open
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
9 changes: 1 addition & 8 deletions packages/federation-sdk/src/services/invite.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,13 @@ export class InviteService {

// SPEC: Invites a remote user to a room. Once the event has been signed by both the inviting homeserver and the invited homeserver, it can be sent to all of the servers in the room by the inviting homeserver.

const invitedServer = extractDomainFromId(inviteEvent.stateKey ?? '');
if (!invitedServer) {
throw new Error(
`invalid state_key ${inviteEvent.stateKey}, no server_name part`,
);
}

await this.federationValidationService.validateOutboundInvite(
userId,
roomId,
);

// if user invited belongs to our server
if (invitedServer === this.configService.serverName) {
if (inviteEvent.stateKeyDomain === this.configService.serverName) {
await stateService.handlePdu(inviteEvent);

// let all servers know of this state change
Expand Down
7 changes: 3 additions & 4 deletions packages/federation-sdk/src/services/state.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ export class StateService {
return instance;
}

private async addAuthEvents(event: PersistentEventBase) {
private async addAuthEvents(event: PersistentEventBase<any, any>) {
const state = await this.getLatestRoomState(event.roomId);

const eventsNeeded = event.getAuthEventStateKeys();
Expand All @@ -307,7 +307,7 @@ export class StateService {
}
}

async addPrevEvents(event: PersistentEventBase) {
async addPrevEvents(event: PersistentEventBase<any, any>) {
const roomVersion = await this.getRoomVersion(event.roomId);
if (!roomVersion) {
throw new Error('Room version not found while filling prev events');
Expand All @@ -330,7 +330,7 @@ export class StateService {
event.addPrevEvents(events);
}

public async signEvent<T extends PersistentEventBase>(event: T) {
public async signEvent<T extends PersistentEventBase<any, any>>(event: T) {
if (process.env.NODE_ENV === 'test') return event;

const signingKey = await this.configService.getSigningKey();
Expand Down Expand Up @@ -511,7 +511,6 @@ export class StateService {
previousStateId,
);
await this.addToRoomGraph(event, previousStateId);

await this.eventService.notify(event);
}

Expand Down
4 changes: 2 additions & 2 deletions packages/room/src/authorizartion-rules/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ class StateResolverAuthorizationError extends Error {
reason,
rejectedBy,
}: {
rejectedEvent: PersistentEventBase;
rejectedEvent: PersistentEventBase<any, any>;
reason: string;
rejectedBy?: PersistentEventBase;
rejectedBy?: PersistentEventBase<any, any>;
},
) {
// build the message
Expand Down
10 changes: 5 additions & 5 deletions packages/room/src/authorizartion-rules/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,11 @@ async function isMembershipChangeAllowed(
if (previousEvents.length === 1) {
const [event] = previousEvents;

if (
event.isCreateEvent() &&
event.getContent().creator === membershipEventToCheck.stateKey
) {
return;
if (event.isCreateEvent()) {
const content = event.getContent() as { creator?: string };
if (content.creator === membershipEventToCheck.stateKey) {
return;
}
}
}

Expand Down
37 changes: 31 additions & 6 deletions packages/room/src/manager/event-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,22 @@ export type PduWithHashesAndSignaturesOptional<T extends Pdu = Pdu> = Prettify<
MakeOptional<T, 'hashes' | 'signatures'>
>;

export type PduTypeWithoutStateKey = {
[K in PduType]: PduForType<K> extends { state_key: unknown } ? never : K;
}[PduType];

export const REDACT_ALLOW_ALL_KEYS: unique symbol = Symbol.for('all');

export interface State extends Map<StateMapKey, PersistentEventBase> {
export interface State
extends Omit<Map<StateMapKey, PersistentEventBase>, 'get'> {
get(key: StateMapKey): PersistentEventBase | undefined;
get<T extends StateMapKey>(
key: T,
): T extends `${infer I}:${string}`
? I extends PduType
? PersistentEventBase<RoomVersion, I> | undefined
: never
: never;
: PersistentEventBase | undefined
: PersistentEventBase | undefined;
}

// convinient wrapper to manage schema differences when working with same algorithms across different versions
Expand All @@ -67,7 +73,7 @@ export abstract class PersistentEventBase<

private signatures: Signature = {};

protected rawEvent: PduWithHashesAndSignaturesOptional;
protected rawEvent: PduWithHashesAndSignaturesOptional<PduForType<Type>>;

private authEventsIds: Set<EventID> = new Set();
private prevEventsIds: Set<EventID> = new Set();
Expand Down Expand Up @@ -134,8 +140,27 @@ export abstract class PersistentEventBase<
return residentServer;
}

get stateKey() {
return 'state_key' in this.rawEvent ? this.rawEvent.state_key : undefined;
get stateKey(): Type extends PduTypeWithoutStateKey
? undefined
: PduForType<Type> extends { state_key: string }
? PduForType<Type>['state_key']
: undefined {
return (
'state_key' in this.rawEvent ? this.rawEvent.state_key : undefined
) as Type extends PduTypeWithoutStateKey
? undefined
: PduForType<Type> extends { state_key: string }
? PduForType<Type>['state_key']
: undefined;
}

get stateKeyDomain(): Type extends PduTypeWithoutStateKey ? never : string {
if (this.stateKey === undefined) {
throw new Error('stateKey is undefined');
}
return extractDomainFromId(
this.stateKey,
) as Type extends PduTypeWithoutStateKey ? never : string;
}

get originServerTs() {
Expand Down