This commit is contained in:
2025-08-15 12:19:41 +02:00
parent b47065edbf
commit 57acd761f9
13 changed files with 1102 additions and 116 deletions

View File

@@ -180,3 +180,406 @@ Connected to MongoDB
[2025-08-15T09:10:12.600Z] SESSION: Validate success 6cc910f09effb8c44ece418cc44b69fcb17501b7070656b4e1ba0cf95fff4844 christoffer
[2025-08-15T09:11:44.183Z] SESSION: Validate success 6cc910f09effb8c44ece418cc44b69fcb17501b7070656b4e1ba0cf95fff4844 christoffer
[2025-08-15T09:12:00.469Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:28.458Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:34.070Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:34.678Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:44.307Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:45.126Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:46.271Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:47.519Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:47.859Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:48.030Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:48.590Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:53.231Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:53.736Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:55.926Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:57.034Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:33:57.400Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:34:00.002Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:34:20.089Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:34:37.318Z] SESSION: Login success christoffer 5925e8bcc9d607a27648a80405d9985b1b3e7353b82d638b2b5b4ffe36c23449
[2025-08-15T09:34:37.330Z] SESSION: Validate success 5925e8bcc9d607a27648a80405d9985b1b3e7353b82d638b2b5b4ffe36c23449 christoffer
[2025-08-15T09:34:37.333Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:36:42.121Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:37:03.496Z] SESSION: Valid 5925e8bcc9d607a27648a80405d9985b1b3e7353b82d638b2b5b4ffe36c23449 christoffer PUT /api/players/christoffer
[2025-08-15T09:37:07.117Z] API: Failed to update player christoffer {"code":"MODULE_NOT_FOUND","requireStack":["/home/alex/git/dwroller/database/routes/playerRoutes-sqlite.js","/home/alex/git/dwroller/database/server.js"]}
[2025-08-15T09:37:10.595Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:37:18.118Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:37:24.505Z] SESSION: Logout success 5925e8bcc9d607a27648a80405d9985b1b3e7353b82d638b2b5b4ffe36c23449
[2025-08-15T09:37:24.513Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:37:27.500Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:37:27.911Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:37:28.085Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:37:30.703Z] SESSION: Login success phillip 0b28f0a3aa3398d909ba4e44bdff7329529908b8ec88ad21fe003ce59caa044c
[2025-08-15T09:37:30.714Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:37:30.717Z] SESSION: Validate success 0b28f0a3aa3398d909ba4e44bdff7329529908b8ec88ad21fe003ce59caa044c phillip
[2025-08-15T09:39:02.869Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:39:04.872Z] SESSION: Login success christoffer b19e94a3b117740e41cabd7803515d42023d41e286d3303c710f591e9f70c8e5
[2025-08-15T09:39:04.907Z] SESSION: Validate success b19e94a3b117740e41cabd7803515d42023d41e286d3303c710f591e9f70c8e5 christoffer
[2025-08-15T09:39:12.226Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:39:14.895Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:39:34.142Z] SESSION: Logout success b19e94a3b117740e41cabd7803515d42023d41e286d3303c710f591e9f70c8e5
[2025-08-15T09:39:34.192Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:42:54.757Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:42:54.772Z] API: Failed to create player gmtest {"code":"MODULE_NOT_FOUND","requireStack":["/home/alex/git/dwroller/database/routes/playerRoutes-sqlite.js","/home/alex/git/dwroller/database/server.js"]}
[2025-08-15T09:42:54.785Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:42:54.799Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T09:42:54.812Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:42:54.826Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T09:42:54.839Z] SESSION: GM bypass accepted DELETE /api/players/gmtest
[2025-08-15T09:42:54.852Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:43:18.701Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:45:20.371Z] API: Failed to create player gmtest {"code":"MODULE_NOT_FOUND","requireStack":["/home/alex/git/dwroller/database/routes/playerRoutes-sqlite.js","/home/alex/git/dwroller/database/server.js"]}
[2025-08-15T09:47:04.187Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:47:04.198Z] API: Failed to create player gmtest {"code":"MODULE_NOT_FOUND","requireStack":["/home/alex/git/dwroller/database/routes/playerRoutes-sqlite.js","/home/alex/git/dwroller/database/server.js"]}
[2025-08-15T09:47:04.208Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:47:04.219Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T09:47:04.230Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T09:47:04.240Z] SESSION: GM bypass accepted DELETE /api/players/gmtest
[2025-08-15T09:47:04.250Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:47:44.631Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:47:47.404Z] SESSION: Login success phillip 2d60199a5a383cf6c1467bd42b33055ad0ce77c4935bac31a6fd4d812c535f0a
[2025-08-15T09:47:47.475Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:47:47.482Z] SESSION: Validate success 2d60199a5a383cf6c1467bd42b33055ad0ce77c4935bac31a6fd4d812c535f0a phillip
[2025-08-15T09:47:50.107Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:48:03.443Z] API: Failed to create player gmtest2 {"code":"MODULE_NOT_FOUND","requireStack":["/home/alex/git/dwroller/database/routes/playerRoutes-sqlite.js","/home/alex/git/dwroller/database/server.js"]}
[2025-08-15T09:48:14.288Z] API: Failed to create player gmtest2 {"code":"MODULE_NOT_FOUND","requireStack":["/home/alex/git/dwroller/database/routes/playerRoutes-sqlite.js","/home/alex/git/dwroller/database/server.js"]}
[2025-08-15T09:49:19.949Z] DB: getPlayerByName - start gmtest
[2025-08-15T09:49:19.950Z] DB: getPlayerByName - not found gmtest
[2025-08-15T09:49:20.115Z] DB: createPlayer - start gmtest
[2025-08-15T09:49:20.125Z] DB: createPlayer - done gmtest rowid 4
[2025-08-15T09:49:20.125Z] API: Created player gmtest
[2025-08-15T09:52:14.622Z] DB: getAllPlayers - start
[2025-08-15T09:52:14.622Z] DB: getAllPlayers - resultCount 4
[2025-08-15T09:52:14.622Z] API: Fetch all players (public) Found 4 players
[2025-08-15T09:52:19.681Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T09:52:19.682Z] DB: getPlayerByName - start gmtest
[2025-08-15T09:52:19.682Z] DB: getPlayerByName - found gmtest
[2025-08-15T09:52:19.682Z] DB: updatePlayer - start gmtest
[2025-08-15T09:52:19.683Z] DB: updatePlayer - changes 1 gmtest
[2025-08-15T09:52:19.683Z] DB: getPlayerByName - start gmtest
[2025-08-15T09:52:19.683Z] DB: getPlayerByName - found gmtest
[2025-08-15T09:52:19.683Z] API: Updated player gmtest
[2025-08-15T09:52:25.522Z] DB: getPlayerByName - start gmtest
[2025-08-15T09:52:25.523Z] DB: getPlayerByName - found gmtest
[2025-08-15T09:52:25.523Z] API: Fetch player gmtest
[2025-08-15T09:52:31.755Z] DB: getPlayerByName - start gmtest
[2025-08-15T09:52:31.755Z] DB: getPlayerByName - found gmtest
[2025-08-15T09:52:31.756Z] API: Fetch player gmtest
[2025-08-15T09:52:38.318Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T09:52:38.318Z] DB: getPlayerByName - start gmtest
[2025-08-15T09:52:38.318Z] DB: getPlayerByName - found gmtest
[2025-08-15T09:52:38.398Z] DB: updatePlayer - start gmtest
[2025-08-15T09:52:38.398Z] DB: updatePlayer - changes 1 gmtest
[2025-08-15T09:52:38.398Z] DB: getPlayerByName - start gmtest
[2025-08-15T09:52:38.398Z] DB: getPlayerByName - found gmtest
[2025-08-15T09:52:38.398Z] API: Updated player gmtest
[2025-08-15T09:52:43.073Z] DB: getPlayerByName - start gmtest
[2025-08-15T09:52:43.074Z] DB: getPlayerByName - found gmtest
[2025-08-15T09:52:43.179Z] DB: createSession - start 959f0b154d1a554483362280c79ce52f0584358dc8a95228125b9be555b2cf89 expiresAt 2025-08-16T09:52:43.179Z
[2025-08-15T09:52:43.180Z] DB: createSession - done 959f0b154d1a554483362280c79ce52f0584358dc8a95228125b9be555b2cf89
[2025-08-15T09:52:43.180Z] API: Player login gmtest 959f0b154d1a554483362280c79ce52f0584358dc8a95228125b9be555b2cf89
[2025-08-15T09:52:47.647Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T09:52:47.647Z] DB: getPlayerByName - start gmtest
[2025-08-15T09:52:47.647Z] DB: getPlayerByName - found gmtest
[2025-08-15T09:52:47.647Z] DB: updatePlayer - start gmtest
[2025-08-15T09:52:47.647Z] DB: updatePlayer - changes 1 gmtest
[2025-08-15T09:52:47.647Z] DB: getPlayerByName - start gmtest
[2025-08-15T09:52:47.647Z] DB: getPlayerByName - found gmtest
[2025-08-15T09:52:47.647Z] API: Updated player gmtest
[2025-08-15T09:52:52.260Z] SESSION: GM bypass accepted DELETE /api/players/gmtest
[2025-08-15T09:52:52.260Z] DB: deletePlayer - start gmtest
[2025-08-15T09:52:52.261Z] DB: deletePlayer - changes 1 gmtest
[2025-08-15T09:52:52.261Z] API: Deleted player gmtest
[2025-08-15T09:52:57.546Z] DB: getAllPlayers - start
[2025-08-15T09:52:57.546Z] DB: getAllPlayers - resultCount 3
[2025-08-15T09:52:57.546Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:54:44.664Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:54:44.664Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:54:49.647Z] DB: getAllPlayers - start
[2025-08-15T09:54:49.647Z] DB: getAllPlayers - resultCount 3
[2025-08-15T09:54:49.647Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:55:47.472Z] SESSION: GM bypass accepted PUT /api/players/christoffer
[2025-08-15T09:55:47.473Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:55:47.473Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:55:47.589Z] DB: updatePlayer - start christoffer
[2025-08-15T09:55:47.590Z] DB: updatePlayer - changes 1 christoffer
[2025-08-15T09:55:47.590Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:55:47.590Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:55:47.590Z] API: Updated player christoffer
[2025-08-15T09:55:52.341Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:55:52.341Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:55:52.420Z] DB: createSession - start b624e0e4569e376c8d408bebb9a4d02ab67c06c49d6374b78506b2e29335ac49 expiresAt 2025-08-16T09:55:52.420Z
[2025-08-15T09:55:52.421Z] DB: createSession - done b624e0e4569e376c8d408bebb9a4d02ab67c06c49d6374b78506b2e29335ac49
[2025-08-15T09:55:52.421Z] API: Player login christoffer b624e0e4569e376c8d408bebb9a4d02ab67c06c49d6374b78506b2e29335ac49
[2025-08-15T09:56:00.491Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:56:00.491Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:56:00.491Z] API: Fetch player christoffer
[2025-08-15T09:56:05.962Z] DB: getSession - start b624e0e4569e376c8d408bebb9a4d02ab67c06c49d6374b78506b2e29335ac49
[2025-08-15T09:56:05.963Z] DB: getSession - ok b624e0e4569e376c8d408bebb9a4d02ab67c06c49d6374b78506b2e29335ac49
[2025-08-15T09:56:05.963Z] SESSION: Valid b624e0e4569e376c8d408bebb9a4d02ab67c06c49d6374b78506b2e29335ac49 christoffer PUT /api/players/christoffer
[2025-08-15T09:56:05.964Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:56:05.964Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:56:05.964Z] DB: updatePlayer - start christoffer
[2025-08-15T09:56:05.964Z] DB: updatePlayer - changes 1 christoffer
[2025-08-15T09:56:05.964Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:56:05.964Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:56:05.964Z] API: Updated player christoffer
[2025-08-15T09:56:10.814Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:56:10.814Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:56:10.814Z] API: Fetch player christoffer
[2025-08-15T09:56:28.669Z] DB: getSession - start b624e0e4569e376c8d408bebb9a4d02ab67c06c49d6374b78506b2e29335ac49
[2025-08-15T09:56:28.670Z] DB: getSession - ok b624e0e4569e376c8d408bebb9a4d02ab67c06c49d6374b78506b2e29335ac49
[2025-08-15T09:56:28.670Z] SESSION: Valid b624e0e4569e376c8d408bebb9a4d02ab67c06c49d6374b78506b2e29335ac49 christoffer PUT /api/players/christoffer
[2025-08-15T09:56:28.670Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:56:28.670Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:56:28.670Z] DB: updatePlayer - start christoffer
[2025-08-15T09:56:28.670Z] DB: updatePlayer - changes 1 christoffer
[2025-08-15T09:56:28.670Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:56:28.671Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:56:28.671Z] API: Updated player christoffer
[2025-08-15T09:56:35.927Z] DB: deleteSession - start 0b28f0a3aa3398d909ba4e44bdff7329529908b8ec88ad21fe003ce59caa044c
[2025-08-15T09:56:35.927Z] DB: deleteSession - changes 1 0b28f0a3aa3398d909ba4e44bdff7329529908b8ec88ad21fe003ce59caa044c
[2025-08-15T09:56:35.927Z] SESSION: Logout success 0b28f0a3aa3398d909ba4e44bdff7329529908b8ec88ad21fe003ce59caa044c
[2025-08-15T09:56:35.937Z] DB: getAllPlayers - start
[2025-08-15T09:56:35.937Z] DB: getAllPlayers - resultCount 3
[2025-08-15T09:56:35.937Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:56:38.419Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:56:38.420Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:56:38.420Z] DB: createSession - start df93fb133392f56772c27359ce103dacab71dbf72c91b787efe3ce620b00d8e3 expiresAt 2025-08-16T09:56:38.420Z
[2025-08-15T09:56:38.420Z] DB: createSession - done df93fb133392f56772c27359ce103dacab71dbf72c91b787efe3ce620b00d8e3
[2025-08-15T09:56:38.420Z] SESSION: Login success christoffer df93fb133392f56772c27359ce103dacab71dbf72c91b787efe3ce620b00d8e3
[2025-08-15T09:56:38.428Z] DB: getAllPlayers - start
[2025-08-15T09:56:38.429Z] DB: getAllPlayers - resultCount 3
[2025-08-15T09:56:38.429Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:56:38.438Z] DB: getSession - start df93fb133392f56772c27359ce103dacab71dbf72c91b787efe3ce620b00d8e3
[2025-08-15T09:56:38.438Z] DB: getSession - ok df93fb133392f56772c27359ce103dacab71dbf72c91b787efe3ce620b00d8e3
[2025-08-15T09:56:38.438Z] SESSION: Validate success df93fb133392f56772c27359ce103dacab71dbf72c91b787efe3ce620b00d8e3 christoffer
[2025-08-15T09:56:45.032Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:56:45.032Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:56:45.032Z] API: Fetch player christoffer
[2025-08-15T09:56:48.749Z] DB: getSession - start df93fb133392f56772c27359ce103dacab71dbf72c91b787efe3ce620b00d8e3
[2025-08-15T09:56:48.749Z] DB: getSession - ok df93fb133392f56772c27359ce103dacab71dbf72c91b787efe3ce620b00d8e3
[2025-08-15T09:56:48.749Z] SESSION: Validate success df93fb133392f56772c27359ce103dacab71dbf72c91b787efe3ce620b00d8e3 christoffer
[2025-08-15T09:56:50.169Z] DB: getAllPlayers - start
[2025-08-15T09:56:50.169Z] DB: getAllPlayers - resultCount 3
[2025-08-15T09:56:50.169Z] API: Fetch all players (public) Found 3 players
[2025-08-15T09:58:59.451Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:58:59.451Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:58:59.532Z] DB: createSession - start 2db67a36a9c4453f5d99c9a6b20a49f892f79f4e36575c139fe596ad256ad7ff expiresAt 2025-08-16T09:58:59.532Z
[2025-08-15T09:58:59.532Z] DB: createSession - done 2db67a36a9c4453f5d99c9a6b20a49f892f79f4e36575c139fe596ad256ad7ff
[2025-08-15T09:58:59.532Z] API: Player login christoffer 2db67a36a9c4453f5d99c9a6b20a49f892f79f4e36575c139fe596ad256ad7ff
[2025-08-15T09:59:28.107Z] DB: getSession - start 2db67a36a9c4453f5d99c9a6b20a49f892f79f4e36575c139fe596ad256ad7ff
[2025-08-15T09:59:28.107Z] DB: getSession - ok 2db67a36a9c4453f5d99c9a6b20a49f892f79f4e36575c139fe596ad256ad7ff
[2025-08-15T09:59:28.107Z] SESSION: Valid 2db67a36a9c4453f5d99c9a6b20a49f892f79f4e36575c139fe596ad256ad7ff christoffer PUT /api/players/christoffer
[2025-08-15T09:59:28.108Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:59:28.108Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:59:28.108Z] DB: updatePlayer - start christoffer
[2025-08-15T09:59:28.108Z] DB: updatePlayer - changes 1 christoffer
[2025-08-15T09:59:28.108Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:59:28.108Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:59:28.108Z] API: Updated player christoffer
[2025-08-15T09:59:34.647Z] DB: getPlayerByName - start christoffer
[2025-08-15T09:59:34.647Z] DB: getPlayerByName - found christoffer
[2025-08-15T09:59:34.647Z] API: Fetch player christoffer
[2025-08-15T10:02:29.124Z] DB: getAllPlayers - start
[2025-08-15T10:02:29.126Z] DB: getAllPlayers - resultCount 3
[2025-08-15T10:02:36.492Z] DB: getAllPlayers - start
[2025-08-15T10:02:36.493Z] DB: getAllPlayers - resultCount 3
[2025-08-15T10:04:04.343Z] DB: getAllPlayers - start
[2025-08-15T10:04:04.344Z] DB: getAllPlayers - resultCount 3
[2025-08-15T10:07:18.463Z] DB: getAllPlayers - start
[2025-08-15T10:07:18.464Z] DB: getAllPlayers - resultCount 3
[2025-08-15T10:12:41.561Z] DB: getAllPlayers - start
[2025-08-15T10:12:41.563Z] DB: getAllPlayers - resultCount 3
[2025-08-15T10:13:17.458Z] DB: getAllPlayers - start
[2025-08-15T10:13:17.459Z] DB: getAllPlayers - resultCount 3
[2025-08-15T10:13:55.439Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:13:55.440Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:13:55.522Z] DB: createSession - start 89217200ddee8c2dfbc6c3aa9c6d29087fd30ce045bbae12340d367cc89e20bd expiresAt 2025-08-16T10:13:55.522Z
[2025-08-15T10:13:55.522Z] DB: createSession - done 89217200ddee8c2dfbc6c3aa9c6d29087fd30ce045bbae12340d367cc89e20bd
[2025-08-15T10:13:55.522Z] API: Player login christoffer 89217200ddee8c2dfbc6c3aa9c6d29087fd30ce045bbae12340d367cc89e20bd
[2025-08-15T10:13:55.536Z] DB: getSession - start 89217200ddee8c2dfbc6c3aa9c6d29087fd30ce045bbae12340d367cc89e20bd
[2025-08-15T10:13:55.536Z] DB: getSession - ok 89217200ddee8c2dfbc6c3aa9c6d29087fd30ce045bbae12340d367cc89e20bd
[2025-08-15T10:13:55.536Z] SESSION: Valid 89217200ddee8c2dfbc6c3aa9c6d29087fd30ce045bbae12340d367cc89e20bd christoffer PUT /api/players/christoffer
[2025-08-15T10:13:55.536Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:13:55.537Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:13:55.537Z] DB: updatePlayer - start christoffer
[2025-08-15T10:13:55.537Z] DB: updatePlayer - changes 1 christoffer
[2025-08-15T10:13:55.537Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:13:55.537Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:13:55.537Z] API: Updated player christoffer
[2025-08-15T10:13:55.544Z] DB: getSession - start 89217200ddee8c2dfbc6c3aa9c6d29087fd30ce045bbae12340d367cc89e20bd
[2025-08-15T10:13:55.544Z] DB: getSession - ok 89217200ddee8c2dfbc6c3aa9c6d29087fd30ce045bbae12340d367cc89e20bd
[2025-08-15T10:13:55.544Z] SESSION: Valid 89217200ddee8c2dfbc6c3aa9c6d29087fd30ce045bbae12340d367cc89e20bd christoffer PUT /api/players/christoffer
[2025-08-15T10:13:55.544Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:13:55.544Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:13:55.544Z] DB: updatePlayer - start christoffer
[2025-08-15T10:13:55.544Z] DB: updatePlayer - changes 1 christoffer
[2025-08-15T10:13:55.545Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:13:55.545Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:13:55.545Z] API: Updated player christoffer
[2025-08-15T10:13:56.163Z] DB: getAllPlayers - start
[2025-08-15T10:13:56.164Z] DB: getAllPlayers - resultCount 3
[2025-08-15T10:14:23.849Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:14:23.849Z] DB: getPlayerByName - not found gmtest
[2025-08-15T10:14:23.929Z] DB: createPlayer - start gmtest
[2025-08-15T10:14:23.929Z] DB: createPlayer - done gmtest rowid 5
[2025-08-15T10:14:23.935Z] API: Created player gmtest
[2025-08-15T10:14:23.945Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T10:14:23.945Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:14:23.945Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:14:23.945Z] DB: updatePlayer - start gmtest
[2025-08-15T10:14:23.945Z] DB: updatePlayer - changes 1 gmtest
[2025-08-15T10:14:23.945Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:14:23.945Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:14:23.946Z] API: Updated player gmtest
[2025-08-15T10:14:23.950Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T10:14:23.950Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:14:23.950Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:14:24.030Z] DB: updatePlayer - start gmtest
[2025-08-15T10:14:24.030Z] DB: updatePlayer - changes 1 gmtest
[2025-08-15T10:14:24.030Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:14:24.030Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:14:24.030Z] API: Updated player gmtest
[2025-08-15T10:14:24.067Z] SESSION: GM bypass accepted DELETE /api/players/gmtest
[2025-08-15T10:14:24.067Z] DB: deletePlayer - start gmtest
[2025-08-15T10:14:24.067Z] DB: deletePlayer - changes 1 gmtest
[2025-08-15T10:14:24.067Z] API: Deleted player gmtest
[2025-08-15T10:14:24.321Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:14:24.321Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:14:24.400Z] DB: createSession - start bdf9dddc06ea9d1830f1c689cf2c8b81e6b79cfbd81bfb5b84bc46a9e24ae78f expiresAt 2025-08-16T10:14:24.400Z
[2025-08-15T10:14:24.401Z] DB: createSession - done bdf9dddc06ea9d1830f1c689cf2c8b81e6b79cfbd81bfb5b84bc46a9e24ae78f
[2025-08-15T10:14:24.401Z] API: Player login christoffer bdf9dddc06ea9d1830f1c689cf2c8b81e6b79cfbd81bfb5b84bc46a9e24ae78f
[2025-08-15T10:14:24.410Z] DB: getSession - start bdf9dddc06ea9d1830f1c689cf2c8b81e6b79cfbd81bfb5b84bc46a9e24ae78f
[2025-08-15T10:14:24.410Z] DB: getSession - ok bdf9dddc06ea9d1830f1c689cf2c8b81e6b79cfbd81bfb5b84bc46a9e24ae78f
[2025-08-15T10:14:24.410Z] SESSION: Valid bdf9dddc06ea9d1830f1c689cf2c8b81e6b79cfbd81bfb5b84bc46a9e24ae78f christoffer PUT /api/players/christoffer
[2025-08-15T10:14:24.410Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:14:24.410Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:14:24.410Z] DB: updatePlayer - start christoffer
[2025-08-15T10:14:24.411Z] DB: updatePlayer - changes 1 christoffer
[2025-08-15T10:14:24.411Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:14:24.411Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:14:24.411Z] API: Updated player christoffer
[2025-08-15T10:14:24.417Z] DB: getSession - start bdf9dddc06ea9d1830f1c689cf2c8b81e6b79cfbd81bfb5b84bc46a9e24ae78f
[2025-08-15T10:14:24.417Z] DB: getSession - ok bdf9dddc06ea9d1830f1c689cf2c8b81e6b79cfbd81bfb5b84bc46a9e24ae78f
[2025-08-15T10:14:24.417Z] SESSION: Valid bdf9dddc06ea9d1830f1c689cf2c8b81e6b79cfbd81bfb5b84bc46a9e24ae78f christoffer PUT /api/players/christoffer
[2025-08-15T10:14:24.417Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:14:24.417Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:14:24.417Z] DB: updatePlayer - start christoffer
[2025-08-15T10:14:24.418Z] DB: updatePlayer - changes 1 christoffer
[2025-08-15T10:14:24.418Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:14:24.418Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:14:24.418Z] API: Updated player christoffer
[2025-08-15T10:14:24.778Z] DB: getAllPlayers - start
[2025-08-15T10:14:24.778Z] DB: getAllPlayers - resultCount 3
[2025-08-15T10:14:57.192Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:14:57.192Z] DB: getPlayerByName - not found gmtest
[2025-08-15T10:14:57.272Z] DB: createPlayer - start gmtest
[2025-08-15T10:14:57.272Z] DB: createPlayer - done gmtest rowid 6
[2025-08-15T10:14:57.272Z] API: Created player gmtest
[2025-08-15T10:14:57.292Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T10:14:57.293Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:14:57.293Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:14:57.293Z] DB: updatePlayer - start gmtest
[2025-08-15T10:14:57.293Z] DB: updatePlayer - changes 1 gmtest
[2025-08-15T10:14:57.293Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:14:57.293Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:14:57.294Z] API: Updated player gmtest
[2025-08-15T10:14:57.313Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T10:14:57.313Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:14:57.313Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:14:57.393Z] DB: updatePlayer - start gmtest
[2025-08-15T10:14:57.393Z] DB: updatePlayer - changes 1 gmtest
[2025-08-15T10:14:57.393Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:14:57.394Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:14:57.394Z] API: Updated player gmtest
[2025-08-15T10:14:57.412Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:14:57.412Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:14:57.492Z] DB: createSession - start ed409e978652642d30d86d34aa1cc727d6ab0493bf562e936f067d8ae82918da expiresAt 2025-08-16T10:14:57.492Z
[2025-08-15T10:14:57.493Z] DB: createSession - done ed409e978652642d30d86d34aa1cc727d6ab0493bf562e936f067d8ae82918da
[2025-08-15T10:14:57.493Z] API: Player login gmtest ed409e978652642d30d86d34aa1cc727d6ab0493bf562e936f067d8ae82918da
[2025-08-15T10:14:57.513Z] SESSION: GM bypass accepted DELETE /api/players/gmtest
[2025-08-15T10:14:57.514Z] DB: deletePlayer - start gmtest
[2025-08-15T10:14:57.514Z] DB: deletePlayer - changes 1 gmtest
[2025-08-15T10:14:57.514Z] API: Deleted player gmtest
[2025-08-15T10:15:03.883Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:15:03.884Z] DB: getPlayerByName - not found gmtest
[2025-08-15T10:16:37.465Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:16:37.465Z] DB: getPlayerByName - not found gmtest
[2025-08-15T10:16:37.544Z] DB: createPlayer - start gmtest
[2025-08-15T10:16:37.545Z] DB: createPlayer - done gmtest rowid 7
[2025-08-15T10:16:37.545Z] API: Created player gmtest
[2025-08-15T10:16:37.555Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T10:16:37.555Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:16:37.555Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:16:37.555Z] DB: updatePlayer - start gmtest
[2025-08-15T10:16:37.555Z] DB: updatePlayer - changes 1 gmtest
[2025-08-15T10:16:37.555Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:16:37.555Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:16:37.555Z] API: Updated player gmtest
[2025-08-15T10:16:37.559Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T10:16:37.560Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:16:37.560Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:16:37.639Z] DB: updatePlayer - start gmtest
[2025-08-15T10:16:37.640Z] DB: updatePlayer - changes 1 gmtest
[2025-08-15T10:16:37.640Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:16:37.640Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:16:37.640Z] API: Updated player gmtest
[2025-08-15T10:16:37.678Z] SESSION: GM bypass accepted DELETE /api/players/gmtest
[2025-08-15T10:16:37.678Z] DB: deletePlayer - start gmtest
[2025-08-15T10:16:37.678Z] DB: deletePlayer - changes 1 gmtest
[2025-08-15T10:16:37.678Z] API: Deleted player gmtest
[2025-08-15T10:16:38.071Z] DB: getAllPlayers - start
[2025-08-15T10:16:38.071Z] DB: getAllPlayers - resultCount 3
[2025-08-15T10:16:38.331Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:16:38.331Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:16:38.411Z] DB: createSession - start a9d8e32089760c947f479f6a4e5f9cf57250a3741b1cc633c3e98db23c1386ea expiresAt 2025-08-16T10:16:38.411Z
[2025-08-15T10:16:38.411Z] DB: createSession - done a9d8e32089760c947f479f6a4e5f9cf57250a3741b1cc633c3e98db23c1386ea
[2025-08-15T10:16:38.411Z] API: Player login christoffer a9d8e32089760c947f479f6a4e5f9cf57250a3741b1cc633c3e98db23c1386ea
[2025-08-15T10:16:38.421Z] DB: getSession - start a9d8e32089760c947f479f6a4e5f9cf57250a3741b1cc633c3e98db23c1386ea
[2025-08-15T10:16:38.421Z] DB: getSession - ok a9d8e32089760c947f479f6a4e5f9cf57250a3741b1cc633c3e98db23c1386ea
[2025-08-15T10:16:38.421Z] SESSION: Valid a9d8e32089760c947f479f6a4e5f9cf57250a3741b1cc633c3e98db23c1386ea christoffer PUT /api/players/christoffer
[2025-08-15T10:16:38.421Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:16:38.421Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:16:38.421Z] DB: updatePlayer - start christoffer
[2025-08-15T10:16:38.421Z] DB: updatePlayer - changes 1 christoffer
[2025-08-15T10:16:38.421Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:16:38.422Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:16:38.422Z] API: Updated player christoffer
[2025-08-15T10:16:38.428Z] DB: getSession - start a9d8e32089760c947f479f6a4e5f9cf57250a3741b1cc633c3e98db23c1386ea
[2025-08-15T10:16:38.428Z] DB: getSession - ok a9d8e32089760c947f479f6a4e5f9cf57250a3741b1cc633c3e98db23c1386ea
[2025-08-15T10:16:38.428Z] SESSION: Valid a9d8e32089760c947f479f6a4e5f9cf57250a3741b1cc633c3e98db23c1386ea christoffer PUT /api/players/christoffer
[2025-08-15T10:16:38.429Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:16:38.429Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:16:38.429Z] DB: updatePlayer - start christoffer
[2025-08-15T10:16:38.429Z] DB: updatePlayer - changes 1 christoffer
[2025-08-15T10:16:38.429Z] DB: getPlayerByName - start christoffer
[2025-08-15T10:16:38.429Z] DB: getPlayerByName - found christoffer
[2025-08-15T10:16:38.429Z] API: Updated player christoffer
[2025-08-15T10:17:17.822Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:17:17.823Z] DB: getPlayerByName - not found gmtest
[2025-08-15T10:17:17.902Z] DB: createPlayer - start gmtest
[2025-08-15T10:17:17.903Z] DB: createPlayer - done gmtest rowid 8
[2025-08-15T10:17:17.903Z] API: Created player gmtest
[2025-08-15T10:17:17.914Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T10:17:17.915Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:17:17.915Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:17:17.915Z] DB: updatePlayer - start gmtest
[2025-08-15T10:17:17.915Z] DB: updatePlayer - changes 1 gmtest
[2025-08-15T10:17:17.915Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:17:17.915Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:17:17.915Z] API: Updated player gmtest
[2025-08-15T10:17:17.925Z] SESSION: GM bypass accepted PUT /api/players/gmtest
[2025-08-15T10:17:17.925Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:17:17.926Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:17:18.005Z] DB: updatePlayer - start gmtest
[2025-08-15T10:17:18.005Z] DB: updatePlayer - changes 1 gmtest
[2025-08-15T10:17:18.005Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:17:18.006Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:17:18.006Z] API: Updated player gmtest
[2025-08-15T10:17:18.017Z] DB: getPlayerByName - start gmtest
[2025-08-15T10:17:18.018Z] DB: getPlayerByName - found gmtest
[2025-08-15T10:17:18.099Z] DB: createSession - start e5a905f54488e26aae838d7a16d7f50d681f54c72749485f7944464e35b92e9d expiresAt 2025-08-16T10:17:18.099Z
[2025-08-15T10:17:18.100Z] DB: createSession - done e5a905f54488e26aae838d7a16d7f50d681f54c72749485f7944464e35b92e9d
[2025-08-15T10:17:18.100Z] API: Player login gmtest e5a905f54488e26aae838d7a16d7f50d681f54c72749485f7944464e35b92e9d

