snakeia-server 1.1.3-6 → 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 CHANGED
@@ -1,4 +1,4 @@
1
- FROM node:20-alpine
1
+ FROM node:22-alpine
2
2
  RUN addgroup -S snakeia-server && adduser -S snakeia-server -G snakeia-server && chown -R snakeia-server:snakeia-server /home/snakeia-server
3
3
  RUN apk add git
4
4
  WORKDIR /home/snakeia-server/server
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.3.6 (7/25/2024)
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.3.6", // The server version
77
+ "version": "1.1.4", // The server version
78
78
  "port": 3000, // The port where the server runs
79
- "proxyMode": false, // Set this value to true if your server is behind a proxy - defaults to 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 (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
+
131
+ * Version 1.1.3.7 (9/19/2024) :
132
+ - Updated dependencies
133
+
122
134
  * Version 1.1.3.6 (7/25/2024) :
123
135
  - Updated dependencies
124
136
 
@@ -167,7 +179,7 @@ Un serveur pour mon jeu [SnakeIA](https://github.com/Eliastik/snakeia), écrit e
167
179
 
168
180
  ## À propos de ce serveur
169
181
 
170
- * Version 1.1.3.6 (25/07/2024)
182
+ * Version 1.1.4 (23/11/2024)
171
183
  * Made in France by Eliastik - [eliastiksofts.com](http://eliastiksofts.com) - Contact : [eliastiksofts.com/contact](http://eliastiksofts.com/contact)
172
184
  * Licence : GNU GPLv3 (voir le fichier LICENCE.txt)
173
185
 
@@ -233,9 +245,10 @@ Vous pouvez créer un fichier de configuration **local.json** dans le dossier **
233
245
  ````
234
246
  {
235
247
  "ServerConfig": {
236
- "version": "1.1.3.6", // La version du serveur
248
+ "version": "1.1.4", // La version du serveur
237
249
  "port": 3000, // Le port sur lequel lancer le server
238
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
239
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
240
253
  "maxPlayers": 20, // Le nombre maximal d'utilisateurs par salle
241
254
  "maxRooms": 20, // Le nombre maximal de salles
@@ -278,6 +291,17 @@ Vous pouvez créer un fichier de configuration **local.json** dans le dossier **
278
291
 
279
292
  ## Journal des changements
280
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
+
302
+ * Version 1.1.3.7 (19/09/2024) :
303
+ - Mise à jour des dépendences
304
+
281
305
  * Version 1.1.3.6 (25/07/2024) :
282
306
  - Mise à jour des dépendences
283
307
 
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "ServerConfig": {
3
- "version": "1.1.3.6",
3
+ "version": "1.1.4",
4
4
  "port": 3000,
5
5
  "proxyMode": false,
6
+ "numberOfProxies": 1,
6
7
  "enableMultithreading": true,
7
8
  "maxPlayers": 20,
8
9
  "maxRooms": 20,
@@ -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-6",
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": {
@@ -18,21 +18,21 @@
18
18
  },
19
19
  "homepage": "https://github.com/Eliastik/snakeia-server#readme",
20
20
  "dependencies": {
21
- "body-parser": "^1.20.2",
21
+ "body-parser": "^1.20.3",
22
22
  "config": "^3.3.12",
23
- "cookie-parser": "^1.4.6",
24
- "csurf": "^1.11.0",
25
- "ejs": "^3.1.9",
26
- "express": "^4.19.2",
27
- "express-rate-limit": "^7.4.0",
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": "git+https://git@github.com/Eliastik/snakeia.git#2.2",
34
- "socket.io": "^4.7.5",
33
+ "snakeia": "^2.2.0-0",
34
+ "socket.io": "^4.8.1",
35
35
  "socket.io-cookie-parser": "^1.0.0",
36
- "winston": "^3.13.1"
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 csrf = require("csurf");
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(process.env.NODE_ENV !== "production") {
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 csrfProtection = csrf({ cookie: true });
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", csrfProtection, function(req, res) {
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.csrfToken(),
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, csrfProtection, function(req, res) {
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
- var token = document.querySelector("meta[name='csrf-token']").getAttribute("content");
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
- "CSRF-Token": token,
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
- var elements = document.querySelectorAll("[data-action]");
276
+ const elements = document.querySelectorAll("[data-action]");
277
277
 
278
278
  elements.forEach(function(element) {
279
- var action = element.dataset.action;
280
- var form = element.dataset.form;
281
- var data = {};
282
- var confirmAction = element.dataset.confirmAction;
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
- var key = element.split("=")[0];
288
- var value = element.split("=")[1];
287
+ const key = element.split("=")[0];
288
+ const value = element.split("=")[1];
289
289
  data[key] = value;
290
290
  }
291
291
  });