diff --git a/integration-tests/http/__tests__/cart/store/cart.spec.ts b/integration-tests/http/__tests__/cart/store/cart.spec.ts index 8b37d7461d..8f244080f7 100644 --- a/integration-tests/http/__tests__/cart/store/cart.spec.ts +++ b/integration-tests/http/__tests__/cart/store/cart.spec.ts @@ -1,4 +1,3 @@ -import { medusaIntegrationTestRunner } from "@medusajs/test-utils" import { Modules, PriceListStatus, @@ -7,19 +6,39 @@ import { PromotionRuleOperator, PromotionType, } from "@medusajs/utils" +import { medusaIntegrationTestRunner } from "@medusajs/test-utils" import { createAdminUser, generatePublishableKey, generateStoreHeaders, } from "../../../../helpers/create-admin-user" import { setupTaxStructure } from "../../../../modules/__tests__/fixtures" -import { createAuthenticatedCustomer } from "../../../../modules/helpers/create-authenticated-customer" jest.setTimeout(100000) const env = { MEDUSA_FF_MEDUSA_V2: true } const adminHeaders = { headers: { "x-medusa-access-token": "test_token" } } +const generateStoreHeadersWithCustomer = async ({ + api, + storeHeaders, + customer, +}) => { + const registeredCustomerToken = ( + await api.post("/auth/customer/emailpass/register", { + email: customer.email, + password: "password", + }) + ).data.token + + return { + headers: { + ...storeHeaders.headers, + authorization: `Bearer ${registeredCustomerToken}`, + }, + } +} + const shippingAddressData = { address_1: "test address 1", address_2: "test address 2", @@ -117,19 +136,22 @@ medusaIntegrationTestRunner({ const publishableKey = await generatePublishableKey(appContainer) storeHeaders = generateStoreHeaders({ publishableKey }) - const result = await createAuthenticatedCustomer(appContainer, { - first_name: "tony", - last_name: "stark", - email: "tony@stark-industries.com", - }) + customer = ( + await api.post( + "/admin/customers", + { + first_name: "tony", + email: "tony@stark-industries.com", + }, + adminHeaders + ) + ).data.customer - customer = result.customer - storeHeadersWithCustomer = { - headers: { - ...storeHeaders.headers, - authorization: `Bearer ${result.jwt}`, - }, - } + storeHeadersWithCustomer = await generateStoreHeadersWithCustomer({ + storeHeaders, + api, + customer, + }) await setupTaxStructure(appContainer.resolve(Modules.TAX)) @@ -557,23 +579,23 @@ medusaIntegrationTestRunner({ }) describe("POST /store/carts/:id", () => { - let otherRegion, cartWithCustomer + let otherRegion beforeEach(async () => { - const cartData = { - currency_code: "usd", - sales_channel_id: salesChannel.id, - region_id: region.id, - shipping_address: shippingAddressData, - items: [{ variant_id: product.variants[0].id, quantity: 1 }], - promo_codes: [promotion.code], - } - - cart = (await api.post(`/store/carts`, cartData, storeHeaders)).data - .cart - - cartWithCustomer = ( - await api.post(`/store/carts`, cartData, storeHeadersWithCustomer) + cart = ( + await api.post( + `/store/carts`, + { + email: "tony@stark.com", + currency_code: "usd", + sales_channel_id: salesChannel.id, + region_id: region.id, + shipping_address: shippingAddressData, + items: [{ variant_id: product.variants[0].id, quantity: 1 }], + promo_codes: [promotion.code], + }, + storeHeadersWithCustomer + ) ).data.cart otherRegion = ( @@ -729,7 +751,7 @@ medusaIntegrationTestRunner({ it("should not generate tax lines if automatic taxes is false", async () => { let updated = await api.post( `/store/carts/${cart.id}`, - {}, + { email: "another@tax.com" }, storeHeaders ) @@ -754,7 +776,7 @@ medusaIntegrationTestRunner({ updated = await api.post( `/store/carts/${cart.id}`, - { region_id: noAutomaticRegion.id }, + { email: "another@tax.com", region_id: noAutomaticRegion.id }, storeHeaders ) @@ -1214,103 +1236,6 @@ medusaIntegrationTestRunner({ }) ) }) - - it("should update email if cart customer_id is not set", async () => { - const updated = await api.post( - `/store/carts/${cart.id}`, - { email: "tony@stark.com" }, - storeHeaders - ) - - expect(updated.status).toEqual(200) - expect(updated.data.cart).toEqual( - expect.objectContaining({ - email: "tony@stark.com", - customer: expect.objectContaining({ - email: "tony@stark.com", - }), - }) - ) - }) - - it("should update customer_id if cart customer_id if not already set", async () => { - const updated = await api.post( - `/store/carts/${cart.id}`, - { customer_id: customer.id }, - storeHeadersWithCustomer - ) - - expect(updated.status).toEqual(200) - expect(updated.data.cart).toEqual( - expect.objectContaining({ - email: customer.email, - customer: expect.objectContaining({ - id: customer.id, - email: customer.email, - }), - }) - ) - }) - - it("should throw when trying to set customer_id if customer is not logged in", async () => { - const { response } = await api - .post( - `/store/carts/${cartWithCustomer.id}`, - { customer_id: customer.id }, - storeHeaders - ) - .catch((e) => e) - - expect(response.status).toEqual(400) - expect(response.data.message).toEqual( - "auth_customer_id is required when customer_id is set" - ) - }) - - it("should throw when trying to set customer_id if customer_id is already set", async () => { - const newCustomer = ( - await api.post( - "/admin/customers", - { - first_name: "new tony", - email: "new-tony@stark-industries.com", - }, - adminHeaders - ) - ).data.customer - - const { response } = await api - .post( - `/store/carts/${cartWithCustomer.id}`, - { customer_id: newCustomer.id }, - storeHeadersWithCustomer - ) - .catch((e) => e) - - expect(response.status).toEqual(400) - expect(response.data.message).toEqual( - "Cannot update cart customer when customer_id is set" - ) - }) - - it("should update email when email is already set and customer is logged in", async () => { - const updated = await api.post( - `/store/carts/${cart.id}`, - { customer_id: customer.id }, - storeHeadersWithCustomer - ) - - expect(updated.status).toEqual(200) - expect(updated.data.cart).toEqual( - expect.objectContaining({ - email: customer.email, - customer: expect.objectContaining({ - id: customer.id, - email: customer.email, - }), - }) - ) - }) }) }) }, diff --git a/integration-tests/modules/helpers/create-authenticated-customer.ts b/integration-tests/modules/helpers/create-authenticated-customer.ts index eb1f7ed55b..bbf1c40f2d 100644 --- a/integration-tests/modules/helpers/create-authenticated-customer.ts +++ b/integration-tests/modules/helpers/create-authenticated-customer.ts @@ -36,7 +36,7 @@ export const createAuthenticatedCustomer = async ( actor_type: "customer", auth_identity_id: authIdentity.id, }, - http.jwtSecret! + http.jwtSecret ) return { customer, authIdentity, jwt: token } diff --git a/packages/core/core-flows/src/cart/workflows/index.ts b/packages/core/core-flows/src/cart/workflows/index.ts index ab7f3521e3..8bd5203d9e 100644 --- a/packages/core/core-flows/src/cart/workflows/index.ts +++ b/packages/core/core-flows/src/cart/workflows/index.ts @@ -8,6 +8,5 @@ export * from "./list-shipping-options-for-cart" export * from "./refresh-payment-collection" export * from "./update-cart" export * from "./update-cart-promotions" -export * from "./update-cart-with-customer-validation" export * from "./update-line-item-in-cart" export * from "./update-tax-lines" diff --git a/packages/core/core-flows/src/cart/workflows/update-cart-with-customer-validation.ts b/packages/core/core-flows/src/cart/workflows/update-cart-with-customer-validation.ts deleted file mode 100644 index 9b14d24330..0000000000 --- a/packages/core/core-flows/src/cart/workflows/update-cart-with-customer-validation.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { - AdditionalData, - UpdateCartWorkflowInputDTO, -} from "@medusajs/framework/types" -import { isDefined, isPresent, MedusaError } from "@medusajs/framework/utils" -import { - createStep, - createWorkflow, - when, - WorkflowData, - WorkflowResponse, -} from "@medusajs/framework/workflows-sdk" -import { useRemoteQueryStep } from "../../common" -import { updateCartWorkflow } from "./update-cart" - -/** - * This step validates rules of engagement when customer_id or email is - * requested to be updated. - */ -export const validateCartCustomerOrEmailStep = createStep( - "validate-cart-customer-or-email", - async function ({ - input, - cart, - }: { - input: { - customer_id?: string | null - email?: string | null - auth_customer_id: string | undefined | null - } - cart: { customer_id: string | null; email: string | null } - }) { - if (isPresent(cart.customer_id) && cart.customer_id !== input.customer_id) { - throw new MedusaError( - MedusaError.Types.INVALID_DATA, - `Cannot update cart customer when customer_id is set` - ) - } - - if (isDefined(input.customer_id) && !isDefined(input.auth_customer_id)) { - throw new MedusaError( - MedusaError.Types.INVALID_DATA, - `auth_customer_id is required when customer_id is set` - ) - } - - const isInputCustomerIdDifferent = - input.auth_customer_id !== input.customer_id - - if (isDefined(input.customer_id) && isInputCustomerIdDifferent) { - throw new MedusaError( - MedusaError.Types.INVALID_DATA, - `Cannot update cart customer_id to a different customer` - ) - } - } -) - -export const updateCartWorkflowWithCustomerValidationId = - "update-cart-with-customer-validation" -/** - * This workflow wraps updateCartWorkflow with customer validations - */ -export const updateCartWorkflowWithCustomerValidation = createWorkflow( - updateCartWorkflowWithCustomerValidationId, - ( - input: WorkflowData< - UpdateCartWorkflowInputDTO & - AdditionalData & { auth_customer_id: string | undefined } - > - ) => { - const cart = useRemoteQueryStep({ - entry_point: "cart", - variables: { id: input.id }, - fields: ["id", "customer_id", "email"], - list: false, - throw_if_key_not_found: true, - }).config({ name: "get-cart" }) - - when({ input }, ({ input }) => { - return !!input.customer_id || !!input.email - }).then(() => { - validateCartCustomerOrEmailStep({ input, cart }) - }) - - const updatedCart = updateCartWorkflow.runAsStep({ input }) - - return new WorkflowResponse(updatedCart) - } -) diff --git a/packages/medusa/src/api/store/carts/[id]/route.ts b/packages/medusa/src/api/store/carts/[id]/route.ts index 6de4b5c1ee..1a752e21f4 100644 --- a/packages/medusa/src/api/store/carts/[id]/route.ts +++ b/packages/medusa/src/api/store/carts/[id]/route.ts @@ -1,15 +1,11 @@ -import { updateCartWorkflowWithCustomerValidation } from "@medusajs/core-flows" +import { updateCartWorkflow } from "@medusajs/core-flows" import { AdditionalData, HttpTypes, UpdateCartDataDTO, } from "@medusajs/framework/types" -import { - AuthenticatedMedusaRequest, - MedusaRequest, - MedusaResponse, -} from "@medusajs/framework/http" +import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" import { refetchCart } from "../helpers" export const GET = async ( @@ -26,15 +22,17 @@ export const GET = async ( } export const POST = async ( - req: AuthenticatedMedusaRequest, - res: MedusaResponse + req: MedusaRequest, + res: MedusaResponse<{ + cart: HttpTypes.StoreCart + }> ) => { - const workflow = updateCartWorkflowWithCustomerValidation(req.scope) + const workflow = updateCartWorkflow(req.scope) + await workflow.run({ input: { ...req.validatedBody, id: req.params.id, - auth_customer_id: req.auth_context?.actor_id, }, }) diff --git a/packages/medusa/src/api/store/carts/validators.ts b/packages/medusa/src/api/store/carts/validators.ts index 2111cf60c0..ee83af9a5a 100644 --- a/packages/medusa/src/api/store/carts/validators.ts +++ b/packages/medusa/src/api/store/carts/validators.ts @@ -46,7 +46,6 @@ export const StoreRemoveCartPromotions = z export type StoreUpdateCartType = z.infer export const UpdateCart = z .object({ - customer_id: z.string().optional(), region_id: z.string().optional(), email: z.string().email().nullish(), billing_address: z.union([AddressPayload, z.string()]).optional(),