Skip to content

Commit 53687fc

Browse files
committed
add allowedEncryptedRooms and allowedNonPrivateRooms support
1 parent 7ebe99b commit 53687fc

File tree

5 files changed

+65
-1
lines changed

5 files changed

+65
-1
lines changed

packages/federation-sdk/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export {
9090
type BaseEventType,
9191
} from './utils/event-schemas';
9292
export { errCodes } from './utils/response-codes';
93+
export { NotAllowedError } from './services/invite.service';
9394

9495
export { EventRepository } from './repositories/event.repository';
9596
export { RoomRepository } from './repositories/room.repository';

packages/federation-sdk/src/services/config.service.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ export interface AppConfig {
3131
downloadPerMinute: number;
3232
};
3333
};
34+
invite: {
35+
allowedEncryptedRooms: boolean;
36+
allowedNonPrivateRooms: boolean;
37+
};
3438
}
3539

3640
export const AppConfigSchema = z.object({
@@ -69,6 +73,10 @@ export const AppConfigSchema = z.object({
6973
.min(1, 'Download rate limit must be at least 1'),
7074
}),
7175
}),
76+
invite: z.object({
77+
allowedEncryptedRooms: z.boolean(),
78+
allowedNonPrivateRooms: z.boolean(),
79+
}),
7280
});
7381

7482
export class ConfigService {
@@ -113,6 +121,10 @@ export class ConfigService {
113121
return this.config.media;
114122
}
115123

124+
getInviteConfig(): AppConfig['invite'] {
125+
return this.config.invite;
126+
}
127+
116128
async getSigningKey() {
117129
// If config contains a signing key, use it
118130
if (!this.config.signingKey) {

packages/federation-sdk/src/services/invite.service.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ export type ProcessInviteEvent = {
2525
room_version: string;
2626
};
2727

28+
export class NotAllowedError extends Error {
29+
constructor(message: string) {
30+
super(message);
31+
this.name = 'NotAllowedError';
32+
}
33+
}
34+
2835
@singleton()
2936
export class InviteService {
3037
private readonly logger = createLogger('InviteService');
@@ -142,6 +149,42 @@ export class InviteService {
142149
};
143150
}
144151

152+
private async shouldProcessInvite(
153+
event: PduForType<'m.room.member'>,
154+
): Promise<void> {
155+
const isRoomNonPrivate = event.unsigned.invite_room_state.some(
156+
(
157+
stateEvent: PersistentEventBase<
158+
RoomVersion,
159+
'm.room.join_rules'
160+
>['event'],
161+
) =>
162+
stateEvent.type === 'm.room.join_rules' &&
163+
stateEvent.content.join_rule === 'public',
164+
);
165+
166+
const isRoomEncrypted = event.unsigned.invite_room_state.some(
167+
(
168+
stateEvent: PersistentEventBase<
169+
RoomVersion,
170+
'm.room.encryption'
171+
>['event'],
172+
) => stateEvent.type === 'm.room.encryption',
173+
);
174+
175+
const { allowedEncryptedRooms, allowedNonPrivateRooms } =
176+
this.configService.getInviteConfig();
177+
178+
const shouldRejectInvite =
179+
(!allowedEncryptedRooms && isRoomEncrypted) ||
180+
(!allowedNonPrivateRooms && isRoomNonPrivate);
181+
if (shouldRejectInvite) {
182+
throw new NotAllowedError(
183+
`Could not process invite due to room being ${isRoomEncrypted ? 'encrypted' : 'public'}`,
184+
);
185+
}
186+
}
187+
145188
async processInvite(
146189
event: PduForType<'m.room.member'>,
147190
roomId: RoomID,
@@ -150,6 +193,7 @@ export class InviteService {
150193
authenticatedServer: string,
151194
) {
152195
// SPEC: when a user invites another user on a different homeserver, a request to that homeserver to have the event signed and verified must be made
196+
await this.shouldProcessInvite(event);
153197

154198
const residentServer = roomId.split(':').pop();
155199
if (!residentServer) {

packages/federation-sdk/src/services/room.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
type EventID,
2222
PduForType,
2323
PduJoinRuleEventContent,
24+
PduMembershipEventContent,
2425
PduType,
2526
PersistentEventBase,
2627
PersistentEventFactory,
@@ -845,7 +846,7 @@ export class RoomService {
845846

846847
// trying to join room from another server
847848
const makeJoinResponse = await federationService.makeJoin(
848-
residentServer as string,
849+
residentServer,
849850
roomId,
850851
userId,
851852
roomVersion, // NOTE: check the comment in the called method

packages/homeserver/src/homeserver.module.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ export async function setup(options?: HomeserverSetupOptions) {
8888
),
8989
},
9090
},
91+
invite: {
92+
allowedEncryptedRooms:
93+
process.env.INVITE_ALLOWED_ENCRYPTED_ROOMS === 'true' || true,
94+
allowedNonPrivateRooms:
95+
process.env.INVITE_ALLOWED_NON_PRIVATE_ROOMS === 'true' || true,
96+
},
9197
});
9298

9399
const containerOptions: FederationContainerOptions = {

0 commit comments

Comments
 (0)