fix(adminGames): apply Steam URL normalization and scraper guard to create/update

Admin create had no URL handling at all (and crashed on missing steamId
via .length), and admin update passed req.body straight to the scraper.
Reuse normalizeSteamId in both, 400 on unrecognized input, and reject
failed scrapes (non-object / missing title+frontImage) before
Game.create/findOneAndUpdate so failures report as 'Steam lookup failed'
instead of schema validation noise.
This commit is contained in:
2026-09-06 10:11:07 -04:00
parent 964415198a
commit 505252dbf0
+39 -2
View File
@@ -2,6 +2,7 @@ import Game from '../models/Game.js'
import steamScraper from '../scripts/scraper.js' import steamScraper from '../scripts/scraper.js'
import asyncHandler from '../middleware/async.js' import asyncHandler from '../middleware/async.js'
import ErrorResponse from '../utils/errorResponse.js' import ErrorResponse from '../utils/errorResponse.js'
import normalizeSteamId from '../utils/normalizeSteamId.js'
const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$') const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$')
const checkForTwelveRegExp = new RegExp('^[0-9a-fA-F]{12}$') const checkForTwelveRegExp = new RegExp('^[0-9a-fA-F]{12}$')
@@ -41,8 +42,17 @@ export const show = asyncHandler(async (req, res, next) => {
*/ */
export const create = asyncHandler(async (req, res, next) => { export const create = asyncHandler(async (req, res, next) => {
let oldGame let oldGame
req.body.steamId.length > 0 const steamId = normalizeSteamId(req.body.steamId)
? (oldGame = await Game.findOne({ steamId: req.body.steamId })) if (steamId === null)
return next(
new ErrorResponse(
'Enter a Steam app ID or a store.steampowered.com URL.',
400,
)
)
req.body.steamId = steamId
steamId.length > 0
? (oldGame = await Game.findOne({ steamId }))
: (oldGame = await Game.findOne({ title: req.body.title })) : (oldGame = await Game.findOne({ title: req.body.title }))
if (oldGame) if (oldGame)
@@ -56,6 +66,14 @@ export const create = asyncHandler(async (req, res, next) => {
const data = const data =
req.body.scrape === true ? await steamScraper(req.body) : req.body req.body.scrape === true ? await steamScraper(req.body) : req.body
if (
req.body.scrape === true &&
(!data || typeof data !== 'object' || !data.title || !data.frontImage)
)
return next(
new ErrorResponse('Steam lookup failed for that ID/URL.', 400)
)
if (req.body.scrape === false) { if (req.body.scrape === false) {
if (req.body.shortDesc && isValid(req.body.shortDesc)) req.body.shortDesc = decode(req.body.shortDesc) if (req.body.shortDesc && isValid(req.body.shortDesc)) req.body.shortDesc = decode(req.body.shortDesc)
if (req.body.reviews && isValid(req.body.reviews)) req.body.reviews = decode(req.body.reviews) if (req.body.reviews && isValid(req.body.reviews)) req.body.reviews = decode(req.body.reviews)
@@ -96,6 +114,17 @@ export const update = asyncHandler(async (req, res, next) => {
req.body.lastModifiedBy = req.user.id req.body.lastModifiedBy = req.user.id
if (req.body.steamId !== undefined) {
const normalizedSteamId = normalizeSteamId(req.body.steamId)
if (normalizedSteamId === null)
return next(
new ErrorResponse(
'Enter a Steam app ID or a store.steampowered.com URL.',
400,
)
)
req.body.steamId = normalizedSteamId
}
if (req.body.shortDesc && isValid(req.body.shortDesc)) req.body.shortDesc = decode(req.body.shortDesc) if (req.body.shortDesc && isValid(req.body.shortDesc)) req.body.shortDesc = decode(req.body.shortDesc)
if (req.body.reviews && isValid(req.body.reviews)) req.body.reviews = decode(req.body.reviews) if (req.body.reviews && isValid(req.body.reviews)) req.body.reviews = decode(req.body.reviews)
if (req.body.summary && isValid(req.body.summary)) req.body.summary = decode(req.body.summary) if (req.body.summary && isValid(req.body.summary)) req.body.summary = decode(req.body.summary)
@@ -109,6 +138,14 @@ export const update = asyncHandler(async (req, res, next) => {
const data = const data =
req.body.scrape === true ? await steamScraper(req.body) : req.body req.body.scrape === true ? await steamScraper(req.body) : req.body
if (
req.body.scrape === true &&
(!data || typeof data !== 'object' || !data.title || !data.frontImage)
)
return next(
new ErrorResponse('Steam lookup failed for that ID/URL.', 400)
)
game = await Game.findOneAndUpdate({ [gameId]: id }, data, { game = await Game.findOneAndUpdate({ [gameId]: id }, data, {
new: true, new: true,
runValidators: true, runValidators: true,