Skip to content

Commit 9493d31

Browse files
committed
x
1 parent 991f866 commit 9493d31

File tree

7 files changed

+7
-61
lines changed

7 files changed

+7
-61
lines changed

.husky/pre-commit

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bun lint
2+
bunx tsc
3+
bun test

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
},
2727
"husky": {
2828
"hooks": {
29-
"pre-commit": "echo 'pre-commit'"
29+
"pre-commit": "bun test"
3030
}
3131
},
3232
"scripts": {

packages/homeserver/src/routes/federation/README.md

Lines changed: 0 additions & 25 deletions
This file was deleted.
Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
/**
2-
* Extracts the server name from a Matrix ID (e.g., @user:example.com -> example.com)
3-
*
4-
* @param matrixId The Matrix ID to extract the server name from
5-
* @returns The server name part of the Matrix ID
6-
*/
71
export const extractOrigin = (matrixId: string): string => {
82
return matrixId.split(':').pop() as string;
93
};

packages/homeserver/src/validation/EventValidationPipeline.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ export function createEventValidationPipeline() {
2424

2525
const validateAuthEvents = new SequentialPipeline<AuthorizedEvent>()
2626
.add(fetchAuthEvents)
27-
// .add(validateAuthChain)
28-
// .add(validateRoomRules);
27+
.add(validateAuthChain)
28+
.add(validateRoomRules);
2929

3030
return new SequentialPipeline<Event>()
3131
.add(canonicalizeEvent)

packages/homeserver/src/validation/validators/AuthChainValidator.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,13 @@ export const validateAuthChain = createValidator<AuthorizedEvent>(async (event,
2525
// Special case for m.room.create which doesn't need auth events
2626
if (event.event.type === 'm.room.create' && event.event.state_key === '') {
2727
logger.debug(`Create event ${eventId} doesn't need auth events`);
28-
// Continue to type-specific validation for create events
2928
} else {
3029
logger.warn(`Event ${eventId} missing auth_event_objects`);
3130
return failure('M_MISSING_AUTH_EVENTS', 'Event missing auth event objects');
3231
}
3332
}
3433

3534
const hasIncompleteChain = authorizedEvent.incomplete_chain === true;
36-
3735
logger.debug(`Validating auth chain for event ${eventId} with ${authorizedEvent.auth_event_objects?.length || 0} auth events${hasIncompleteChain ? ' (incomplete chain)' : ''}`);
3836

3937
const authEvents = new Map();

packages/homeserver/src/validation/validators/RoomRulesValidator.ts

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createValidator, success, failure } from '../Validator';
1+
import { createValidator, success, failure, ValidationResult } from '../Validator';
22
import { AuthorizedEvent } from './index';
33
import { Logger } from '../../routes/federation/logger';
44

@@ -16,14 +16,6 @@ interface PowerLevels {
1616
invite?: number;
1717
}
1818

19-
/**
20-
* Validates room authorization rules
21-
*
22-
* Matrix rooms have specific authorization rules that determine
23-
* who can send what types of events, based on power levels and
24-
* room state. This validator enforces these rules according to
25-
* the Matrix specification.
26-
*/
2719
export const validateRoomRules = createValidator<AuthorizedEvent>(async (event, _, eventId) => {
2820
try {
2921
logger.debug(`Validating room rules for event ${eventId}`);
@@ -35,11 +27,9 @@ export const validateRoomRules = createValidator<AuthorizedEvent>(async (event,
3527
return failure('M_MISSING_AUTH_EVENTS', 'Event missing auth event objects');
3628
}
3729

38-
// Create a map of auth events for easy access
3930
const authEvents = new Map();
4031
authorizedEvent.auth_event_objects.forEach(authEvent => {
4132
if (authEvent.event && authEvent.event.type) {
42-
// For state events, use type + state_key as the key
4333
if (authEvent.event.state_key !== undefined) {
4434
authEvents.set(`${authEvent.event.type}|${authEvent.event.state_key}`, authEvent.event);
4535
} else {
@@ -48,7 +38,6 @@ export const validateRoomRules = createValidator<AuthorizedEvent>(async (event,
4838
}
4939
});
5040

51-
// Get required auth events for the rules check
5241
const createEvent = authEvents.get('m.room.create|');
5342
if (!createEvent) {
5443
logger.error(`Missing required create event for rules validation`);
@@ -70,7 +59,6 @@ export const validateRoomRules = createValidator<AuthorizedEvent>(async (event,
7059
const eventType = event.event.type;
7160
const stateKey = event.event.state_key;
7261

73-
// Check if the sender's event is allowed based on auth rules
7462
// 1. Check room creator for create events
7563
if (eventType === 'm.room.create') {
7664
// Create events must have the sender match the creator
@@ -82,15 +70,11 @@ export const validateRoomRules = createValidator<AuthorizedEvent>(async (event,
8270

8371
// 2. For member events, validate based on membership type
8472
else if (eventType === 'm.room.member') {
85-
// For self-membership changes
8673
if (stateKey === sender) {
87-
// For joins, check join rules
8874
if (event.event.content?.membership === 'join') {
8975
const joinRulesEvent = authEvents.get('m.room.join_rules|');
9076

91-
// Only enforce join rules if they are specified
9277
if (joinRulesEvent && joinRulesEvent.content?.join_rule === 'invite') {
93-
// For invite-only rooms, check if user was invited
9478
const memberEvent = authEvents.get(`m.room.member|${sender}`);
9579
const existingMembership = memberEvent?.content?.membership;
9680

@@ -103,9 +87,7 @@ export const validateRoomRules = createValidator<AuthorizedEvent>(async (event,
10387
}
10488
}
10589
}
106-
// For changing others' membership
10790
else {
108-
// For invites, check that the inviter has permission
10991
if (event.event.content?.membership === 'invite') {
11092
const userPowerLevel = getUserPowerLevel(sender, powerLevels);
11193
if (userPowerLevel < (powerLevels.invite ?? 50)) {
@@ -114,7 +96,6 @@ export const validateRoomRules = createValidator<AuthorizedEvent>(async (event,
11496
}
11597
}
11698

117-
// For kick/ban, check appropriate permissions
11899
else if (['ban', 'kick'].includes(event.event.content?.membership || '')) {
119100
const targetUser = stateKey;
120101
const action = event.event.content?.membership;
@@ -141,13 +122,11 @@ export const validateRoomRules = createValidator<AuthorizedEvent>(async (event,
141122
else if (eventType === 'm.room.power_levels') {
142123
const userPowerLevel = getUserPowerLevel(sender, powerLevels);
143124

144-
// Check sender has required power level to change power levels
145125
if (userPowerLevel < (powerLevels.events?.['m.room.power_levels'] ?? powerLevels.state_default ?? 50)) {
146126
logger.error(`User ${sender} doesn't have permission to change power levels (power level: ${userPowerLevel})`);
147127
return failure('M_FORBIDDEN', 'User doesn\'t have permission to change power levels');
148128
}
149129

150-
// Prevent privilege escalation
151130
const newPowerLevels = event.event.content as PowerLevels;
152131
if (newPowerLevels && newPowerLevels.users) {
153132
for (const [user, level] of Object.entries(newPowerLevels.users)) {
@@ -173,7 +152,6 @@ export const validateRoomRules = createValidator<AuthorizedEvent>(async (event,
173152

174153
// 5. For normal message events, check event power levels
175154
else {
176-
// First check that the sender is actually in the room
177155
const memberEvent = authEvents.get(`m.room.member|${sender}`);
178156
if (!memberEvent || memberEvent.content?.membership !== 'join') {
179157
logger.error(`User ${sender} tried to send message without being in the room`);
@@ -198,8 +176,6 @@ export const validateRoomRules = createValidator<AuthorizedEvent>(async (event,
198176
}
199177
});
200178

201-
// Helper functions for power level checks
202-
203179
function getUserPowerLevel(userId: string, powerLevels: PowerLevels): number {
204180
if (powerLevels.users && powerLevels.users[userId] !== undefined) {
205181
return powerLevels.users[userId];

0 commit comments

Comments
 (0)