snakeia-server 1.1.3-7 → 1.1.4
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 +23 -5
- 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 (11/23/2024)
|
|
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", // 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,14 @@ You can create another configuration file in the **config** directory named **lo
|
|
|
119
120
|
|
|
120
121
|
## Changelog
|
|
121
122
|
|
|
123
|
+
* Version 1.1.4 (11/23/2024):
|
|
124
|
+
- Switched to csrf-csrf library instead of csurf (no longer maintained) for CSRF protection
|
|
125
|
+
- Added "numberOfProxies" parameter (default 1) to server configuration file
|
|
126
|
+
- Updated dependencies
|
|
127
|
+
|
|
128
|
+
* Version 1.1.3.8 (9/29/2024) :
|
|
129
|
+
- Updated dependencies
|
|
130
|
+
|
|
122
131
|
* Version 1.1.3.7 (9/19/2024) :
|
|
123
132
|
- Updated dependencies
|
|
124
133
|
|
|
@@ -170,7 +179,7 @@ Un serveur pour mon jeu [SnakeIA](https://github.com/Eliastik/snakeia), écrit e
|
|
|
170
179
|
|
|
171
180
|
## À propos de ce serveur
|
|
172
181
|
|
|
173
|
-
* Version 1.1.
|
|
182
|
+
* Version 1.1.4 (23/11/2024)
|
|
174
183
|
* Made in France by Eliastik - [eliastiksofts.com](http://eliastiksofts.com) - Contact : [eliastiksofts.com/contact](http://eliastiksofts.com/contact)
|
|
175
184
|
* Licence : GNU GPLv3 (voir le fichier LICENCE.txt)
|
|
176
185
|
|
|
@@ -236,9 +245,10 @@ Vous pouvez créer un fichier de configuration **local.json** dans le dossier **
|
|
|
236
245
|
````
|
|
237
246
|
{
|
|
238
247
|
"ServerConfig": {
|
|
239
|
-
"version": "1.1.
|
|
248
|
+
"version": "1.1.4", // La version du serveur
|
|
240
249
|
"port": 3000, // Le port sur lequel lancer le server
|
|
241
250
|
"proxyMode": false, // Mettez à true si votre serveur est derrière un proxy - par défaut false
|
|
251
|
+
"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
252
|
"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
253
|
"maxPlayers": 20, // Le nombre maximal d'utilisateurs par salle
|
|
244
254
|
"maxRooms": 20, // Le nombre maximal de salles
|
|
@@ -281,6 +291,14 @@ Vous pouvez créer un fichier de configuration **local.json** dans le dossier **
|
|
|
281
291
|
|
|
282
292
|
## Journal des changements
|
|
283
293
|
|
|
294
|
+
* Version 1.1.4 (23/11/2024) :
|
|
295
|
+
- Passage à la bibliothèque logicielle csrf-csrf au lieu de csurf (qui n'était plus maintenue) pour la protection CSRF
|
|
296
|
+
- Ajout du paramètre "numberOfProxies" (par défaut à 1) dans le fichier de configuration du serveur
|
|
297
|
+
- Mise à jour des dépendences
|
|
298
|
+
|
|
299
|
+
* Version 1.1.3.8 (29/09/2024) :
|
|
300
|
+
- Mise à jour des dépendences
|
|
301
|
+
|
|
284
302
|
* Version 1.1.3.7 (19/09/2024) :
|
|
285
303
|
- Mise à jour des dépendences
|
|
286
304
|
|
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",
|
|
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.4.
|
|
23
|
+
"cookie-parser": "^1.4.7",
|
|
24
|
+
"csrf-csrf": "^3.0.8",
|
|
25
|
+
"ejs": "^3.1.10",
|
|
26
|
+
"express": "^4.21.1",
|
|
27
|
+
"express-rate-limit": "^7.4.1",
|
|
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
|
});
|