fix(api): tighter public lot endpoint, SSO callback from config, mapped 4xx errors
- Public lot lookup: 30 requests/min per IP and only well-formed lot numbers (1-64 chars) reach the database. - SSO callback URL is built from OIDC_REDIRECT_URI instead of the Host header; SSO cookies are cleared with the attributes they were set with. - Logout is rate-limited like the other auth endpoints. - Middleware errors with a 4xx status (body too large, malformed JSON) answer with that status instead of a 500; error log lines carry the path without query string. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
eafe925d60
commit
0899576262
4 files changed
+49
-9
No files matched your search
@@ -1,16 +1,26 @@
|
||||
import { Controller, Get, Param } from '@nestjs/common';
|
||||
import { Controller, Get, NotFoundException, Param } from '@nestjs/common';
|
||||
import { Throttle } from '@nestjs/throttler';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { Public } from '../auth/decorators/public.decorator';
|
||||
import { PublicBatch, PublicService } from './public.service';
|
||||
|
||||
// What a printed lot number can look like - anything else is not a lot.
|
||||
const LOT_NUMBER_PATTERN = /^[A-Za-z0-9._\/-]{1,64}$/;
|
||||
|
||||
@ApiTags('public')
|
||||
@Public()
|
||||
@Controller('public/batches')
|
||||
export class PublicController {
|
||||
constructor(private readonly publicService: PublicService) {}
|
||||
|
||||
// Anonymous and enumerable by design (lot numbers are printed on jars),
|
||||
// so it gets a tighter per-IP limit than logged-in traffic.
|
||||
@Throttle({ default: { limit: 30, ttl: 60000 } })
|
||||
@Get(':lotNumber')
|
||||
findByLot(@Param('lotNumber') lotNumber: string): Promise<PublicBatch> {
|
||||
if (!LOT_NUMBER_PATTERN.test(lotNumber)) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return this.publicService.findBatchByLot(lotNumber);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user