-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat: add rate limit for email verification codes #2041
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements rate limiting for email verification codes across signup, password reset, and email change flows. The changes refactor existing rate limit logic into a centralized service and extend it to cover all email verification scenarios.
- Consolidates rate limit configuration from
authConfigtothresholdConfigwith separate settings for each email flow - Introduces a reusable
checkSendMailRateLimitmethod inMailSenderServiceto handle rate limiting consistently - Adds UI countdown timers using a new
useCutDownhook to display remaining wait time to users
Reviewed Changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/openapi/src/admin/setting/get-public.ts | Replaces single rate limit field with three separate fields for different email verification flows |
| packages/common-i18n/src/locales/*/common.json, auth.json | Adds localized error messages for rate limit violations |
| apps/nextjs-app/src/lib/server-env.ts | Adds type definitions for new rate limit configuration fields |
| apps/nextjs-app/src/features/auth/pages/ResetPasswordPage.tsx | Improves error handling type annotations |
| apps/nextjs-app/src/features/auth/pages/ForgetPasswordPage.tsx | Implements countdown timer and rate limit error handling for password reset |
| apps/nextjs-app/src/features/auth/components/SignForm.tsx | Extracts countdown logic to reusable hook and updates field references |
| apps/nextjs-app/src/features/app/hooks/useSetting.ts | Adds new query hook for public settings |
| apps/nextjs-app/src/features/app/hooks/useCutDown.ts | Creates reusable countdown timer hook |
| apps/nextjs-app/src/features/app/components/setting/account/ChangeEmailDialog.tsx | Implements countdown timer and rate limit error handling for email change |
| apps/nestjs-backend/src/features/setting/open-api/setting-open-api.controller.ts | Updates controller to use new threshold config fields |
| apps/nestjs-backend/src/features/mail-sender/mail-sender.service.ts | Adds centralized rate limiting method with cache-based tracking |
| apps/nestjs-backend/src/features/auth/local-auth/local-auth.service.ts | Refactors email sending to use new centralized rate limiting |
| apps/nestjs-backend/src/configs/threshold.config.ts | Moves rate limit config with backward compatibility and adds new fields |
| apps/nestjs-backend/src/configs/auth.config.ts | Removes old rate limit field |
| apps/nestjs-backend/src/cache/types.ts | Updates cache key types to reflect new generic rate limit pattern |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| process.env.BACKEND_SIGNUP_VERIFICATION_CODE_RATE_LIMIT_SECONDS ?? | ||
| process.env.BACKEND_SIGNUP_VERIFICATION_SEND_MAIL_CODE_RATE ?? | ||
| 30 |
Copilot
AI
Oct 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fallback chain for signupVerificationSendMailCodeRate creates an implicit dependency on deprecated environment variable BACKEND_SIGNUP_VERIFICATION_CODE_RATE_LIMIT_SECONDS. Consider documenting this backward compatibility in a comment or setting a deprecation timeline.
| if (_rateLimit <= 0) { | ||
| return await fn(); | ||
| } | ||
| const rateLimit = _rateLimit - 2; // 2 seconds for network latency |
Copilot
AI
Oct 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The magic number 2 for network latency adjustment should be extracted to a named constant (e.g., NETWORK_LATENCY_BUFFER_SECONDS = 2) to improve code clarity and maintainability.
| return await fn(); | ||
| } | ||
| const rateLimit = _rateLimit - 2; // 2 seconds for network latency | ||
| const rateLimitKey = `send-mail-rate-limit:${_rateLimitKey}:${email}` as const; |
Copilot
AI
Oct 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The as const assertion on a template literal with variables has no effect since the type cannot be literal. Remove the as const assertion as it provides no type safety benefit here.
| const rateLimitKey = `send-mail-rate-limit:${_rateLimitKey}:${email}` as const; | |
| const rateLimitKey = `send-mail-rate-limit:${_rateLimitKey}:${email}`; |
No description provided.