Assist_Design/apps/bff/src/modules/catalog/internet-eligibility.controller.ts

54 lines
1.9 KiB
TypeScript
Raw Normal View History

import { Body, Controller, Get, Post, Req, UseGuards, UsePipes } from "@nestjs/common";
import { ZodValidationPipe } from "nestjs-zod";
import { z } from "zod";
import type { RequestWithUser } from "@bff/modules/auth/auth.types.js";
import { RateLimit, RateLimitGuard } from "@bff/core/rate-limiting/index.js";
import {
InternetCatalogService,
type InternetEligibilityDto,
} from "./services/internet-catalog.service.js";
import { addressSchema } from "@customer-portal/domain/customer";
const eligibilityRequestSchema = z.object({
notes: z.string().trim().max(2000).optional(),
address: addressSchema.partial().optional(),
});
type EligibilityRequest = z.infer<typeof eligibilityRequestSchema>;
/**
* Internet Eligibility Controller
*
* Authenticated endpoints for:
* - fetching current Salesforce eligibility value
* - requesting a (manual) eligibility/availability check
*
* Note: CatalogController is @Public, so we keep these endpoints in a separate controller
* to ensure GlobalAuthGuard enforces authentication.
*/
@Controller("catalog/internet")
@UseGuards(RateLimitGuard)
export class InternetEligibilityController {
constructor(private readonly internetCatalog: InternetCatalogService) {}
@Get("eligibility")
@RateLimit({ limit: 60, ttl: 60 }) // 60/min per IP (cheap)
async getEligibility(@Req() req: RequestWithUser): Promise<InternetEligibilityDto> {
return this.internetCatalog.getEligibilityDetailsForUser(req.user.id);
}
@Post("eligibility-request")
@RateLimit({ limit: 5, ttl: 300 }) // 5 per 5 minutes per IP
@UsePipes(new ZodValidationPipe(eligibilityRequestSchema))
async requestEligibility(
@Req() req: RequestWithUser,
@Body() body: EligibilityRequest
): Promise<{ requestId: string }> {
const requestId = await this.internetCatalog.requestEligibilityCheckForUser(req.user.id, {
email: req.user.email,
...body,
});
return { requestId };
}
}