snakeia-server 1.1.3-7 → 1.1.4-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile +1 -1
- package/README.md +31 -7
- package/config/default.json +2 -1
- package/docker-compose.yml +4 -0
- package/package.json +9 -9
- package/server.js +19 -8
- package/views/admin.html +9 -9
package/Dockerfile
CHANGED
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A server for my [SnakeIA](https://github.com/Eliastik/snakeia) game, written in
|
|
|
8
8
|
|
|
9
9
|
## About this server
|
|
10
10
|
|
|
11
|
-
* Version 1.1.
|
|
11
|
+
* Version 1.1.4.1 (1/1/2025)
|
|
12
12
|
* Made in France by Eliastik - [eliastiksofts.com](http://eliastiksofts.com) - Contact : [eliastiksofts.com/contact](http://eliastiksofts.com/contact)
|
|
13
13
|
* License: GNU GPLv3 (see LICENCE.txt file)
|
|
14
14
|
|
|
@@ -74,9 +74,10 @@ You can create another configuration file in the **config** directory named **lo
|
|
|
74
74
|
````
|
|
75
75
|
{
|
|
76
76
|
"ServerConfig": {
|
|
77
|
-
"version": "1.1.
|
|
77
|
+
"version": "1.1.4.1", // The server version
|
|
78
78
|
"port": 3000, // The port where the server runs
|
|
79
|
-
"proxyMode": false, //
|
|
79
|
+
"proxyMode": false, // Sets this value to true if your server is behind a proxy - defaults to false
|
|
80
|
+
"numberOfProxies": 1, // Sets the number of reverse proxies in front of the server. Default to 1. See: https://expressjs.com/en/guide/behind-proxies.html / https://express-rate-limit.mintlify.app/guides/troubleshooting-proxy-issues
|
|
80
81
|
"enableMultithreading": true, // Enabling the use of different threads for the game engine, improves performance / requires a version of Nodejs that supports Worker Threads
|
|
81
82
|
"maxPlayers": 20, // The maximum number of players for each room
|
|
82
83
|
"maxRooms": 20, // The maximum number of room
|
|
@@ -119,6 +120,17 @@ You can create another configuration file in the **config** directory named **lo
|
|
|
119
120
|
|
|
120
121
|
## Changelog
|
|
121
122
|
|
|
123
|
+
* Version 1.1.4.1 (1/1/2024):
|
|
124
|
+
- Updated dependencies
|
|
125
|
+
|
|
126
|
+
* Version 1.1.4 (11/23/2024):
|
|
127
|
+
- Switched to csrf-csrf library instead of csurf (no longer maintained) for CSRF protection
|
|
128
|
+
- Added "numberOfProxies" parameter (default 1) to server configuration file
|
|
129
|
+
- Updated dependencies
|
|
130
|
+
|
|
131
|
+
* Version 1.1.3.8 (9/29/2024) :
|
|
132
|
+
- Updated dependencies
|
|
133
|
+
|
|
122
134
|
* Version 1.1.3.7 (9/19/2024) :
|
|
123
135
|
- Updated dependencies
|
|
124
136
|
|
|
@@ -170,7 +182,7 @@ Un serveur pour mon jeu [SnakeIA](https://github.com/Eliastik/snakeia), écrit e
|
|
|
170
182
|
|
|
171
183
|
## À propos de ce serveur
|
|
172
184
|
|
|
173
|
-
* Version 1.1.
|
|
185
|
+
* Version 1.1.4.1 (1/1/2025)
|
|
174
186
|
* Made in France by Eliastik - [eliastiksofts.com](http://eliastiksofts.com) - Contact : [eliastiksofts.com/contact](http://eliastiksofts.com/contact)
|
|
175
187
|
* Licence : GNU GPLv3 (voir le fichier LICENCE.txt)
|
|
176
188
|
|
|
@@ -236,9 +248,10 @@ Vous pouvez créer un fichier de configuration **local.json** dans le dossier **
|
|
|
236
248
|
````
|
|
237
249
|
{
|
|
238
250
|
"ServerConfig": {
|
|
239
|
-
"version": "1.1.
|
|
251
|
+
"version": "1.1.4.1", // La version du serveur
|
|
240
252
|
"port": 3000, // Le port sur lequel lancer le server
|
|
241
253
|
"proxyMode": false, // Mettez à true si votre serveur est derrière un proxy - par défaut false
|
|
254
|
+
"numberOfProxies": 1, // Configure le nombre de proxies devant votre serveur. Par défaut 1. Voir : https://expressjs.com/en/guide/behind-proxies.html / https://express-rate-limit.mintlify.app/guides/troubleshooting-proxy-issues
|
|
242
255
|
"enableMultithreading": true, // Activer l'utilisation de threads différents pour le moteur de jeu, améliore les performances / nécessite une version de Nodejs qui supporte les Worker Threads
|
|
243
256
|
"maxPlayers": 20, // Le nombre maximal d'utilisateurs par salle
|
|
244
257
|
"maxRooms": 20, // Le nombre maximal de salles
|
|
@@ -281,6 +294,17 @@ Vous pouvez créer un fichier de configuration **local.json** dans le dossier **
|
|
|
281
294
|
|
|
282
295
|
## Journal des changements
|
|
283
296
|
|
|
297
|
+
* Version 1.1.4.1 (1/1/2025) :
|
|
298
|
+
- Mise à jour des dépendences
|
|
299
|
+
|
|
300
|
+
* Version 1.1.4 (23/11/2024) :
|
|
301
|
+
- Passage à la bibliothèque logicielle csrf-csrf au lieu de csurf (qui n'était plus maintenue) pour la protection CSRF
|
|
302
|
+
- Ajout du paramètre "numberOfProxies" (par défaut à 1) dans le fichier de configuration du serveur
|
|
303
|
+
- Mise à jour des dépendences
|
|
304
|
+
|
|
305
|
+
* Version 1.1.3.8 (29/09/2024) :
|
|
306
|
+
- Mise à jour des dépendences
|
|
307
|
+
|
|
284
308
|
* Version 1.1.3.7 (19/09/2024) :
|
|
285
309
|
- Mise à jour des dépendences
|
|
286
310
|
|
|
@@ -335,7 +359,7 @@ Vous pouvez créer un fichier de configuration **local.json** dans le dossier **
|
|
|
335
359
|
|
|
336
360
|
## Déclaration de licence
|
|
337
361
|
|
|
338
|
-
Copyright (C) 2020-
|
|
362
|
+
Copyright (C) 2020-2025 Eliastik (eliastiksofts.com)
|
|
339
363
|
|
|
340
364
|
Ce programme est un logiciel libre ; vous pouvez le redistribuer ou le modifier suivant les termes de la GNU General Public License telle que publiée par la Free Software Foundation ; soit la version 3 de la licence, soit (à votre gré) toute version ultérieure.
|
|
341
365
|
|
|
@@ -345,7 +369,7 @@ Vous devez avoir reçu une copie de la GNU General Public License en même temps
|
|
|
345
369
|
|
|
346
370
|
----
|
|
347
371
|
|
|
348
|
-
Copyright (C) 2020-
|
|
372
|
+
Copyright (C) 2020-2025 Eliastik (eliastiksofts.com)
|
|
349
373
|
|
|
350
374
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
351
375
|
|
package/config/default.json
CHANGED
package/docker-compose.yml
CHANGED
|
@@ -3,6 +3,7 @@ version: "3.4"
|
|
|
3
3
|
services:
|
|
4
4
|
snakeia-server:
|
|
5
5
|
image: eliastik/snakeia-server:latest
|
|
6
|
+
container_name: snakeia-server
|
|
6
7
|
restart: unless-stopped
|
|
7
8
|
# uncomment to build the image
|
|
8
9
|
# build:
|
|
@@ -12,5 +13,8 @@ services:
|
|
|
12
13
|
NODE_ENV: production
|
|
13
14
|
volumes:
|
|
14
15
|
- ./config/default.json:/home/snakeia-server/server/config/default.json
|
|
16
|
+
# - ./config/local.json:/home/snakeia-server/server/config/local.json
|
|
17
|
+
- ./error.log:/home/snakeia-server/server/logs/error.log
|
|
18
|
+
- ./server.log:/home/snakeia-server/server/logs/server.log
|
|
15
19
|
ports:
|
|
16
20
|
- "3000:3000"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "snakeia-server",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4-1",
|
|
4
4
|
"description": "Server for multiplaying in SnakeIA (https://github.com/Eliastik/snakeia)",
|
|
5
5
|
"main": "server.js",
|
|
6
6
|
"scripts": {
|
|
@@ -20,19 +20,19 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"body-parser": "^1.20.3",
|
|
22
22
|
"config": "^3.3.12",
|
|
23
|
-
"cookie-parser": "^1.4.
|
|
24
|
-
"
|
|
25
|
-
"ejs": "^3.1.
|
|
26
|
-
"express": "^4.21.
|
|
27
|
-
"express-rate-limit": "^7.
|
|
23
|
+
"cookie-parser": "^1.4.7",
|
|
24
|
+
"csrf-csrf": "^3.1.0",
|
|
25
|
+
"ejs": "^3.1.10",
|
|
26
|
+
"express": "^4.21.2",
|
|
27
|
+
"express-rate-limit": "^7.5.0",
|
|
28
28
|
"html-entities": "^2.5.2",
|
|
29
29
|
"i18n": "^0.15.1",
|
|
30
30
|
"jsonwebtoken": "^9.0.2",
|
|
31
31
|
"node-fetch": "^3.3.2",
|
|
32
32
|
"seedrandom": "^3.0.5",
|
|
33
|
-
"snakeia": "
|
|
34
|
-
"socket.io": "^4.
|
|
33
|
+
"snakeia": "^2.2.0-0",
|
|
34
|
+
"socket.io": "^4.8.1",
|
|
35
35
|
"socket.io-cookie-parser": "^1.0.0",
|
|
36
|
-
"winston": "^3.
|
|
36
|
+
"winston": "^3.17.0"
|
|
37
37
|
}
|
|
38
38
|
}
|
package/server.js
CHANGED
|
@@ -36,7 +36,7 @@ const ioCookieParser = require("socket.io-cookie-parser");
|
|
|
36
36
|
const i18n = require("i18n");
|
|
37
37
|
const rateLimit = require("express-rate-limit");
|
|
38
38
|
const winston = require("winston");
|
|
39
|
-
const
|
|
39
|
+
const { doubleCsrf } = require("csrf-csrf");
|
|
40
40
|
const bodyParser = require("body-parser");
|
|
41
41
|
const node_config = require("config");
|
|
42
42
|
|
|
@@ -55,6 +55,8 @@ config.port = process.env.PORT || config.port;
|
|
|
55
55
|
const jsonWebTokenSecretKey = config.jsonWebTokenSecretKey && config.jsonWebTokenSecretKey.trim() != "" ? config.jsonWebTokenSecretKey : generateRandomJsonWebTokenSecretKey();
|
|
56
56
|
const jsonWebTokenSecretKeyAdmin = config.jsonWebTokenSecretKeyAdmin && config.jsonWebTokenSecretKeyAdmin.trim() != "" ? config.jsonWebTokenSecretKeyAdmin : generateRandomJsonWebTokenSecretKey(jsonWebTokenSecretKey);
|
|
57
57
|
|
|
58
|
+
const productionMode = process.env.NODE_ENV === "production";
|
|
59
|
+
|
|
58
60
|
// Update config to file
|
|
59
61
|
function updateConfigToFile() {
|
|
60
62
|
fs.writeFileSync(configFile, JSON.stringify({ "ServerConfig": config }, null, 4), "UTF-8");
|
|
@@ -73,14 +75,14 @@ const logger = winston.createLogger({
|
|
|
73
75
|
exceptionHandlers: config.enableLoggingFile ? [new winston.transports.File({ filename: config.errorLogFile })] : []
|
|
74
76
|
});
|
|
75
77
|
|
|
76
|
-
if(
|
|
78
|
+
if(!productionMode) {
|
|
77
79
|
logger.add(new winston.transports.Console({
|
|
78
80
|
format: winston.format.colorize()
|
|
79
81
|
}));
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
if(config.proxyMode) {
|
|
83
|
-
app.enable("trust proxy");
|
|
85
|
+
app.enable("trust proxy", config.numberOfProxies);
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
// Internationalization
|
|
@@ -1165,9 +1167,18 @@ function verifyFormAuthenticationAdmin(body) {
|
|
|
1165
1167
|
});
|
|
1166
1168
|
}
|
|
1167
1169
|
|
|
1168
|
-
const
|
|
1170
|
+
const csrfSecret = generateRandomJsonWebTokenSecretKey(jsonWebTokenSecretKeyAdmin);
|
|
1171
|
+
const { doubleCsrfProtection, generateToken } = doubleCsrf({
|
|
1172
|
+
getSecret: () => csrfSecret,
|
|
1173
|
+
cookieName: productionMode ? "__Host-snakeia-server.x-csrf-token" : "snakeia-server.x-csrf-token",
|
|
1174
|
+
cookieOptions: {
|
|
1175
|
+
sameSite: productionMode ? "strict" : "lax",
|
|
1176
|
+
path: "/",
|
|
1177
|
+
secure: productionMode
|
|
1178
|
+
}
|
|
1179
|
+
});
|
|
1169
1180
|
|
|
1170
|
-
app.get("/admin",
|
|
1181
|
+
app.get("/admin", doubleCsrfProtection, function(req, res) {
|
|
1171
1182
|
if(req.cookies) {
|
|
1172
1183
|
jwt.verify(req.cookies.tokenAdmin, jsonWebTokenSecretKeyAdmin, function(err, data) {
|
|
1173
1184
|
if(invalidatedAdminTokens.includes(req.cookies.tokenAdmin)) err = true;
|
|
@@ -1195,7 +1206,7 @@ app.get("/admin", csrfProtection, function(req, res) {
|
|
|
1195
1206
|
games: games,
|
|
1196
1207
|
io: io,
|
|
1197
1208
|
config: config,
|
|
1198
|
-
csrfToken: req
|
|
1209
|
+
csrfToken: generateToken(req, res, true),
|
|
1199
1210
|
serverLog: logFile,
|
|
1200
1211
|
errorLog: errorLogFile,
|
|
1201
1212
|
getIPSocketIO: getIPSocketIO
|
|
@@ -1288,14 +1299,14 @@ function adminAction(req, res, action) {
|
|
|
1288
1299
|
|
|
1289
1300
|
const jsonParser = bodyParser.json();
|
|
1290
1301
|
|
|
1291
|
-
app.post("/admin/:action", jsonParser,
|
|
1302
|
+
app.post("/admin/:action", jsonParser, doubleCsrfProtection, function(req, res) {
|
|
1292
1303
|
adminAction(req, res, req.params.action);
|
|
1293
1304
|
});
|
|
1294
1305
|
|
|
1295
1306
|
app.use(function (err, req, res, next) {
|
|
1296
1307
|
if(err.code !== "EBADCSRFTOKEN") return next(err);
|
|
1297
1308
|
res.status(403);
|
|
1298
|
-
res.send("Error");
|
|
1309
|
+
res.send("Error: invalid CSRF token");
|
|
1299
1310
|
});
|
|
1300
1311
|
|
|
1301
1312
|
const adminRateLimiter = rateLimit({
|
package/views/admin.html
CHANGED
|
@@ -251,13 +251,13 @@
|
|
|
251
251
|
</div>
|
|
252
252
|
<% if(authent && games) { %>
|
|
253
253
|
<script type="text/javascript">
|
|
254
|
-
|
|
254
|
+
const token = document.querySelector("meta[name='csrf-token']").getAttribute("content");
|
|
255
255
|
|
|
256
256
|
function requestAction(action, data, element) {
|
|
257
257
|
fetch("/admin/" + action, {
|
|
258
258
|
credentials: "same-origin",
|
|
259
259
|
headers: {
|
|
260
|
-
"
|
|
260
|
+
"x-csrf-token": token,
|
|
261
261
|
"Content-Type": "application/json",
|
|
262
262
|
},
|
|
263
263
|
method: "POST",
|
|
@@ -273,19 +273,19 @@
|
|
|
273
273
|
});
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
|
|
276
|
+
const elements = document.querySelectorAll("[data-action]");
|
|
277
277
|
|
|
278
278
|
elements.forEach(function(element) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
279
|
+
const action = element.dataset.action;
|
|
280
|
+
const form = element.dataset.form;
|
|
281
|
+
const data = {};
|
|
282
|
+
const confirmAction = element.dataset.confirmAction;
|
|
283
283
|
|
|
284
284
|
if(form) {
|
|
285
285
|
form.split("&").forEach(function(element) {
|
|
286
286
|
if(element) {
|
|
287
|
-
|
|
288
|
-
|
|
287
|
+
const key = element.split("=")[0];
|
|
288
|
+
const value = element.split("=")[1];
|
|
289
289
|
data[key] = value;
|
|
290
290
|
}
|
|
291
291
|
});
|