Skip to content

Commit d127ab3

Browse files
committed
Fix server crashed, regular cleanups
Signed-off-by: Hoang Pham <[email protected]>
1 parent ac790eb commit d127ab3

21 files changed

+737
-271
lines changed

tests/integration/configMock.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
const defaultMockValues = {
2+
IS_TEST_ENV: true,
3+
BYPASS_SSL_VALIDATION: false,
4+
USE_TLS: false,
5+
TLS_KEY_PATH: null,
6+
TLS_CERT_PATH: null,
7+
STORAGE_STRATEGY: 'lru',
8+
REDIS_URL: null,
9+
FORCE_CLOSE_TIMEOUT: 60 * 1000,
10+
METRICS_TOKEN: null,
11+
JWT_SECRET_KEY: null,
12+
BACKUP_DIR: './backup',
13+
ROOM_CLEANUP_INTERVAL: 1000,
14+
LOCK_TIMEOUT: 1000,
15+
LOCK_RETRY_INTERVAL: 1000,
16+
MAX_BACKUPS_PER_ROOM: 10,
17+
ROOM_MAX_AGE: 1000,
18+
MAX_ROOMS_IN_STORAGE: 1000,
19+
}
20+
21+
export function createConfigMock(customValues = {}) {
22+
const mockValues = { ...defaultMockValues, ...customValues }
23+
24+
const computedProperties = {
25+
get JWT_SECRET_KEY() {
26+
return mockValues.JWT_SECRET_KEY
27+
},
28+
get NEXTCLOUD_WEBSOCKET_URL() {
29+
return mockValues.NEXTCLOUD_WEBSOCKET_URL
30+
},
31+
get NEXTCLOUD_URL() {
32+
return mockValues.NEXTCLOUD_URL
33+
},
34+
}
35+
36+
const mockConfig = {
37+
...mockValues,
38+
...computedProperties,
39+
}
40+
41+
return mockConfig
42+
}

tests/integration/metrics.spec.mjs

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,37 @@
11
import { beforeAll, afterAll, describe, it, expect, vi } from 'vitest'
22
import axios from 'axios'
3-
import ServerManager from '../../websocket_server/ServerManager.js'
3+
import { createConfigMock } from './configMock.js'
4+
import ServerManagerModule from '../../websocket_server/ServerManager.js'
5+
import ConfigModule from '../../websocket_server/Config.js'
46

5-
const SERVER_URL = 'http://localhost:3008'
6-
const SECRET = 'secret'
7+
vi.mock('../../websocket_server/Config.js', () => ({
8+
default: createConfigMock({
9+
NEXTCLOUD_URL: 'http://localhost:3008',
10+
NEXTCLOUD_WEBSOCKET_URL: 'http://localhost:3008',
11+
PORT: '3008',
12+
METRICS_TOKEN: 'secret',
13+
}),
14+
}))
715

8-
vi.stubEnv('METRICS_TOKEN', SECRET)
16+
const Config = ConfigModule
17+
const ServerManager = ServerManagerModule
918

