diff --git a/README.md b/README.md index 3f8ed8b9..54232b25 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,14 @@ These variables are exposed to the client-side React application: - Enable debug mode (mocks external services) - Set to any value to enable +- **Config table: `white_email_domain` / `private_white_email_domain`** + - `white_email_domain`: Global email domain whitelist used when requesting email verification codes. Stored in the `config` table as JSON array string, for example: `["gmail.com"]`. + - `private_white_email_domain`: Higher-priority private email domain whitelist checked before `white_email_domain`. Also stored in the `config` table as JSON array string, for example: `["corp.example.com", "partner.org"]`. + - Configuration example in `config` table: + - `c_key = 'white_email_domain'`, `c_val = '["gmail.com"]'` + - `c_key = 'private_white_email_domain'`, `c_val = '["corp.example.com", "partner.org"]'` + - If an email domain is present in `private_white_email_domain`, it is accepted even if not listed in `white_email_domain`. If it is in neither list, the API responds with the same `error_api_email_domain` error and `white_email_domain` data as before. + ## Running the Application ### Development Mode diff --git a/helpers/database.js b/helpers/database.js index 0b89367c..d6500881 100644 --- a/helpers/database.js +++ b/helpers/database.js @@ -234,12 +234,21 @@ export function clearConfigCache(key) { * Returns default ['gmail.com'] if config not found or parse fails */ export async function getWhiteEmailDomain() { + const domains = await getConfigValue('white_email_domain', ['gmail.com'], 300); + return Array.isArray(domains) ? domains : ['gmail.com']; +} + +/** + * Get private white email domain list from config table + * Returns default [] if config not found or parse fails + */ +export async function getPrivateWhiteEmailDomain() { const domains = await getConfigValue( - 'white_email_domain', - ['gmail.com'], + 'private_white_email_domain', + [], 300 ); - return Array.isArray(domains) ? domains : ['gmail.com']; + return Array.isArray(domains) ? domains : []; } export default { @@ -268,6 +277,7 @@ export default { findLastSendSmsByCountryNumber, countTryNumber, getWhiteEmailDomain, + getPrivateWhiteEmailDomain, getConfigValue, clearConfigCache, }; diff --git a/routes/apiHandlers.js b/routes/apiHandlers.js index da2e181d..a97d3300 100644 --- a/routes/apiHandlers.js +++ b/routes/apiHandlers.js @@ -154,13 +154,16 @@ async function handleRequestEmailCode(req) { } // white list check const emailDomain = email.split('@')[1]; - const whiteEmailDomains = await database.getWhiteEmailDomain(); - if (!whiteEmailDomains.includes(emailDomain)) { - throw new ApiError({ - type: 'error_api_email_domain', - field: 'email', - data: { whiteEmailDomains }, - }); + const privateWhiteEmailDomains = await database.getPrivateWhiteEmailDomain(); + if (!privateWhiteEmailDomains.includes(emailDomain)) { + const whiteEmailDomains = await database.getWhiteEmailDomain(); + if (!whiteEmailDomains.includes(emailDomain)) { + throw new ApiError({ + type: 'error_api_email_domain', + field: 'email', + data: { whiteEmailDomains }, + }); + } } // account creation policy check const isEnoughPendingClaimedAccounts =