fix: Make VAPID public key endpoint publicly accessible
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled

The VAPID public key endpoint needs to be publicly accessible since
frontends need it BEFORE user authentication to set up push subscriptions.

Changes:
- Added @Public() decorator to /api/v1/push/vapid-public-key endpoint
- Imported Public decorator from auth decorators
- Kept all other endpoints protected with JwtAuthGuard:
  * POST /api/v1/push/subscriptions (requires auth)
  * GET /api/v1/push/subscriptions (requires auth)
  * DELETE /api/v1/push/subscriptions (requires auth)
  * POST /api/v1/push/test (requires auth)
  * GET /api/v1/push/statistics (requires auth)

The endpoint now returns the public VAPID key without authentication:
GET /api/v1/push/vapid-public-key
Response: {"publicKey":"BErlB..."}

This matches the Web Push API standard where VAPID public keys
are safe to expose publicly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Andrei
2025-10-08 23:15:42 +00:00
parent 9b31d56c1d
commit 2f1946e683

View File

@@ -13,15 +13,17 @@ import {
} from '@nestjs/common'; } from '@nestjs/common';
import { PushService, PushSubscriptionData } from './push.service'; import { PushService, PushSubscriptionData } from './push.service';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { Public } from '../auth/decorators/public.decorator';
@Controller('api/v1/push') @Controller('api/v1/push')
@UseGuards(JwtAuthGuard)
export class PushController { export class PushController {
constructor(private readonly pushService: PushService) {} constructor(private readonly pushService: PushService) {}
/** /**
* Get the public VAPID key for frontend subscription * Get the public VAPID key for frontend subscription
* This endpoint is public since it's needed for subscription setup
*/ */
@Public()
@Get('vapid-public-key') @Get('vapid-public-key')
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
getPublicKey(): { publicKey: string } { getPublicKey(): { publicKey: string } {
@@ -34,6 +36,7 @@ export class PushController {
* Subscribe to push notifications * Subscribe to push notifications
*/ */
@Post('subscriptions') @Post('subscriptions')
@UseGuards(JwtAuthGuard)
@HttpCode(HttpStatus.CREATED) @HttpCode(HttpStatus.CREATED)
async subscribe( async subscribe(
@Req() req: any, @Req() req: any,
@@ -74,6 +77,7 @@ export class PushController {
* Get user's push subscriptions * Get user's push subscriptions
*/ */
@Get('subscriptions') @Get('subscriptions')
@UseGuards(JwtAuthGuard)
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
async getSubscriptions(@Req() req: any) { async getSubscriptions(@Req() req: any) {
const userId = req.user?.userId; const userId = req.user?.userId;
@@ -97,6 +101,7 @@ export class PushController {
* Unsubscribe from push notifications * Unsubscribe from push notifications
*/ */
@Delete('subscriptions') @Delete('subscriptions')
@UseGuards(JwtAuthGuard)
@HttpCode(HttpStatus.NO_CONTENT) @HttpCode(HttpStatus.NO_CONTENT)
async unsubscribe(@Req() req: any, @Query('endpoint') endpoint: string) { async unsubscribe(@Req() req: any, @Query('endpoint') endpoint: string) {
const userId = req.user?.userId; const userId = req.user?.userId;
@@ -112,6 +117,7 @@ export class PushController {
* Send a test push notification * Send a test push notification
*/ */
@Post('test') @Post('test')
@UseGuards(JwtAuthGuard)
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
async sendTest(@Req() req: any) { async sendTest(@Req() req: any) {
const userId = req.user?.userId; const userId = req.user?.userId;
@@ -126,6 +132,7 @@ export class PushController {
* Get push notification statistics (admin or self) * Get push notification statistics (admin or self)
*/ */
@Get('statistics') @Get('statistics')
@UseGuards(JwtAuthGuard)
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
async getStatistics(@Req() req: any) { async getStatistics(@Req() req: any) {
const userId = req.user?.userId; const userId = req.user?.userId;