1019
describe('Metrics endpoint', () => {
1120
let serverManager
1221

1322
beforeAll(async () => {
14-
serverManager = new ServerManager({
15-
port: 3008,
16-
storageStrategy: 'lru',
17-
})
18-
19-
serverManager.start()
23+
serverManager = new ServerManager()
24+
await serverManager.start()
2025
})
2126

2227
afterAll(async () => {
23-
await serverManager.server.close()
28+
await serverManager.gracefulShutdown()
2429
})
2530

2631
it('should work with bearer auth', async () => {
27-
const response = await axios.get(`${SERVER_URL}/metrics`, {
32+
const response = await axios.get(`${Config.NEXTCLOUD_URL}/metrics`, {
2833
headers: {
29-
Authorization: `Bearer ${SECRET}`,
34+
Authorization: `Bearer ${Config.METRICS_TOKEN}`,
3035
},
3136
})
3237
expect(response.status).toBe(200)
@@ -39,14 +44,14 @@ describe('Metrics endpoint', () => {
3944
})
4045

4146
it('should work with token param', async () => {
42-
const response = await axios.get(`${SERVER_URL}/metrics?token=${SECRET}`)
47+
const response = await axios.get(`${Config.NEXTCLOUD_URL}/metrics?token=${Config.METRICS_TOKEN}`)
4348
expect(response.status).toBe(200)
4449
expect(response.data).toContain('whiteboard_room_stats{stat="activeRooms"}')
4550
})
4651

4752
it('Not return on invalid auth', async () => {
4853
try {
49-
await axios.get(`${SERVER_URL}/metrics`, {
54+
await axios.get(`${Config.NEXTCLOUD_URL}/metrics`, {
5055
headers: {
5156
Authorization: 'Bearer wrongtoken',
5257
},

tests/integration/socket.spec.mjs

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
import { beforeAll, afterAll, describe, it, expect, vi } from 'vitest'
2-
import ServerManager from '../../websocket_server/ServerManager.js'
3-
import io from 'socket.io-client'
2+
import { io } from 'socket.io-client'
43
import jwt from 'jsonwebtoken'
5-
import Utils from '../../websocket_server/Utils.js'
4+
import { createConfigMock } from './configMock.js'
5+
import ServerManagerModule from '../../websocket_server/ServerManager.js'
6+
import UtilsModule from '../../websocket_server/Utils.js'
7+
import ConfigModule from '../../websocket_server/Config.js'
68

7-
const SERVER_URL = 'http://localhost:3009'
8-
const SECRET = 'secret'
9+
vi.mock('../../websocket_server/Config.js', () => ({
10+
default: createConfigMock({
11+
NEXTCLOUD_URL: 'http://localhost:3009',
12+
NEXTCLOUD_WEBSOCKET_URL: 'http://localhost:3009',
13+
PORT: '3009',
14+
JWT_SECRET_KEY: 'secret',
15+
}),
16+
}))
917

10-
vi.stubEnv('JWT_SECRET_KEY', SECRET)
18+
const Config = ConfigModule
19+
const ServerManager = ServerManagerModule
20+
const Utils = UtilsModule
1121

1222
function waitFor(socket, event) {
1323
return new Promise((resolve) => {
@@ -19,16 +29,12 @@ describe('Socket handling', () => {
1929
let serverManager, socket
2030

2131
beforeAll(async () => {
22-
serverManager = new ServerManager({
23-
port: 3009,
24-
storageStrategy: 'lru',
25-
})
26-
27-
serverManager.start()
32+
serverManager = new ServerManager()
33+
await serverManager.start()
2834

29-
socket = io(SERVER_URL, {
35+
socket = io(Config.NEXTCLOUD_WEBSOCKET_URL, {
3036
auth: {
31-
token: jwt.sign({ roomID: 123, user: { name: 'Admin' } }, SECRET),
37+
token: jwt.sign({ roomID: 123, user: { name: 'Admin' } }, Config.JWT_SECRET_KEY),
3238
},
3339
})
3440

@@ -39,11 +45,11 @@ describe('Socket handling', () => {
3945

4046
afterAll(async () => {
4147
await socket.disconnect()
42-
await serverManager.server.close()
48+
await serverManager.gracefulShutdown()
4349
})
4450

4551
it('socket invalid jwt', async () => {
46-
const socket = io(SERVER_URL, {
52+
const socket = io(Config.NEXTCLOUD_WEBSOCKET_URL, {
4753
auth: {
4854
token: jwt.sign({ roomID: 123, user: { name: 'Admin' } }, 'wrongsecret'),
4955
},
@@ -56,9 +62,9 @@ describe('Socket handling', () => {
5662
})
5763

5864
it('socket valid jwt', async () => {
59-
const socket = io(SERVER_URL, {
65+
const socket = io(Config.NEXTCLOUD_WEBSOCKET_URL, {
6066
auth: {
61-
token: jwt.sign({ roomID: 123, user: { name: 'Admin' } }, SECRET),
67+
token: jwt.sign({ roomID: 123, user: { name: 'Admin' } }, Config.JWT_SECRET_KEY),
6268
},
6369
})
6470
return new Promise((resolve) => {
@@ -78,9 +84,9 @@ describe('Socket handling', () => {
7884
})
7985

8086
it('read only socket', async () => {
81-
const socket = io(SERVER_URL, {
87+
const socket = io(Config.NEXTCLOUD_WEBSOCKET_URL, {
8288
auth: {
83-
token: jwt.sign({ roomID: 123, user: { name: 'Admin' }, isFileReadOnly: true }, SECRET),
89+
token: jwt.sign({ roomID: 123, user: { name: 'Admin' }, isFileReadOnly: true }, Config.JWT_SECRET_KEY),
8490
},
8591
})
8692
return new Promise((resolve) => {

websocket_server/ApiService.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,12 @@
77

88
import fetch from 'node-fetch'
99
import https from 'https'
10-
import dotenv from 'dotenv'
11-
import Utils from './Utils.js'
12-
dotenv.config()
10+
import Config from './Config.js'
1311

1412
export default class ApiService {
1513

1614
constructor(tokenGenerator) {
17-
this.NEXTCLOUD_URL = process.env.NEXTCLOUD_URL
18-
this.IS_DEV = Utils.parseBooleanFromEnv(process.env.IS_DEV)
19-
this.agent = this.IS_DEV ? new https.Agent({ rejectUnauthorized: false }) : null
15+
this.agent = (Config.USE_TLS && Config.BYPASS_SSL_VALIDATION) ? new https.Agent({ rejectUnauthorized: false }) : null
2016
this.tokenGenerator = tokenGenerator
2117
}
2218

@@ -50,15 +46,15 @@ export default class ApiService {
5046
}
5147

5248
async getRoomDataFromServer(roomID, jwtToken) {
53-
const url = `${this.NEXTCLOUD_URL}/index.php/apps/whiteboard/${roomID}`
49+
const url = `${Config.NEXTCLOUD_URL}/index.php/apps/whiteboard/${roomID}`
5450
const options = this.fetchOptions('GET', jwtToken)
5551
return this.fetchData(url, options)
5652
}
5753

5854
async saveRoomDataToServer(roomID, roomData, lastEditedUser, files) {
5955
console.log(`[${roomID}] Saving room data to server: ${roomData.length} elements, ${Object.keys(files).length} files`)
6056

61-
const url = `${this.NEXTCLOUD_URL}/index.php/apps/whiteboard/${roomID}`
57+
const url = `${Config.NEXTCLOUD_URL}/index.php/apps/whiteboard/${roomID}`
6258

6359
const body = {
6460
data: {

websocket_server/AppManager.js

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,14 @@
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
55

6-
import dotenv from 'dotenv'
76
import express from 'express'
8-
import PrometheusDataManager from './PrometheusDataManager.js'
9-
10-
dotenv.config()
7+
import Config from './Config.js'
118

129
export default class AppManager {
1310

14-
constructor(storageManager) {
11+
constructor(metricsManager) {
1512
this.app = express()
16-
this.storageManager = storageManager
17-
this.metricsManager = new PrometheusDataManager(storageManager)
18-
this.METRICS_TOKEN = process.env.METRICS_TOKEN
13+
this.metricsManager = metricsManager
1914
this.setupRoutes()
2015
}
2116

@@ -30,7 +25,7 @@ export default class AppManager {
3025

3126
async metricsHandler(req, res) {
3227
const token = req.headers.authorization?.split(' ')[1] || req.query.token
33-
if (!this.METRICS_TOKEN || token !== this.METRICS_TOKEN) {
28+
if (!Config.METRICS_TOKEN || token !== Config.METRICS_TOKEN) {
3429
return res.status(403).send('Unauthorized')
3530
}
3631
this.metricsManager.updateMetrics()

0 commit comments

Comments
 (0)