* feat(admin): add IP whitelist (strict allowlist mode) (#920) - Add enableWhitelist/whitelist fields to IpBlacklistSettings - Implement three-layer access control: whitelist → blacklist → daily limit - Whitelist uses exact match for IPv4/IPv6, regex for patterns - Whitelisted IPs skip blacklist checks (trusted) - Fail-closed when cf-connecting-ip missing under whitelist mode - Frontend: independent whitelist toggle + empty list protection - Backend: backward compatible (old frontends get defaults) - E2E tests: config validation + runtime behavior - Docs: CHANGELOG zh/en updated Closes #920 * fix(admin): address PR review feedback on IP whitelist - Add IPv4-mapped IPv6 (::ffff:x.x.x.x) exact match in isWhitelisted - Include error.message in whitelist regex parse failure log - Include actual/max size in whitelist size limit error message Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(admin): validate whitelist regex on save and preserve existing whitelist on partial update - Reject invalid regex patterns in whitelist at save time to prevent runtime lockout - Preserve existing enableWhitelist/whitelist from DB when older clients omit these fields Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(admin): revert P2 - keep simple ?? defaults for backward compat Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(admin): validate whitelist elements are strings before trimming Prevents 500 error when whitelist contains non-string elements (e.g. numbers, null) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs(admin): add IP blacklist/whitelist documentation (zh + en) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(admin): fix fingerprint blacklist bypass when cf-connecting-ip absent, improve e2e tests - Split checkBlacklist into checkFingerprintBlacklist (IP-independent) and checkIpAsnBlacklist - Fingerprint check now runs before the !reqIp early-return to prevent bypass - Add afterEach reset to config test group, extract RESET_SETTINGS constant - Strengthen whitelist-blocks test to deterministic 403 assertion - Add e2e tests: invalid regex rejection, non-string element rejection, fingerprint-blocks-without-IP Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(admin): suppress no-useless-escape lint warning in whitelist regex check Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2.0 KiB
Admin Console
Note
You need to configure
ADMIN_PASSWORDSorADMIN_USER_ROLEto access the admin console Admin role configuration: if the user role equals ADMIN_USER_ROLE, they can access the admin console
After deploying the frontend application, click the upper-left logo 5 times or visit the /admin path to enter the management console.
You need to configure ADMIN_PASSWORDS in the backend or ensure the current user role is ADMIN_USER_ROLE, otherwise access to the console will be denied.
Account List Sorting
The Accounts tab in the admin console supports column sorting. Click the column header to toggle ascending/descending order for:
- ID
- Name
- Created At
- Updated At
- Mail Count
- Send Count
When searching for email addresses, pagination automatically resets to page 1.
If your website is for private access only, you can disable this check
DISABLE_ADMIN_PASSWORD_CHECK = true
IP Blacklist / Whitelist
Configure access control in Admin Console → IP Blacklist Settings. Applies to: create address, send mail, external send mail API, user registration, and verify code endpoints.
IP Whitelist (Strict Mode)
When enabled, only whitelisted IPs can access protected endpoints; all others receive 403.
- Plain entries: exact match (no substring), e.g.
1.2.3.4 - Regex entries: use anchored patterns, e.g.
^192\.168\.1\.\d+$ - Whitelisted IPs skip blacklist checks
- If whitelist is enabled but the list is empty, the server ignores the switch (fail-open to prevent lockout)
IP Blacklist
When enabled, matching IPs receive 403. Supports substring text matching or regex.
ASN Organization Blacklist
Block by ISP/provider name, case-insensitive. Supports text or regex matching.
Browser Fingerprint Blacklist
Block by x-fingerprint request header. Supports exact or regex matching.
Daily Request Limit
Limit the maximum number of requests per IP per day (1–1,000,000). Exceeding the limit returns 429. Counter resets every 24 hours (UTC date boundary).