View File

@@ -1,4 +1,4 @@
const Session = require('./sessionModel');
const { sessionHelpers } = require('./sqlite-db');
const fs = require('fs');
const path = require('path');
function logToFile(...args) {
@@ -7,26 +7,44 @@ function logToFile(...args) {
}
// Express middleware to require a valid sessionId in req.headers['x-session-id'] or req.body.sessionId
// Attaches req.session and req.sessionPlayerName if valid, else sends 401
// Accepts a GM bypass header 'x-gm-secret' matching process.env.GM_PASSWORD or 'bongo' for local convenience
module.exports = async function requireSession(req, res, next) {
// Ensure req.body is always an object
if (typeof req.body !== 'object' || req.body === null) req.body = {};
const sessionId = req.headers['x-session-id'] || req.body.sessionId || req.query.sessionId;
if (!sessionId) {
logToFile('SESSION: Missing sessionId', req.method, req.originalUrl);
return res.status(401).json({ error: 'Session required' });
try {
// GM bypass
const gmSecret = req.headers['x-gm-secret'] || req.query.gmSecret || req.body.gmSecret;
const gmPassword = process.env.GM_PASSWORD || 'bongo';
if (gmSecret && String(gmSecret) === String(gmPassword)) {
logToFile('SESSION: GM bypass accepted', req.method, req.originalUrl);
req.session = { data: { playerName: 'GM' }, playerName: 'GM' };
req.sessionPlayerName = 'GM';
return next();
}
// Ensure req.body is always an object
if (typeof req.body !== 'object' || req.body === null) req.body = {};
const sessionId = req.headers['x-session-id'] || req.body.sessionId || req.query.sessionId;
if (!sessionId) {
logToFile('SESSION: Missing sessionId', req.method, req.originalUrl);
return res.status(401).json({ error: 'Session required' });
}
const session = sessionHelpers.get(sessionId);
if (!session) {
logToFile('SESSION: Not found', sessionId, req.method, req.originalUrl);
return res.status(401).json({ error: 'Invalid or expired session' });
}
if (new Date(session.expiresAt) < new Date()) {
logToFile('SESSION: Expired', sessionId, req.method, req.originalUrl);
return res.status(401).json({ error: 'Invalid or expired session' });
}
logToFile('SESSION: Valid', sessionId, session.data.playerName, req.method, req.originalUrl);
req.session = session;
req.sessionPlayerName = session.data.playerName;
next();
} catch (err) {
logToFile('SESSION: Error', err && err.message ? err.message : String(err));
return res.status(500).json({ error: 'Session validation failed' });
}
const session = await Session.findOne({ sessionId });
if (!session) {
logToFile('SESSION: Not found', sessionId, req.method, req.originalUrl);
return res.status(401).json({ error: 'Invalid or expired session' });
}
if (session.expiresAt < new Date()) {
logToFile('SESSION: Expired', sessionId, req.method, req.originalUrl);
return res.status(401).json({ error: 'Invalid or expired session' });
}
logToFile('SESSION: Valid', sessionId, session.playerName, req.method, req.originalUrl);
req.session = session;
req.sessionPlayerName = session.playerName;
next();
};

View File

@@ -1,5 +1,5 @@
const express = require('express');
const { playerHelpers } = require('../sqlite-db');
const { playerHelpers, sessionHelpers } = require('../sqlite-db');
const fs = require('fs');
const path = require('path');
@@ -12,6 +12,30 @@ function logToFile(...args) {
const requireSession = require('../requireSession');
const router = express.Router();
// Add safe bcrypt helpers to avoid MODULE_NOT_FOUND failures at runtime
async function safeHash(pw) {
if (!pw) return '';
try {
const bcrypt = require('bcrypt');
return await bcrypt.hash(pw, 10);
} catch (err) {
// Fallback to storing plaintext (development only) and log the error
logToFile('WARN: bcrypt.hash failed, falling back to plaintext pw', err && err.stack ? err.stack : String(err));
return String(pw);
}
}
async function safeCompare(candidate, hashed) {
try {
const bcrypt = require('bcrypt');
return await bcrypt.compare(candidate, hashed);
} catch (err) {
// If bcrypt not available, fall back to plaintext comparison (dev only)
logToFile('WARN: bcrypt.compare failed, falling back to plaintext compare', err && err.stack ? err.stack : String(err));
return String(candidate) === String(hashed);
}
}
// TEMP ADMIN: List all users
router.get('/admin/list', async (req, res) => {
try {
@@ -48,11 +72,17 @@ router.get('/', async (req, res) => {
try {
const players = playerHelpers.getAll();
logToFile('API: Fetch all players (public)', `Found ${players.length} players`);
// Only send name for dropdown if not authed
if (!req.headers['x-session-id']) {
// Allow full list if client provided a valid session id OR the GM secret header
const gmSecret = req.headers['x-gm-secret'] || req.query.gmSecret || (req.body && req.body.gmSecret);
const gmPassword = process.env.GM_PASSWORD || 'bongo';
const isGm = gmSecret && String(gmSecret) === String(gmPassword);
const isAuthed = !!req.headers['x-session-id'];
if (!isAuthed && !isGm) {
return res.json(players.map(p => ({ name: p.name })));
}
res.json(players);
} catch (error) {
logToFile('API: Failed to fetch players', error);
@@ -90,11 +120,10 @@ router.post('/', async (req, res) => {
return res.status(409).json({ error: 'Player already exists' });
}
// Create password hash if password provided
// Create password hash if password provided (use safeHash)
let pwHash = '';
if (pw) {
const bcrypt = require('bcrypt');
pwHash = await bcrypt.hash(pw, 10);
pwHash = await safeHash(pw);
}
const newPlayer = playerHelpers.create({
@@ -109,7 +138,8 @@ router.post('/', async (req, res) => {
logToFile('API: Created player', name);
res.status(201).json(newPlayer);
} catch (error) {
logToFile('API: Failed to create player', req.body.name, error);
// Log stack for easier debugging
logToFile('API: Failed to create player', req.body && req.body.name, error && error.stack ? error.stack : error);
res.status(500).json({ error: 'Failed to create player' });
}
});
@@ -126,10 +156,9 @@ router.put('/:name', requireSession, async (req, res) => {
return res.status(404).json({ error: 'Player not found' });
}
// Handle password update if provided
// Handle password update if provided using safeHash
if (updateData.pw) {
const bcrypt = require('bcrypt');
updateData.pwHash = await bcrypt.hash(updateData.pw, 10);
updateData.pwHash = await safeHash(updateData.pw);
}
// Merge the data properly
@@ -141,38 +170,20 @@ router.put('/:name', requireSession, async (req, res) => {
pwHash: updateData.pwHash || existingPlayer.pwHash
};
// Handle the special case where frontend sends flat data that should go into tabInfo
if (updateData.playerName || updateData.charName || updateData.characteristics) {
mergedData.tabInfo = {
...mergedData.tabInfo,
playerName: updateData.playerName || mergedData.tabInfo.playerName,
charName: updateData.charName || mergedData.tabInfo.charName,
gear: updateData.gear || mergedData.tabInfo.gear,
chapter: updateData.chapter || mergedData.tabInfo.chapter,
demeanour: updateData.demeanour || mergedData.tabInfo.demeanour,
speciality: updateData.speciality || mergedData.tabInfo.speciality,
rank: updateData.rank || mergedData.tabInfo.rank,
powerArmour: updateData.powerArmour || mergedData.tabInfo.powerArmour,
description: updateData.description || mergedData.tabInfo.description,
pastEvent: updateData.pastEvent || mergedData.tabInfo.pastEvent,
personalDemeanour: updateData.personalDemeanour || mergedData.tabInfo.personalDemeanour,
characteristics: updateData.characteristics || mergedData.tabInfo.characteristics,
skills: updateData.skills || mergedData.tabInfo.skills,
weapons: updateData.weapons || mergedData.tabInfo.weapons,
armour: updateData.armour || mergedData.tabInfo.armour,
talents: updateData.talents || mergedData.tabInfo.talents,
psychic: updateData.psychic || mergedData.tabInfo.psychic,
wounds: updateData.wounds || mergedData.tabInfo.wounds,
insanity: updateData.insanity || mergedData.tabInfo.insanity,
movement: updateData.movement || mergedData.tabInfo.movement,
fate: updateData.fate || mergedData.tabInfo.fate,
corruption: updateData.corruption || mergedData.tabInfo.corruption,
renown: updateData.renown || mergedData.tabInfo.renown,
xp: updateData.xp || mergedData.tabInfo.xp,
xpSpent: updateData.xpSpent || mergedData.tabInfo.xpSpent,
notes: updateData.notes || mergedData.tabInfo.notes,
rp: updateData.rp || mergedData.tabInfo.rp
};
// If frontend sends flat fields (not under tabInfo), map them into tabInfo.
// This accepts updates for any of the known tabInfo keys even when only those
// fields are sent, not requiring playerName/charName to be present.
const flatFields = [
'playerName','charName','gear','chapter','demeanour','speciality','rank','powerArmour',
'description','pastEvent','personalDemeanour','characteristics','skills','weapons','armour',
'talents','psychic','wounds','insanity','movement','fate','corruption','renown','xp','xpSpent',
'notes','rp'
];
for (const key of flatFields) {
if (Object.prototype.hasOwnProperty.call(updateData, key)) {
mergedData.tabInfo[key] = updateData[key];
}
}
const updated = playerHelpers.update(name, mergedData);
@@ -185,7 +196,7 @@ router.put('/:name', requireSession, async (req, res) => {
logToFile('API: Updated player', name);
res.json(updatedPlayer);
} catch (error) {
logToFile('API: Failed to update player', req.params.name, error);
logToFile('API: Failed to update player', req.params.name, error && error.stack ? error.stack : error);
res.status(500).json({ error: 'Failed to update player' });
}
});
@@ -209,7 +220,7 @@ router.delete('/:name', requireSession, async (req, res) => {
}
});
// Login endpoint
// Login endpoint - create a server session so x-session-id can be used
router.post('/login', async (req, res) => {
try {
const { name, password } = req.body;
@@ -223,21 +234,22 @@ router.post('/login', async (req, res) => {
return res.status(401).json({ error: 'Invalid credentials' });
}
// Check password
const bcrypt = require('bcrypt');
const isValidPassword = await bcrypt.compare(password, player.pwHash);
// Check password using safeCompare
const isValidPassword = await safeCompare(password, player.pwHash);
if (!isValidPassword) {
return res.status(401).json({ error: 'Invalid credentials' });
}
// Create session (you might want to implement proper session management)
// Create session and store it in sessions table
const sessionId = require('crypto').randomBytes(32).toString('hex');
logToFile('API: Player login', name);
const expiresAt = new Date(Date.now() + 1000 * 60 * 60 * 24).toISOString(); // 24h
sessionHelpers.create(sessionId, { playerName: player.name }, expiresAt);
logToFile('API: Player login', name, sessionId);
res.json({
message: 'Login successful',
sessionId,
expiresAt,
player: {
name: player.name,
rollerInfo: player.rollerInfo,
@@ -246,7 +258,7 @@ router.post('/login', async (req, res) => {
}
});
} catch (error) {
logToFile('API: Login failed', req.body.name, error);
logToFile('API: Login failed', req.body.name, error && error.stack ? error.stack : error);
res.status(500).json({ error: 'Login failed' });
}
});

View File

@@ -2,6 +2,17 @@ const Database = require('better-sqlite3');
const path = require('path');
const fs = require('fs');
// Simple DB logger to backend.log
const backendLogPath = path.join(__dirname, 'backend.log');
function logToFile(...args) {
try {
const msg = `[${new Date().toISOString()}] ` + args.map(a => (typeof a === 'object' ? JSON.stringify(a) : String(a))).join(' ') + '\n';
fs.appendFileSync(backendLogPath, msg, { encoding: 'utf8' });
} catch (err) {
console.error('Failed to write backend log', err);
}
}
// Create database directory if it doesn't exist
const dbDir = path.join(__dirname, 'sqlite');
if (!fs.existsSync(dbDir)) {
@@ -90,8 +101,9 @@ const statements = {
// Helper functions
const playerHelpers = {
getAll: () => {
logToFile('DB: getAllPlayers - start');
const rows = statements.getAllPlayers.all();
return rows.map(row => ({
const result = rows.map(row => ({
name: row.name,
rollerInfo: JSON.parse(row.roller_info || '{}'),
shopInfo: JSON.parse(row.shop_info || '{}'),
@@ -102,12 +114,18 @@ const playerHelpers = {
createdAt: row.created_at,
updatedAt: row.updated_at
}));
logToFile('DB: getAllPlayers - resultCount', result.length);
return result;
},
getByName: (name) => {
logToFile('DB: getPlayerByName - start', name);
const row = statements.getPlayerByName.get(name);
if (!row) return null;
return {
if (!row) {
logToFile('DB: getPlayerByName - not found', name);
return null;
}
const result = {
name: row.name,
rollerInfo: JSON.parse(row.roller_info || '{}'),
shopInfo: JSON.parse(row.shop_info || '{}'),
@@ -118,9 +136,12 @@ const playerHelpers = {
createdAt: row.created_at,
updatedAt: row.updated_at
};
logToFile('DB: getPlayerByName - found', name);
return result;
},
create: (playerData) => {
logToFile('DB: createPlayer - start', playerData.name);
const result = statements.insertPlayer.run(
playerData.name,
JSON.stringify(playerData.rollerInfo || {}),
@@ -129,10 +150,13 @@ const playerHelpers = {
playerData.pw || '',
playerData.pwHash || ''
);
return { ...playerData, _id: result.lastInsertRowid };
const out = { ...playerData, _id: result.lastInsertRowid };
logToFile('DB: createPlayer - done', playerData.name, 'rowid', result.lastInsertRowid);
return out;
},
update: (name, playerData) => {
logToFile('DB: updatePlayer - start', name);
const result = statements.updatePlayer.run(
JSON.stringify(playerData.rollerInfo || {}),
JSON.stringify(playerData.shopInfo || {}),
@@ -141,42 +165,59 @@ const playerHelpers = {
playerData.pwHash || '',
name
);
logToFile('DB: updatePlayer - changes', result.changes, name);
return result.changes > 0;
},
delete: (name) => {
logToFile('DB: deletePlayer - start', name);
const result = statements.deletePlayer.run(name);
logToFile('DB: deletePlayer - changes', result.changes, name);
return result.changes > 0;
}
};
const sessionHelpers = {
get: (sessionId) => {
logToFile('DB: getSession - start', sessionId);
const row = statements.getSession.get(sessionId);
if (!row) return null;
return {
if (!row) {
logToFile('DB: getSession - not found', sessionId);
return null;
}
const out = {
sessionId: row.session_id,
data: JSON.parse(row.data || '{}'),
expiresAt: row.expires_at
};
logToFile('DB: getSession - ok', sessionId);
return out;
},
create: (sessionId, data, expiresAt) => {
statements.insertSession.run(sessionId, JSON.stringify(data), expiresAt);
logToFile('DB: createSession - start', sessionId, 'expiresAt', expiresAt);
const res = statements.insertSession.run(sessionId, JSON.stringify(data), expiresAt);
logToFile('DB: createSession - done', sessionId);
},
update: (sessionId, data, expiresAt) => {
logToFile('DB: updateSession - start', sessionId);
const result = statements.updateSession.run(JSON.stringify(data), expiresAt, sessionId);
logToFile('DB: updateSession - changes', result.changes, sessionId);
return result.changes > 0;
},
delete: (sessionId) => {
logToFile('DB: deleteSession - start', sessionId);
const result = statements.deleteSession.run(sessionId);
logToFile('DB: deleteSession - changes', result.changes, sessionId);
return result.changes > 0;
},
cleanExpired: () => {
logToFile('DB: cleanExpiredSessions - start');
const result = statements.cleanExpiredSessions.run();
logToFile('DB: cleanExpiredSessions - removed', result.changes);
return result.changes;
}
};
@@ -186,5 +227,6 @@ module.exports = {
statements,
playerHelpers,
sessionHelpers,
close: () => db.close()
close: () => db.close(),
logToFile
};

Binary file not shown.

Binary file not shown.

Binary file not shown.