feat: Security

This commit is contained in:
2026-06-05 18:34:01 +02:00
parent ee293d7daf
commit 45675192a5
134 changed files with 4128 additions and 446 deletions

View File

@@ -14,6 +14,41 @@ vi.mock('../services/server-access.service', () => ({
authorizeWebSocketJoin: vi.fn(async () => ({ allowed: true as const }))
}));
let authenticatedUserId = 'user-1';
vi.mock('../services/session-auth.service', () => ({
consumeSessionToken: vi.fn(async (token: string) => {
if (token !== 'test-token') {
return null;
}
return {
token,
user: {
id: authenticatedUserId,
username: 'test-user',
displayName: 'Test User',
passwordHash: 'hash',
createdAt: Date.now()
},
issuedAt: Date.now(),
expiresAt: Date.now() + 60_000
};
})
}));
vi.mock('../services/plugin-support.service', async (importOriginal) => {
const actual = await importOriginal<typeof import('../services/plugin-support.service')>();
return {
...actual,
getPluginRequirementsSnapshot: vi.fn(async () => ({
requirements: [],
eventDefinitions: []
}))
};
});
/**
* Minimal mock WebSocket that records sent messages.
*/
@@ -38,6 +73,7 @@ function createConnectedUser(
const user: ConnectedUser = {
oderId,
ws,
authenticated: true,
serverIds: new Set(),
displayName: 'Test User',
lastPong: Date.now(),
@@ -168,7 +204,8 @@ describe('server websocket handler - status_update', () => {
getSentMessagesStore(user2).sentMessages.length = 0;
// Identify first (required for handler)
await handleWebSocketMessage('conn-1', { type: 'identify', oderId: 'user-1', displayName: 'User 1' });
authenticatedUserId = 'user-1';
await handleWebSocketMessage('conn-1', { type: 'identify', token: 'test-token', oderId: 'user-1', displayName: 'User 1' });
// user-2 joins server -> should receive server_users with user-1's status
getSentMessagesStore(user2).sentMessages.length = 0;
@@ -201,7 +238,8 @@ describe('server websocket handler - user_joined includes status', () => {
getRequiredConnectedUser('conn-1').status = 'busy';
// Identify user-1
await handleWebSocketMessage('conn-1', { type: 'identify', oderId: 'user-1', displayName: 'User 1' });
authenticatedUserId = 'user-1';
await handleWebSocketMessage('conn-1', { type: 'identify', token: 'test-token', oderId: 'user-1', displayName: 'User 1' });
getSentMessagesStore(user2).sentMessages.length = 0;
@@ -237,8 +275,10 @@ describe('server websocket handler - profile metadata in presence messages', ()
bob.serverIds.add('server-1');
getSentMessagesStore(bob).sentMessages.length = 0;
authenticatedUserId = 'user-1';
await handleWebSocketMessage('conn-1', {
type: 'identify',
token: 'test-token',
oderId: 'user-1',
displayName: 'Alice Updated',
description: 'Updated bio',
@@ -261,8 +301,10 @@ describe('server websocket handler - profile metadata in presence messages', ()
alice.serverIds.add('server-1');
bob.serverIds.add('server-1');
authenticatedUserId = 'user-1';
await handleWebSocketMessage('conn-1', {
type: 'identify',
token: 'test-token',
oderId: 'user-1',
displayName: 'Alice',
description: 'Alice bio',
@@ -291,8 +333,10 @@ describe('server websocket handler - profile metadata in presence messages', ()
alice.serverIds.add('server-1');
bob.serverIds.add('server-1');
authenticatedUserId = 'user-1';
await handleWebSocketMessage('conn-1', {
type: 'identify',
token: 'test-token',
oderId: 'user-1',
displayName: 'Alice',
homeSignalServerUrl: 'http://signal.example.com:3001/'