fix(rateLimit): exempt explored entrance DELETE from IP rate limiter#1706
Conversation
- Skip deleteRateLimit for DELETE /api/v1/entrances/:id/cavers/:id - Add test covering the exemption - Low-risk self-service action already protected by tokenAuth
Paul-AUB
left a comment
There was a problem hiding this comment.
Suggestions (Should Consider)
-
[test/integration/2_utils/rateLimiter.test.js:295] The test exercises the exemption with unauthenticated requests (
req.tokenis unset). In production,tokenAuthwill have already rejected unauthenticated callers before they reach the controller, but the rate-limiter middleware runs before policies apply, so the unauthenticated path is technically valid to test. Still, adding a variant with areq.tokenset (regular user) would more closely mirror the real call path and document the intended actor. -
[test/integration/2_utils/rateLimiter.test.js:295] Consider adding a negative assertion: send
TEST_USER_DELETE_LIMIT + 5requests to a path like/api/v1/entrances/42/cavers/7/extraand confirm some return 429. The regex$anchor already prevents over-broad matching, but an explicit counter-example locks in that invariant and guards against a future regex loosening.
Nitpicks (Optional)
- [config/rateLimit/rateLimiter.js:139] The inline comment says "tokenAuth already ensures ownership", but
tokenAuthestablishes authentication, not ownership — the ownership check is in the controller/policy. A more precise phrasing would be "tokenAuth ensures the caller is authenticated, and the controller enforces that users can only remove their own entries". Minor doc inaccuracy, won't affect behaviour.
🤔 What
DELETE /api/v1/entrances/:entranceId/cavers/:caverIdroute from the IP-baseddeleteRateLimitmiddleware.🤷♂️ Why
The
deleteRateLimitallows regular users only 1 DELETE request per hour per IP. This makes it impractical for a user to manage their exploration list (removing multiple entrances in a session). The endpoint is already protected bytokenAuthand only allows users to remove their own entries, so the destructive-action rate limit adds no meaningful protection here.🔍 How
Added a path-based
skipcheck inconfig/rateLimit/rateLimiter.jsthat matches/api/v1/entrances/<digits>/cavers/<digits>and returnstrue(skip). The general rate limiter still applies to this route, so it's not unprotected.🧪 Testing
All 13 rate limiter tests pass, including the new one.
📸 Previews
N/A