Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check for opaqueId before decode #6744

Merged
merged 12 commits into from
May 23, 2023
5 changes: 3 additions & 2 deletions packages/api-plugin-products/src/resolvers/Query/product.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import isOpaqueId from "@reactioncommerce/api-utils/isOpaqueId.js";
import { decodeProductOpaqueId, decodeShopOpaqueId } from "../../xforms/id.js";

/**
Expand All @@ -18,8 +19,8 @@ export default async function product(_, args, context) {
shopId: opaqueShopId
} = args;

const productId = decodeProductOpaqueId(opaqueProductId);
const shopId = decodeShopOpaqueId(opaqueShopId);
const productId = isOpaqueId(opaqueProductId) ? decodeProductOpaqueId(opaqueProductId) : opaqueProductId;
const shopId = isOpaqueId(opaqueShopId) ? decodeShopOpaqueId(opaqueShopId) : opaqueShopId;

return context.queries.product(context, {
productId,
Expand Down
8 changes: 5 additions & 3 deletions packages/api-plugin-products/src/resolvers/Query/products.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import getPaginatedResponse from "@reactioncommerce/api-utils/graphql/getPaginatedResponse.js";
import wasFieldRequested from "@reactioncommerce/api-utils/graphql/wasFieldRequested.js";
import isOpaqueId from "@reactioncommerce/api-utils/isOpaqueId.js";
import { decodeProductOpaqueId, decodeShopOpaqueId, decodeTagOpaqueId } from "../../xforms/id.js";

/**
Expand Down Expand Up @@ -32,9 +33,10 @@ export default async function products(_, args, context, info) {
...connectionArgs
} = args;

const shopIds = opaqueShopIds.map(decodeShopOpaqueId);
const productIds = opaqueProductIds && opaqueProductIds.map(decodeProductOpaqueId);
const tagIds = opaqueTagIds && opaqueTagIds.map(decodeTagOpaqueId);
const shopIds = opaqueShopIds.map((opaqueShopId) => (isOpaqueId(opaqueShopId) ? decodeShopOpaqueId(opaqueShopId) : opaqueShopId));
const productIds = opaqueProductIds &&
opaqueProductIds.map((opaqueProductId) => (isOpaqueId(opaqueProductId) ? decodeProductOpaqueId(opaqueProductId) : opaqueProductId));
const tagIds = opaqueTagIds && opaqueTagIds.map((opaqueTagId) => (isOpaqueId(opaqueTagId) ? decodeTagOpaqueId(opaqueTagId) : opaqueTagId));

const query = await context.queries.products(context, {
createdAt,
Expand Down
22 changes: 22 additions & 0 deletions packages/api-utils/lib/isOpaqueId.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @name isOpaqueId
* @method
* @memberof GraphQL/Transforms
* @summary Checks if the given ID is an opaque ID
* @param {String} inputId The ID to check
* @returns {Boolean} True if the ID is an opaque ID
*/
export default function isOpaqueId(inputId) {
if (inputId === undefined || inputId === null) return null;

const [namespace, id] = Buffer
.from(inputId, "base64")
.toString("utf8")
.split(":", 2);

if (namespace && namespace.startsWith("reaction/") && id) {
return true;
}

return false;
}
11 changes: 11 additions & 0 deletions packages/api-utils/lib/isOpaqueId.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import isOpaqueId from "./isOpaqueId.js";

test("returns true for opaqueId", () => {
const encodedId = "cmVhY3Rpb24vc2hvcDpieTV3cGRnM25NcThnWDU0Yw==";
expect(isOpaqueId(encodedId)).toEqual(true);
});

test("returns false for internal id", () => {
const id = "by5wpdg3nMq8gX54c";
expect(isOpaqueId(id)).toEqual(false);
});