From bfad2a39c1ac8fbafb43b5ed9b44b4b63ccaae5f Mon Sep 17 00:00:00 2001 From: azures04 Date: Mon, 5 Jan 2026 05:06:06 +0100 Subject: [PATCH] Add player action logging for admin operations Introduces a new addPlayerAction method in adminRepository and logPlayerAction in adminService to record admin actions on player accounts. Updates relevant admin routes to log actions such as bans, unbans, forced name changes, and skin resets. Also improves error messages in adminService for consistency and clarity. --- repositories/adminRepository.js | 18 ++++++++++++++++++ routes/admin/ban/index.js | 16 +++++++++++----- routes/admin/players/textures.js | 1 + routes/admin/players/username.js | 1 + services/adminService.js | 18 ++++++++++++------ 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/repositories/adminRepository.js b/repositories/adminRepository.js index 7f2891b..ed0d1ca 100644 --- a/repositories/adminRepository.js +++ b/repositories/adminRepository.js @@ -119,10 +119,28 @@ async function getAdminByUsername(username) { } } +async function addPlayerAction(playerUuid, actionCode) { + try { + const cleanUuid = playerUuid.replace(/-/g, "") + const sql = "INSERT IGNORE INTO playerProfileActions (uuid, action) VALUES (?, ?)" + const result = await database.query(sql, [cleanUuid, actionCode]) + + return { + code: 200, + success: result.affectedRows > 0, + message: result.affectedRows > 0 ? "Action taken." : "Action already taken." + } + } catch (error) { + logger.log("Internal Server Error".bold + " : " + error.toString(), ["MariaDB", "yellow"]) + throw new DefaultError(500, "Internal Server Error", "Database Error") + } +} + module.exports = { createAdmin, getAdminById, hasPermission, + addPlayerAction, assignPermission, revokePermission, getAdminByUsername, diff --git a/routes/admin/ban/index.js b/routes/admin/ban/index.js index 7ffaa39..e5e1930 100644 --- a/routes/admin/ban/index.js +++ b/routes/admin/ban/index.js @@ -4,28 +4,34 @@ const userService = require("../../../services/userService") const adminService = require("../../../services/adminService") router.get("/:uuid", adminService.hasPermission("PLAYER_BAN_STATUS"), async (req, res) => { - const banStatus = await userService.getPlayerBanStatus(req.params.uuid) + const { uuid } = req.params + const banStatus = await userService.getPlayerBanStatus(uuid) return res.status(200).json(banStatus) }) router.get("/:uuid/actions", adminService.hasPermission("PLAYER_ACTIONS_LIST"), async (req, res) => { - const playerActions = await userService.getPlayerActions(req.params.uuid) + const { uuid } = req.params + const playerActions = await userService.getPlayerActions(uuid) return res.status(200).json(playerActions) }) router.get("/:uuid/history", adminService.hasPermission("PLAYER_BAN_HISTORY"), async (req, res) => { - const banHistory = await userService.getPlayerBans(req.params.uuid) + const { uuid } = req.params + const banHistory = await userService.getPlayerBans(uuid) return res.status(200).json(banHistory) }) router.put("/:uuid", adminService.hasPermission("PLAYER_BAN"), async (req, res) => { const { reasonKey, reasonMessage, expires } = req.body - const ban = await userService.banUser(req.params.uuid, { reasonKey, reasonMessage, expires }) + const ban = await userService.banUser(uuid, { reasonKey, reasonMessage, expires }) + await adminService.logPlayerAction("BAN") return res.status(200).json(ban) }) router.delete("/:uuid", adminService.hasPermission("PLAYER_UNBAN"), async (req, res) => { - const ban = await userService.unbanUser(req.params.uuid) + const { uuid } = req.params + const ban = await userService.unbanUser(uuid) + await adminService.logPlayerAction("UNBAN") return res.status(200).json(ban) }) diff --git a/routes/admin/players/textures.js b/routes/admin/players/textures.js index cb2e926..ca27d3e 100644 --- a/routes/admin/players/textures.js +++ b/routes/admin/players/textures.js @@ -5,6 +5,7 @@ const adminService = require("../../../services/adminService") router.delete("/skin/:uuid", adminService.hasPermission("RESET_PLAYER_SKIN"), async (req, res) => { const result = await userService.resetSkin(req.params.uuid) + await adminService.logPlayerAction("USING_BANNED_SKIN") return res.status(200).json(result) }) diff --git a/routes/admin/players/username.js b/routes/admin/players/username.js index 809ed26..c676d4d 100644 --- a/routes/admin/players/username.js +++ b/routes/admin/players/username.js @@ -6,6 +6,7 @@ const adminService = require("../../../services/adminService") router.patch("/:uuid", adminService.hasPermission("CHANGE_PLAYER_USERNAME"), async (req, res) => { const { newUsername } = req.body const result = await userService.changeUsername(req.params.uuid, newUsername) + await adminService.logPlayerAction("FORCED_NAME_CHANGE") return res.status(200).json(result) }) diff --git a/services/adminService.js b/services/adminService.js index 3f6f369..fbf6237 100644 --- a/services/adminService.js +++ b/services/adminService.js @@ -85,7 +85,7 @@ function hasPermission(requiredPermission) { try { const authHeader = req.headers.authorization if (!authHeader || !authHeader.startsWith("Bearer ")) { - throw new DefaultError(401, "Authentification admin requise.") + throw new DefaultError(401, "Admin auth required.") } const token = authHeader.split(" ")[1] @@ -117,29 +117,35 @@ async function uploadCape(fileObject, alias = null) { const hash = crypto.createHash("sha256").update(buffer).digest("hex") const existing = await userRepository.getTextureByHash(hash) - if (existing) throw new DefaultError(409, "Cette cape existe déjà.") + if (existing) throw new DefaultError(409, "Cape already existing.") const textureUrl = `/texture/${hash}` - await userRepository.createTexture(crypto.randomUUID(), hash, 'CAPE', textureUrl, alias) + await userRepository.createTexture(crypto.randomUUID(), hash, "CAPE", textureUrl, alias) return { hash, url: textureUrl } } async function deleteGlobalCape(hash) { const success = await userRepository.deleteTexture(hash) - if (!success) throw new DefaultError(404, "Cape introuvable.") + if (!success) throw new DefaultError(404, "Cape not found.") - return { message: "Texture supprimée globalement." } + return { message: "Texture removed." } +} + +async function logPlayerAction(playerUuid, actionCode) { + return await adminRepository.addPlayerAction(playerUuid, actionCode) } module.exports = { loginAdmin, uploadCape, registerAdmin, + hasPermission, getAdminProfile, grantPermission, revokePermission, checkAdminAccess, + deleteGlobalCape, + logPlayerAction, changeAdminPassword, - hasPermission, } \ No newline at end of file