Skip to content

Commit

Permalink
feat: fix insecure request exposing sensitive information (#18756)
Browse files Browse the repository at this point in the history
  • Loading branch information
kpawelczak authored Jul 10, 2024
1 parent dd2c600 commit 77ba8c2
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 75 deletions.
32 changes: 0 additions & 32 deletions feature-libs/cart/base/occ/adapters/default-occ-cart-config.ts

This file was deleted.

24 changes: 20 additions & 4 deletions feature-libs/cart/base/occ/adapters/occ-cart.adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@
*/

import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { CartAdapter } from '@spartacus/cart/base/core';
import {
CART_NORMALIZER,
Cart,
CART_NORMALIZER,
SaveCartResult,
} from '@spartacus/cart/base/root';
import {
ConverterService,
FeatureConfigService,
InterceptorUtil,
Occ,
OCC_CART_ID_CURRENT,
OCC_USER_ID_ANONYMOUS,
Occ,
OccEndpointsService,
USE_CLIENT_TOKEN,
} from '@spartacus/core';
Expand All @@ -26,6 +27,8 @@ import { map } from 'rxjs/operators';

@Injectable()
export class OccCartAdapter implements CartAdapter {
private featureConfigService = inject(FeatureConfigService);

constructor(
protected http: HttpClient,
protected occEndpointsService: OccEndpointsService,
Expand Down Expand Up @@ -113,7 +116,20 @@ export class OccCartAdapter implements CartAdapter {
saveCartDescription,
},
});
return this.http.patch<Occ.Cart>(endpoint, cartId).pipe(

let httpParams: HttpParams = new HttpParams();

if (
this.featureConfigService?.isEnabled(
'occCartNameAndDescriptionInHttpRequestBody'
)
) {
httpParams = httpParams
.set('saveCartName', saveCartName)
.set('saveCartDescription', saveCartDescription);
}

return this.http.patch<Occ.Cart>(endpoint, httpParams).pipe(
map((cartResponse) => (cartResponse as SaveCartResult).savedCartData),
this.converterService.pipeable(CART_NORMALIZER)
);
Expand Down
6 changes: 3 additions & 3 deletions feature-libs/cart/base/occ/cart-base-occ.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ import {
CART_NORMALIZER,
ORDER_ENTRY_PROMOTIONS_NORMALIZER,
} from '@spartacus/cart/base/root';
import { provideDefaultConfig } from '@spartacus/core';
import { provideDefaultConfigFactory } from '@spartacus/core';
import { OccCartNormalizer } from './adapters/converters/occ-cart-normalizer';
import { OrderEntryPromotionsNormalizer } from './adapters/converters/order-entry-promotions-normalizer';
import { defaultOccCartConfig } from './adapters/default-occ-cart-config';
import { OccCartEntryAdapter } from './adapters/occ-cart-entry.adapter';
import { OccCartValidationAdapter } from './adapters/occ-cart-validation.adapter';
import { OccCartVoucherAdapter } from './adapters/occ-cart-voucher.adapter';
import { OccCartAdapter } from './adapters/occ-cart.adapter';
import { defaultOccCartConfigFactory } from './config/default-occ-cart-config-factory';

@NgModule({
imports: [CommonModule],
providers: [
provideDefaultConfig(defaultOccCartConfig),
provideDefaultConfigFactory(defaultOccCartConfigFactory),
{
provide: CartAdapter,
useClass: OccCartAdapter,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2024 SAP Spartacus team <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/

import { FeatureToggles, OccConfig } from '@spartacus/core';
import { inject } from '@angular/core';

export function defaultOccCartConfigFactory(): OccConfig {
const featureToggles = inject(FeatureToggles);

return {
backend: {
occ: {
endpoints: {
/* eslint-disable max-len */
carts:
'users/${userId}/carts?fields=carts(DEFAULT,potentialProductPromotions,appliedProductPromotions,potentialOrderPromotions,appliedOrderPromotions,entries(totalPrice(formattedValue),product(images(FULL),stock(FULL)),basePrice(formattedValue,value),updateable),totalPrice(formattedValue),totalItems,totalPriceWithTax(formattedValue),totalDiscounts(value,formattedValue),subTotal(formattedValue),totalUnitCount,deliveryItemsQuantity,deliveryCost(formattedValue),totalTax(formattedValue, value),pickupItemsQuantity,net,appliedVouchers,productDiscounts(formattedValue),user,saveTime,name,description)',
cart: 'users/${userId}/carts/${cartId}?fields=DEFAULT,potentialProductPromotions,appliedProductPromotions,potentialOrderPromotions,appliedOrderPromotions,entries(totalPrice(formattedValue),product(images(FULL),stock(FULL)),basePrice(formattedValue,value),updateable),totalPrice(formattedValue),totalItems,totalPriceWithTax(formattedValue),totalDiscounts(value,formattedValue),subTotal(formattedValue),totalUnitCount,deliveryItemsQuantity,deliveryCost(formattedValue),totalTax(formattedValue, value),pickupItemsQuantity,net,appliedVouchers,productDiscounts(formattedValue),user,saveTime,name,description',
createCart:
'users/${userId}/carts?fields=DEFAULT,potentialProductPromotions,appliedProductPromotions,potentialOrderPromotions,appliedOrderPromotions,entries(totalPrice(formattedValue),product(images(FULL),stock(FULL)),basePrice(formattedValue,value),updateable),totalPrice(formattedValue),totalItems,totalPriceWithTax(formattedValue),totalDiscounts(value,formattedValue),subTotal(formattedValue),totalUnitCount,deliveryItemsQuantity,deliveryCost(formattedValue),totalTax(formattedValue, value),pickupItemsQuantity,net,appliedVouchers,productDiscounts(formattedValue),user',
addEntries: 'users/${userId}/carts/${cartId}/entries',
updateEntries:
'users/${userId}/carts/${cartId}/entries/${entryNumber}',
removeEntries:
'users/${userId}/carts/${cartId}/entries/${entryNumber}',
addEmail: 'users/${userId}/carts/${cartId}/email',
deleteCart: 'users/${userId}/carts/${cartId}',
cartVoucher: 'users/${userId}/carts/${cartId}/vouchers',
saveCart: featureToggles.occCartNameAndDescriptionInHttpRequestBody
? '/users/${userId}/carts/${cartId}/save'
: '/users/${userId}/carts/${cartId}/save?saveCartName=${saveCartName}&saveCartDescription=${saveCartDescription}',
validate: 'users/${userId}/carts/${cartId}/validate?fields=DEFAULT',
/* eslint-enable */
},
},
},
};
}
38 changes: 27 additions & 11 deletions feature-libs/cart/saved-cart/occ/adapters/occ-saved-cart.adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,27 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import {
Cart,
CART_NORMALIZER,
SaveCartResult,
} from '@spartacus/cart/base/root';
import { SavedCartAdapter } from '@spartacus/cart/saved-cart/core';
import { ConverterService, Occ, OccEndpointsService } from '@spartacus/core';
import {
ConverterService,
FeatureConfigService,
Occ,
OccEndpointsService,
} from '@spartacus/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable()
export class OccSavedCartAdapter implements SavedCartAdapter {
private featureConfigService = inject(FeatureConfigService);

constructor(
protected http: HttpClient,
protected occEndpoints: OccEndpointsService,
Expand Down Expand Up @@ -56,15 +63,24 @@ export class OccSavedCartAdapter implements SavedCartAdapter {
cartId: string,
saveCartName: string
): Observable<Cart> {
return this.http
.post<Occ.Cart>(
this.getCloneSavedCartEndpoint(userId, cartId, saveCartName),
cartId
let httpParams: HttpParams = new HttpParams();
if (
this.featureConfigService?.isEnabled(
'occCartNameAndDescriptionInHttpRequestBody'
)
.pipe(
map((cartResponse) => (cartResponse as SaveCartResult).savedCartData),
this.converter.pipeable(CART_NORMALIZER)
);
) {
httpParams = httpParams.set('name', saveCartName);
}
const endpoint = this.getCloneSavedCartEndpoint(
userId,
cartId,
saveCartName
);

return this.http.post<Occ.Cart>(endpoint, httpParams).pipe(
map((cartResponse) => (cartResponse as SaveCartResult).savedCartData),
this.converter.pipeable(CART_NORMALIZER)
);
}

protected getSavedCartEndpoint(userId: string, cartId: string): string {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* SPDX-FileCopyrightText: 2024 SAP Spartacus team <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/

import { FeatureToggles, OccConfig } from '@spartacus/core';
import { inject } from '@angular/core';

export function defaultOccSavedCartConfigFactory(): OccConfig {
const featureToggles = inject(FeatureToggles);

return {
backend: {
occ: {
endpoints: {
savedCarts:
'/users/${userId}/carts?savedCartsOnly=true&fields=carts(DEFAULT,potentialProductPromotions,appliedProductPromotions,potentialOrderPromotions,appliedOrderPromotions,entries(totalPrice(formattedValue),product(images(FULL),stock(FULL)),basePrice(formattedValue,value),updateable),totalPrice(formattedValue),totalItems,totalPriceWithTax(formattedValue),totalDiscounts(value,formattedValue),subTotal(formattedValue),totalUnitCount,deliveryItemsQuantity,deliveryCost(formattedValue),totalTax(formattedValue, value),pickupItemsQuantity,net,appliedVouchers,productDiscounts(formattedValue),saveTime,user,name,description)',
savedCart: '/users/${userId}/carts/${cartId}/savedcart',
restoreSavedCart: '/users/${userId}/carts/${cartId}/restoresavedcart',
cloneSavedCart:
featureToggles.occCartNameAndDescriptionInHttpRequestBody
? '/users/${userId}/carts/${cartId}/clonesavedcart'
: '/users/${userId}/carts/${cartId}/clonesavedcart?name=${saveCartName}',
},
},
},
};
}

This file was deleted.

6 changes: 3 additions & 3 deletions feature-libs/cart/saved-cart/occ/saved-cart-occ.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { SavedCartAdapter } from '@spartacus/cart/saved-cart/core';
import { provideDefaultConfig } from '@spartacus/core';
import { provideDefaultConfigFactory } from '@spartacus/core';
import { OccSavedCartAdapter } from './adapters/occ-saved-cart.adapter';
import { defaultOccSavedCartConfig } from './config/default-occ-saved-cart-config';
import { defaultOccSavedCartConfigFactory } from './config/default-occ-saved-cart-config-factory';

@NgModule({
imports: [CommonModule],
providers: [
provideDefaultConfig(defaultOccSavedCartConfig),
provideDefaultConfigFactory(defaultOccSavedCartConfigFactory),
{
provide: SavedCartAdapter,
useClass: OccSavedCartAdapter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,13 @@ export interface FeatureTogglesInterface {
*/
a11yStoreFinderSearchboxBloat?: boolean;

/**
* In OCC cart requests, it puts parameters of a cart name and cart description
* into a request body, instead of query params.
* This toggle is used in the following classes: `OccCartAdapter`, `OccSavedCartAdapter`, `SavedCartOccModule`, `CartBaseOccModule`.
*/
occCartNameAndDescriptionInHttpRequestBody?: boolean;

/**
* When enabled, styles for the `cx-bottom-header-slot` class will be applied. These styles are necessary to display
* customization buttons in the BottomHeaderSlot in SmartEdit.
Expand Down Expand Up @@ -441,5 +448,6 @@ export const defaultFeatureToggles: Required<FeatureTogglesInterface> = {
a11yCxMessageFocus: false,
a11yLinkBtnsToTertiaryBtns: false,
a11yStoreFinderSearchboxBloat: false,
occCartNameAndDescriptionInHttpRequestBody: false,
cmsBottomHeaderSlotUsingFlexStyles: false,
};
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ if (environment.estimatedDeliveryDate) {
true,
a11yFacetsDialogFocusHandling: true,
a11yCxMessageFocus: true,
occCartNameAndDescriptionInHttpRequestBody: true,
a11yLinkBtnsToTertiaryBtns: true,
cmsBottomHeaderSlotUsingFlexStyles: true,
a11yStoreFinderSearchboxBloat: true,
Expand Down

0 comments on commit 77ba8c2

Please sign in to comment.