11import clientPromise from "@/utils/mongo.js" ;
22import { requireUser } from "@/middleware/authenticate" ;
3+ import { ensureSafeUserId , coerceNumberField , coerceStringField } from "@/utils/securityValidators.js" ;
34
45export default async function handler ( req , res ) {
56 if ( req . method !== "POST" ) {
@@ -21,26 +22,46 @@ export default async function handler( req, res ) {
2122 const client = await clientPromise ;
2223 const db = client . db ( "cardPriceApp" ) ;
2324 const collection = db . collection ( "myCollection" ) ;
25+ const safeUserId = ensureSafeUserId ( auth . decoded . username ) ;
2426
25- const sanitizedCards = cards
26- . filter ( ( card ) => card && typeof card === "object" )
27- . map ( ( card ) => {
28- const rawCardId = card ?. cardId ;
29- const normalizedCardId =
30- rawCardId === null || rawCardId === undefined ? null : String ( rawCardId ) ;
31- return {
32- ...card ,
33- cardId : normalizedCardId ,
27+ const sanitizedCards = [ ] ;
28+
29+ for ( const card of cards ) {
30+ if ( ! card || typeof card !== "object" ) {
31+ continue ;
32+ }
33+
34+ try {
35+ const sanitizedCard = {
36+ productName : coerceStringField ( card . productName , { maxLength : 256 } ) ,
37+ setName : coerceStringField ( card . setName , { maxLength : 256 } ) ,
38+ number : coerceStringField ( card . number ?? "" , { maxLength : 128 , allowEmpty : true } ) ,
39+ printing : coerceStringField ( card . printing ?? "" , { maxLength : 128 , allowEmpty : true } ) ,
40+ rarity : coerceStringField ( card . rarity ?? "" , { maxLength : 128 , allowEmpty : true } ) ,
41+ condition : coerceStringField ( card . condition ?? "" , { maxLength : 128 , allowEmpty : true } ) ,
42+ marketPrice : coerceNumberField ( card . marketPrice ?? 0 ) ,
43+ lowPrice : coerceNumberField ( card . lowPrice ?? 0 ) ,
44+ quantity : coerceNumberField ( card . quantity ?? 1 , { min : 0 } ) ,
45+ cardId :
46+ card . cardId === null || card . cardId === undefined
47+ ? null
48+ : coerceStringField ( card . cardId , { maxLength : 128 } ) ,
3449 } ;
35- } ) ;
50+
51+ sanitizedCards . push ( sanitizedCard ) ;
52+ } catch ( error ) {
53+ console . warn ( "Skipping invalid card payload:" , error ?. message ?? error ) ;
54+ }
55+ }
56+
3657 if ( sanitizedCards . length === 0 ) {
3758 return res . status ( 400 ) . json ( { error : "No valid card data provided." } ) ;
3859 }
3960
4061 const bulkOps = sanitizedCards . map ( ( card ) => ( {
4162 updateOne : {
4263 filter : {
43- userId : auth . decoded . username ,
64+ userId : safeUserId ,
4465 productName : card . productName ,
4566 setName : card . setName ,
4667 number : card . number ,
@@ -49,15 +70,15 @@ export default async function handler( req, res ) {
4970 condition : card . condition
5071 } ,
5172 update : {
52- $inc : { quantity : card . quantity || 1 } ,
73+ $inc : { quantity : card . quantity } ,
5374 $set : {
5475 oldPrice : null ,
5576 cardId : card . cardId || null ,
5677 } ,
5778 $setOnInsert : {
5879 marketPrice : card . marketPrice || 0 ,
5980 lowPrice : card . lowPrice || 0 ,
60- userId : auth . decoded . username
81+ userId : safeUserId
6182 }
6283 } ,
6384 upsert : true
0 commit comments