fix: inconsistent handling of purchase request #594

Merged
Sainan merged 1 commits from purchase-consistency into main 2024-12-21 20:40:38 -08:00
2 changed files with 3 additions and 41 deletions

View File

@ -1,11 +1,11 @@
import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { toPurchaseRequest } from "@/src/helpers/purchaseHelpers";
import { IPurchaseRequest } from "@/src/types/purchaseTypes";
import { handlePurchase } from "@/src/services/purchaseService";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const purchaseController: RequestHandler = async (req, res) => {
const purchaseRequest = toPurchaseRequest(JSON.parse(String(req.body)));
const purchaseRequest = JSON.parse(String(req.body)) as IPurchaseRequest;
const accountId = await getAccountIdForRequest(req);
const response = await handlePurchase(purchaseRequest, accountId);
coderabbitai[bot] commented 2024-12-21 18:01:02 -08:00 (Migrated from github.com)
Review

🛠️ Refactor suggestion

Revisit validation with direct type assertion.
Casting to IPurchaseRequest bypasses structured validation, which the older helper performed. While this simplifies code, it also risks letting malformed data through. Consider reintroducing minimal validation checks (e.g., presence of required fields) to mitigate potential runtime errors down the line.

_:hammer_and_wrench: Refactor suggestion_ **Revisit validation with direct type assertion.** Casting to IPurchaseRequest bypasses structured validation, which the older helper performed. While this simplifies code, it also risks letting malformed data through. Consider reintroducing minimal validation checks (e.g., presence of required fields) to mitigate potential runtime errors down the line. <!-- This is an auto-generated comment by CodeRabbit -->
res.json(response);

View File

@ -1,43 +1,5 @@
import { parseBoolean, parseNumber, parseString } from "@/src/helpers/general";
import { slotPurchaseNameToSlotName } from "@/src/services/purchaseService";
import { IPurchaseRequest, SlotPurchaseName } from "@/src/types/purchaseTypes";
export const toPurchaseRequest = (purchaseRequest: unknown): IPurchaseRequest => {
if (!purchaseRequest || typeof purchaseRequest !== "object") {
throw new Error("incorrect or missing purchase request data");
}
if (
"PurchaseParams" in purchaseRequest &&
"buildLabel" in purchaseRequest &&
purchaseRequest.PurchaseParams &&
typeof purchaseRequest.PurchaseParams === "object" &&
"Source" in purchaseRequest.PurchaseParams &&
"StoreItem" in purchaseRequest.PurchaseParams &&
"StorePage" in purchaseRequest.PurchaseParams &&
"SearchTerm" in purchaseRequest.PurchaseParams &&
"CurrentLocation" in purchaseRequest.PurchaseParams &&
"Quantity" in purchaseRequest.PurchaseParams &&
"UsePremium" in purchaseRequest.PurchaseParams &&
"ExpectedPrice" in purchaseRequest.PurchaseParams
) {
return {
PurchaseParams: {
Source: parseNumber(purchaseRequest.PurchaseParams.Source),
StoreItem: parseString(purchaseRequest.PurchaseParams.StoreItem),
StorePage: parseString(purchaseRequest.PurchaseParams.StorePage),
SearchTerm: parseString(purchaseRequest.PurchaseParams.SearchTerm),
CurrentLocation: parseString(purchaseRequest.PurchaseParams.CurrentLocation),
Quantity: parseNumber(purchaseRequest.PurchaseParams.Quantity),
UsePremium: parseBoolean(purchaseRequest.PurchaseParams.UsePremium),
ExpectedPrice: parseNumber(purchaseRequest.PurchaseParams.ExpectedPrice)
},
buildLabel: parseString(purchaseRequest.buildLabel)
};
}
throw new Error("invalid purchaseRequest");
};
import { SlotPurchaseName } from "@/src/types/purchaseTypes";
export const isSlotPurchaseName = (slotPurchaseName: string): slotPurchaseName is SlotPurchaseName => {
return slotPurchaseName in slotPurchaseNameToSlotName;