Skip to content

Commit

Permalink
feat(business constraint bypass): add limit param on `/api/products…
Browse files Browse the repository at this point in the history
…/latest` (#294)

Adds a `limit` URL param to `/api/products/latest` which controls the
amount of products returned via this EP. This introduces a business
constraint bypass, as this EP is used on the main page to display only
the 3 latest products, and the user must be logged in to access the
Marketplace page where they can see the full list of products via the
`/api/products` EP, which is password protected.
  • Loading branch information
tamirGer authored Dec 29, 2023
1 parent cae06a0 commit fea6dfd
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,6 @@ Additionally, the endpoint PUT /api/users/one/{email}/photo accepts SVG images,

* **IFrame Injection** - The `/testimonials` page a URL parameter `videosrc` which directly controls the src attribute of the IFrame at the bottom of this page. Similarly, the home page takes a URL param `maptitle` which directly controls the `title` attribute of the IFrame at the CONTACT section of this page.

* **Excessive Data Exposure** - The `/api/users/one/:email` is supposed to expose only basic user information required to be displayed on the UI, but it also returns the user's phone number which is unnecessary information.
* **Excessive Data Exposure** - The `/api/users/one/:email` is supposed to expose only basic user information required to be displayed on the UI, but it also returns the user's phone number which is unnecessary information.

* **Business Constraint Bypass** - The `/api/products/latest` endpoint supports a `limit` parameter, which by default is set to 3. The `/api/products` endpoint is a password protected endpoint which returns all of the products, yet if you change the `limit` param of `/api/products/latest` to be high enough you could get the same results without the need to be authenticated.
16 changes: 14 additions & 2 deletions src/products/products.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
UseGuards,
Headers,
InternalServerErrorException,
Query,
BadRequestException,
} from '@nestjs/common';
import {
ApiOperation,
Expand All @@ -14,6 +16,7 @@ import {
ApiForbiddenResponse,
ApiInternalServerErrorResponse,
ApiHeader,
ApiQuery,
} from '@nestjs/swagger';
import { AuthGuard } from '../auth/auth.guard';
import { JwtProcessorType } from '../auth/auth.service';
Expand Down Expand Up @@ -61,16 +64,25 @@ export class ProductsController {
}

@Get('latest')
@ApiQuery({ name: 'limit', example: 3, required: false })
@ApiOperation({
description: API_DESC_GET_LATEST_PRODUCTS,
})
@ApiOkResponse({
type: ProductDto,
isArray: true,
})
async getLatestProducts(): Promise<ProductDto[]> {
async getLatestProducts(
@Query('limit') limit: number,
): Promise<ProductDto[]> {
this.logger.debug('Get latest products.');
const products = await this.productsService.findLatest(3);
if (limit && isNaN(limit)) {
throw new BadRequestException('Limit must be a number');
}
if (limit && limit < 0) {
throw new BadRequestException('Limit must be positive');
}
const products = await this.productsService.findLatest(limit || 3);
return products.map((p: Product) => new ProductDto(p));
}

Expand Down

0 comments on commit fea6dfd

Please sign in to comment.