From e08c0c973617b5eac82d0db8b0b3d8a3b6a6501b Mon Sep 17 00:00:00 2001 From: wtclaude Date: Wed, 22 Jul 2026 13:01:12 -0500 Subject: [PATCH] fix(admin): restore digit match in discordId route validation The `:discordId` param validator on the five admin moderation routes used `/^d{1,32}$/`, which matches 1-32 literal `d` characters instead of digits. A real numeric Discord snowflake failed validation, so every `/moderation/user/:discordId*` endpoint returned a 400 for valid input. The backslash was dropped in a prior code-smell cleanup (12d50fd) that intended `[0-9]` -> `\d`. Restore `\d` so the regex matches digits again. Co-Authored-By: Claude --- server/src/router/v1/admin/admin.routes.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/src/router/v1/admin/admin.routes.js b/server/src/router/v1/admin/admin.routes.js index 276cc55..161fe95 100644 --- a/server/src/router/v1/admin/admin.routes.js +++ b/server/src/router/v1/admin/admin.routes.js @@ -1113,7 +1113,7 @@ adminRouter.get( // #swagger.tags = ['Admin · Moderation'] // #swagger.summary = 'Per-user moderation summary (counts, latest tag, linked account)' // #swagger.security = [{ "cookieAuth": [] }, { "bearerAuth": [] }] - param('discordId').matches(/^d{1,32}$/), + param('discordId').matches(/^\d{1,32}$/), validate, moderation.getUser, ) @@ -1122,7 +1122,7 @@ adminRouter.get( // #swagger.tags = ['Admin · Moderation'] // #swagger.summary = 'Full moderation action history for a user' // #swagger.security = [{ "cookieAuth": [] }, { "bearerAuth": [] }] - param('discordId').matches(/^d{1,32}$/), + param('discordId').matches(/^\d{1,32}$/), validate, moderation.getUserActions, ) @@ -1131,7 +1131,7 @@ adminRouter.get( // #swagger.tags = ['Admin · Moderation'] // #swagger.summary = 'Staff notes for a user (admin_only notes hidden from moderators)' // #swagger.security = [{ "cookieAuth": [] }, { "bearerAuth": [] }] - param('discordId').matches(/^d{1,32}$/), + param('discordId').matches(/^\d{1,32}$/), validate, moderation.getUserNotes, ) @@ -1140,7 +1140,7 @@ adminRouter.post( // #swagger.tags = ['Admin · Moderation'] // #swagger.summary = 'Add a staff note (admin_only visibility requires the admin role)' // #swagger.security = [{ "cookieAuth": [] }, { "bearerAuth": [] }] - param('discordId').matches(/^d{1,32}$/), + param('discordId').matches(/^\d{1,32}$/), body('body').isString().trim().isLength({ min: 1, max: 4000 }), body('visibility').optional().isIn(['staff_only', 'admin_only']), validate, @@ -1209,7 +1209,7 @@ adminRouter.get( // #swagger.security = [{ "cookieAuth": [] }, { "bearerAuth": [] }] // #swagger.parameters['discordId'] = { in: 'path', required: true, schema: { type: 'string' }, description: 'Discord snowflake.' } /* #swagger.responses[200] = { description: 'Appeals for the user', content: { "application/json": { schema: { type: "array", items: { $ref: "#/components/schemas/AppealQueueItem" } } } } } */ - param('discordId').matches(/^d{1,32}$/), + param('discordId').matches(/^\d{1,32}$/), validate, moderation.getUserAppeals, )