2017-10-28 22:18:07 +02:00
'use strict' ;
2025-10-08 20:11:55 +02:00
exports = module . exports = {
2020-12-23 15:34:23 -08:00
add ,
get ,
2021-08-13 17:22:28 -07:00
list ,
2021-12-03 13:46:54 -08:00
setConfig ,
setWellKnown ,
2020-12-23 15:34:23 -08:00
del ,
clear ,
2017-10-28 22:18:07 +02:00
2022-11-11 18:09:10 +01:00
getDomainObjectMap ,
2020-12-23 15:34:23 -08:00
removePrivateFields ,
removeRestrictedFields ,
2025-02-17 19:01:53 +01:00
checkConfigs
2017-10-28 22:18:07 +02:00
} ;
2025-08-14 11:17:38 +05:30
const assert = require ( 'node:assert' ) ,
2019-10-23 10:02:04 -07:00
BoxError = require ( './boxerror.js' ) ,
2023-08-04 14:13:30 +05:30
constants = require ( './constants.js' ) ,
2025-08-14 11:17:38 +05:30
crypto = require ( 'node:crypto' ) ,
2023-08-11 19:41:05 +05:30
dashboard = require ( './dashboard.js' ) ,
2021-08-13 17:22:28 -07:00
database = require ( './database.js' ) ,
2022-11-30 12:37:41 +01:00
debug = require ( 'debug' ) ( 'box:domains' ) ,
2018-11-10 00:43:46 -08:00
eventlog = require ( './eventlog.js' ) ,
2023-08-04 20:54:16 +05:30
mailServer = require ( './mailserver.js' ) ,
2025-02-17 19:01:53 +01:00
notifications = require ( './notifications.js' ) ,
2018-01-30 12:23:27 -08:00
reverseProxy = require ( './reverseproxy.js' ) ,
2021-08-13 17:22:28 -07:00
safe = require ( 'safetydance' ) ,
2017-10-28 23:23:58 +02:00
tld = require ( 'tldjs' ) ,
2025-02-13 14:03:25 +01:00
_ = require ( './underscore.js' ) ;
2017-10-28 22:18:07 +02:00
2021-08-13 17:22:28 -07:00
const DOMAINS _FIELDS = [ 'domain' , 'zoneName' , 'provider' , 'configJson' , 'tlsConfigJson' , 'wellKnownJson' , 'fallbackCertificateJson' ] . join ( ',' ) ;
function postProcess ( data ) {
data . config = safe . JSON . parse ( data . configJson ) ;
delete data . configJson ;
data . tlsConfig = safe . JSON . parse ( data . tlsConfigJson ) ;
delete data . tlsConfigJson ;
data . wellKnown = safe . JSON . parse ( data . wellKnownJson ) ;
delete data . wellKnownJson ;
data . fallbackCertificate = safe . JSON . parse ( data . fallbackCertificateJson ) ;
delete data . fallbackCertificateJson ;
return data ;
}
2017-10-29 00:15:11 +02:00
// choose which subdomain backend we use for test purpose we use route53
function api ( provider ) {
assert . strictEqual ( typeof provider , 'string' ) ;
switch ( provider ) {
2023-04-21 10:39:11 +02:00
case 'bunny' : return require ( './dns/bunny.js' ) ;
2017-11-21 19:18:03 -08:00
case 'cloudflare' : return require ( './dns/cloudflare.js' ) ;
2024-04-24 20:32:54 +02:00
case 'desec' : return require ( './dns/desec.js' ) ;
2023-10-23 23:17:32 +02:00
case 'dnsimple' : return require ( './dns/dnsimple.js' ) ;
2017-11-21 19:18:03 -08:00
case 'route53' : return require ( './dns/route53.js' ) ;
case 'gcdns' : return require ( './dns/gcdns.js' ) ;
case 'digitalocean' : return require ( './dns/digitalocean.js' ) ;
2018-05-06 18:57:27 -07:00
case 'gandi' : return require ( './dns/gandi.js' ) ;
2018-05-06 22:22:42 -07:00
case 'godaddy' : return require ( './dns/godaddy.js' ) ;
2022-05-02 22:00:42 -07:00
case 'hetzner' : return require ( './dns/hetzner.js' ) ;
2025-10-10 11:18:04 +02:00
case 'hetznercloud' : return require ( './dns/hetznercloud.js' ) ;
2024-11-26 13:11:26 +05:30
case 'inwx' : return require ( './dns/inwx.js' ) ;
2020-03-12 17:13:13 -07:00
case 'linode' : return require ( './dns/linode.js' ) ;
2021-05-29 22:30:26 -07:00
case 'vultr' : return require ( './dns/vultr.js' ) ;
2018-05-09 12:24:33 +02:00
case 'namecom' : return require ( './dns/namecom.js' ) ;
2019-01-16 18:05:42 +02:00
case 'namecheap' : return require ( './dns/namecheap.js' ) ;
2021-01-18 19:43:47 +01:00
case 'netcup' : return require ( './dns/netcup.js' ) ;
2017-11-21 19:18:03 -08:00
case 'noop' : return require ( './dns/noop.js' ) ;
2023-11-05 18:38:30 +01:00
case 'ovh' : return require ( './dns/ovh.js' ) ;
2017-11-21 19:18:03 -08:00
case 'manual' : return require ( './dns/manual.js' ) ;
2023-03-16 10:24:31 +01:00
case 'porkbun' : return require ( './dns/porkbun.js' ) ;
2018-09-06 20:26:24 -07:00
case 'wildcard' : return require ( './dns/wildcard.js' ) ;
2017-11-21 19:18:03 -08:00
default : return null ;
2017-10-29 00:15:11 +02:00
}
}
2022-01-05 22:41:41 -08:00
async function verifyDomainConfig ( domainConfig , domain , zoneName , provider ) {
assert ( domainConfig && typeof domainConfig === 'object' ) ; // the dns config to test with
2017-10-29 00:15:11 +02:00
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof zoneName , 'string' ) ;
2018-01-09 14:46:38 -08:00
assert . strictEqual ( typeof provider , 'string' ) ;
2017-10-29 00:15:11 +02:00
2021-08-27 09:52:24 -07:00
const backend = api ( provider ) ;
2022-02-07 13:19:59 -08:00
if ( ! backend ) throw new BoxError ( BoxError . BAD _FIELD , 'Invalid provider' ) ;
2017-10-29 00:15:11 +02:00
2024-04-29 15:51:16 +02:00
const domainObject = { config : domainConfig , domain , zoneName } ;
2022-07-14 10:32:30 +05:30
const [ error , sanitizedConfig ] = await safe ( api ( provider ) . verifyDomainConfig ( domainObject ) ) ;
if ( error && error . reason === BoxError . ACCESS _DENIED ) throw new BoxError ( BoxError . BAD _FIELD , ` Access denied: ${ error . message } ` ) ;
if ( error && error . reason === BoxError . NOT _FOUND ) throw new BoxError ( BoxError . BAD _FIELD , ` Zone not found: ${ error . message } ` ) ;
if ( error && error . reason === BoxError . EXTERNAL _ERROR ) throw new BoxError ( BoxError . BAD _FIELD , ` Configuration error: ${ error . message } ` ) ;
if ( error ) throw error ;
2021-08-27 09:52:24 -07:00
2022-07-14 10:32:30 +05:30
return sanitizedConfig ;
2018-08-22 11:53:23 +02:00
}
2017-10-29 00:15:11 +02:00
2018-09-12 12:25:07 -07:00
function validateTlsConfig ( tlsConfig , dnsProvider ) {
2018-09-11 21:53:18 -07:00
assert . strictEqual ( typeof tlsConfig , 'object' ) ;
2018-09-12 12:25:07 -07:00
assert . strictEqual ( typeof dnsProvider , 'string' ) ;
switch ( tlsConfig . provider ) {
case 'letsencrypt-prod' :
case 'letsencrypt-staging' :
case 'fallback' :
break ;
default :
2022-02-07 13:19:59 -08:00
return new BoxError ( BoxError . BAD _FIELD , 'tlsConfig.provider must be fallback, letsencrypt-prod/staging' ) ;
2018-09-12 12:25:07 -07:00
}
2018-09-11 21:53:18 -07:00
2018-09-12 12:25:07 -07:00
if ( tlsConfig . wildcard ) {
2022-02-07 13:19:59 -08:00
if ( ! tlsConfig . provider . startsWith ( 'letsencrypt' ) ) return new BoxError ( BoxError . BAD _FIELD , 'wildcard can only be set with letsencrypt' ) ;
if ( dnsProvider === 'manual' || dnsProvider === 'noop' || dnsProvider === 'wildcard' ) return new BoxError ( BoxError . BAD _FIELD , 'wildcard cert requires a programmable DNS backend' ) ;
2018-09-11 21:53:18 -07:00
}
return null ;
}
2020-12-23 15:34:23 -08:00
function validateWellKnown ( wellKnown ) {
assert . strictEqual ( typeof wellKnown , 'object' ) ;
return null ;
}
2021-08-13 17:22:28 -07:00
async function add ( domain , data , auditSource ) {
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof domain , 'string' ) ;
2018-11-10 00:43:46 -08:00
assert . strictEqual ( typeof data . zoneName , 'string' ) ;
assert . strictEqual ( typeof data . provider , 'string' ) ;
assert . strictEqual ( typeof data . config , 'object' ) ;
assert . strictEqual ( typeof data . fallbackCertificate , 'object' ) ;
assert . strictEqual ( typeof data . tlsConfig , 'object' ) ;
2017-10-28 22:18:07 +02:00
2024-04-29 13:05:07 +02:00
const { provider , config , tlsConfig } = data ;
2018-11-10 00:43:46 -08:00
2025-02-05 10:51:05 +01:00
if ( ! tld . isValid ( domain ) ) throw new BoxError ( BoxError . BAD _FIELD , 'Invalid domain' ) ;
2022-02-07 13:19:59 -08:00
if ( domain . endsWith ( '.' ) ) throw new BoxError ( BoxError . BAD _FIELD , 'Invalid domain' ) ;
2018-01-23 18:54:05 -08:00
2024-04-29 13:05:07 +02:00
let zoneName ;
if ( data . zoneName ) {
2025-02-05 10:51:05 +01:00
if ( ! tld . isValid ( data . zoneName ) ) throw new BoxError ( BoxError . BAD _FIELD , 'Invalid zoneName' ) ;
2024-04-29 15:51:16 +02:00
if ( data . zoneName . endsWith ( '.' ) ) throw new BoxError ( BoxError . BAD _FIELD , 'Invalid zoneName' ) ;
2024-04-29 13:05:07 +02:00
zoneName = data . zoneName ;
2018-01-23 18:54:05 -08:00
} else {
2018-01-24 14:17:26 -08:00
zoneName = tld . getDomain ( domain ) || domain ;
2018-01-23 18:54:05 -08:00
}
2017-10-28 22:18:07 +02:00
2024-04-29 13:05:07 +02:00
let fallbackCertificate ;
if ( data . fallbackCertificate ) {
await reverseProxy . validateCertificate ( 'test' , domain , data . fallbackCertificate ) ;
fallbackCertificate = data . fallbackCertificate ;
2018-11-05 19:09:58 -08:00
} else {
2021-08-17 14:04:29 -07:00
fallbackCertificate = await reverseProxy . generateFallbackCertificate ( domain ) ;
2017-11-09 02:06:36 +01:00
}
2018-09-12 12:25:07 -07:00
let error = validateTlsConfig ( tlsConfig , provider ) ;
2021-08-13 17:22:28 -07:00
if ( error ) throw error ;
2018-01-31 18:20:11 +01:00
2023-08-04 20:54:16 +05:30
const dkimKey = await mailServer . generateDkimKey ( ) ;
2021-10-11 19:51:29 -07:00
2024-04-29 13:05:07 +02:00
let dkimSelector = data . dkimSelector ;
if ( ! data . dkimSelector ) {
2023-08-11 19:41:05 +05:30
const { domain : dashboardDomain } = await dashboard . getLocation ( ) ;
2021-02-24 11:40:23 -08:00
// create a unique suffix. this lets one add this domain can be added in another cloudron instance and not have their dkim selector conflict
2023-08-11 19:41:05 +05:30
const suffix = crypto . createHash ( 'sha256' ) . update ( dashboardDomain ) . digest ( 'hex' ) . substr ( 0 , 6 ) ;
2021-02-24 11:40:23 -08:00
dkimSelector = ` cloudron- ${ suffix } ` ;
}
2020-03-31 12:04:46 -07:00
2022-07-14 10:32:30 +05:30
const sanitizedConfig = await verifyDomainConfig ( config , domain , zoneName , provider ) ;
2017-10-28 23:23:58 +02:00
2022-07-14 10:32:30 +05:30
const queries = [
2021-08-13 17:22:28 -07:00
{ query : 'INSERT INTO domains (domain, zoneName, provider, configJson, tlsConfigJson, fallbackCertificateJson) VALUES (?, ?, ?, ?, ?, ?)' ,
2022-07-14 10:32:30 +05:30
args : [ domain , zoneName , provider , JSON . stringify ( sanitizedConfig ) , JSON . stringify ( tlsConfig ) , JSON . stringify ( fallbackCertificate ) ] } ,
2021-10-11 19:51:29 -07:00
{ query : 'INSERT INTO mail (domain, dkimKeyJson, dkimSelector) VALUES (?, ?, ?)' , args : [ domain , JSON . stringify ( dkimKey ) , dkimSelector || 'cloudron' ] } ,
2021-08-13 17:22:28 -07:00
] ;
2017-10-28 23:23:58 +02:00
2021-08-13 17:22:28 -07:00
[ error ] = await safe ( database . transaction ( queries ) ) ;
2025-09-29 11:55:15 +02:00
if ( error && error . sqlCode === 'ER_DUP_ENTRY' ) throw new BoxError ( BoxError . ALREADY _EXISTS , 'Domain already exists' ) ;
2021-08-13 17:22:28 -07:00
if ( error ) throw new BoxError ( BoxError . DATABASE _ERROR , error ) ;
2018-01-26 19:16:43 -08:00
2021-08-13 17:22:28 -07:00
await reverseProxy . setFallbackCertificate ( domain , fallbackCertificate ) ;
2020-03-31 12:04:46 -07:00
2022-02-24 20:04:46 -08:00
await eventlog . add ( eventlog . ACTION _DOMAIN _ADD , auditSource , { domain , zoneName , provider } ) ;
2021-08-13 17:22:28 -07:00
2023-08-04 20:54:16 +05:30
safe ( mailServer . onDomainAdded ( domain ) , { debug } ) ; // background
2017-10-28 22:18:07 +02:00
}
2021-08-13 17:22:28 -07:00
async function get ( domain ) {
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof domain , 'string' ) ;
2021-08-13 17:22:28 -07:00
const result = await database . query ( ` SELECT ${ DOMAINS _FIELDS } FROM domains WHERE domain=? ` , [ domain ] ) ;
if ( result . length === 0 ) return null ;
return postProcess ( result [ 0 ] ) ;
2017-10-28 22:18:07 +02:00
}
2021-08-13 17:22:28 -07:00
async function list ( ) {
const results = await database . query ( ` SELECT ${ DOMAINS _FIELDS } FROM domains ORDER BY domain ` ) ;
2025-04-28 16:36:37 +02:00
2021-08-13 17:22:28 -07:00
results . forEach ( postProcess ) ;
2025-04-28 16:36:37 +02:00
2025-10-17 18:55:22 +02:00
return results . sort ( ( d1 , d2 ) => { // domains are alphabetically sorted
return d1 . domain . localeCompare ( d2 . domain ) ;
2025-05-06 10:03:20 +02:00
} ) ;
2017-10-28 22:18:07 +02:00
}
2021-12-03 13:46:54 -08:00
async function setConfig ( domain , data , auditSource ) {
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof domain , 'string' ) ;
2018-11-10 00:43:46 -08:00
assert . strictEqual ( typeof data . zoneName , 'string' ) ;
assert . strictEqual ( typeof data . provider , 'string' ) ;
assert . strictEqual ( typeof data . config , 'object' ) ;
assert . strictEqual ( typeof data . fallbackCertificate , 'object' ) ;
assert . strictEqual ( typeof data . tlsConfig , 'object' ) ;
assert . strictEqual ( typeof auditSource , 'object' ) ;
2017-10-28 22:18:07 +02:00
2024-04-29 13:05:07 +02:00
const { provider , config , fallbackCertificate , tlsConfig } = data ;
2023-08-11 19:41:05 +05:30
const { domain : dashboardDomain } = await dashboard . getLocation ( ) ;
2024-01-13 21:15:41 +01:00
if ( constants . DEMO && ( domain === dashboardDomain ) ) throw new BoxError ( BoxError . BAD _STATE , 'Not allowed in demo mode' ) ;
2020-02-19 10:45:55 -08:00
2021-08-13 17:22:28 -07:00
const domainObject = await get ( domain ) ;
2024-04-29 13:05:07 +02:00
let zoneName ;
if ( data . zoneName ) {
2025-02-05 10:51:05 +01:00
if ( ! tld . isValid ( data . zoneName ) ) throw new BoxError ( BoxError . BAD _FIELD , 'Invalid zoneName' ) ;
2024-04-29 13:05:07 +02:00
zoneName = data . zoneName ;
2021-08-13 17:22:28 -07:00
} else {
zoneName = domainObject . zoneName ;
}
2017-10-28 22:18:07 +02:00
2024-02-21 12:33:04 +01:00
if ( fallbackCertificate ) await reverseProxy . validateCertificate ( 'test' , domain , fallbackCertificate ) ;
2018-05-15 13:51:00 -07:00
2022-07-14 10:35:59 +05:30
const tlsConfigError = validateTlsConfig ( tlsConfig , provider ) ;
if ( tlsConfigError ) throw tlsConfigError ;
2017-11-09 02:06:36 +01:00
2021-08-13 17:22:28 -07:00
if ( provider === domainObject . provider ) api ( provider ) . injectPrivateFields ( config , domainObject . config ) ;
2020-12-23 15:34:23 -08:00
2022-07-14 10:32:30 +05:30
const sanitizedConfig = await verifyDomainConfig ( config , domain , zoneName , provider ) ;
2017-10-28 23:23:58 +02:00
2021-08-27 09:52:24 -07:00
const newData = {
2022-07-14 10:32:30 +05:30
config : sanitizedConfig ,
2021-08-13 17:22:28 -07:00
zoneName ,
provider ,
tlsConfig ,
} ;
2019-02-08 20:35:05 -08:00
2021-08-13 17:22:28 -07:00
if ( fallbackCertificate ) newData . fallbackCertificate = fallbackCertificate ;
2021-05-04 21:40:11 -07:00
2022-07-14 10:32:30 +05:30
const args = [ ] , fields = [ ] ;
2021-08-13 17:22:28 -07:00
for ( const k in newData ) {
2021-12-03 13:46:54 -08:00
if ( k === 'config' || k === 'tlsConfig' || k === 'fallbackCertificate' ) { // json fields
2021-08-13 17:22:28 -07:00
fields . push ( ` ${ k } Json = ? ` ) ;
args . push ( JSON . stringify ( newData [ k ] ) ) ;
} else {
fields . push ( k + ' = ?' ) ;
args . push ( newData [ k ] ) ;
}
}
args . push ( domain ) ;
2017-10-28 23:23:58 +02:00
2022-07-14 10:35:59 +05:30
const result = await database . query ( 'UPDATE domains SET ' + fields . join ( ', ' ) + ' WHERE domain=?' , args ) ;
if ( result . affectedRows === 0 ) throw new BoxError ( BoxError . NOT _FOUND , 'Domain not found' ) ;
2018-01-26 22:27:32 -08:00
2022-11-14 10:58:32 +01:00
if ( fallbackCertificate ) await reverseProxy . setFallbackCertificate ( domain , fallbackCertificate ) ;
2022-11-29 18:11:22 +01:00
if ( ! _ . isEqual ( domainObject . tlsConfig , tlsConfig . provider ) ) await reverseProxy . handleCertificateProviderChanged ( domain ) ;
2018-11-10 00:43:46 -08:00
2022-02-24 20:04:46 -08:00
await eventlog . add ( eventlog . ACTION _DOMAIN _UPDATE , auditSource , { domain , zoneName , provider } ) ;
2017-10-28 22:18:07 +02:00
}
2021-12-03 13:46:54 -08:00
async function setWellKnown ( domain , wellKnown , auditSource ) {
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof wellKnown , 'object' ) ;
assert . strictEqual ( typeof auditSource , 'object' ) ;
2022-07-14 10:35:59 +05:30
const wellKnownError = validateWellKnown ( wellKnown ) ;
if ( wellKnownError ) throw wellKnownError ;
2021-12-03 13:46:54 -08:00
2022-07-14 10:35:59 +05:30
const result = await database . query ( 'UPDATE domains SET wellKnownJson = ? WHERE domain=?' , [ JSON . stringify ( wellKnown ) , domain ] ) ;
if ( result . affectedRows === 0 ) throw new BoxError ( BoxError . NOT _FOUND , 'Domain not found' ) ;
2021-12-03 13:46:54 -08:00
2022-02-24 20:04:46 -08:00
await eventlog . add ( eventlog . ACTION _DOMAIN _UPDATE , auditSource , { domain , wellKnown } ) ;
2021-12-03 13:46:54 -08:00
}
2021-08-13 17:22:28 -07:00
async function del ( domain , auditSource ) {
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof domain , 'string' ) ;
2018-11-10 00:43:46 -08:00
assert . strictEqual ( typeof auditSource , 'object' ) ;
2018-01-23 20:25:45 -08:00
2023-08-11 19:41:05 +05:30
const { domain : dashboardDomain } = await dashboard . getLocation ( ) ;
if ( domain === dashboardDomain ) throw new BoxError ( BoxError . CONFLICT , 'Cannot remove admin domain' ) ;
2023-08-04 21:37:38 +05:30
const { domain : mailDomain } = await mailServer . getLocation ( ) ;
if ( domain === mailDomain ) throw new BoxError ( BoxError . CONFLICT , 'Cannot remove mail domain. Change the mail server location first' ) ;
2018-01-23 20:25:45 -08:00
2024-04-29 13:05:07 +02:00
const queries = [
2021-08-13 17:22:28 -07:00
{ query : 'DELETE FROM mail WHERE domain = ?' , args : [ domain ] } ,
{ query : 'DELETE FROM domains WHERE domain = ?' , args : [ domain ] } ,
] ;
2017-10-29 00:15:11 +02:00
2021-08-13 17:22:28 -07:00
const [ error , results ] = await safe ( database . transaction ( queries ) ) ;
2025-09-29 11:55:15 +02:00
console . dir ( error ) ;
if ( error && error . sqlCode === 'ER_ROW_IS_REFERENCED_2' ) {
2024-01-02 17:18:37 +01:00
if ( error . message . includes ( 'mailboxes_aliasDomain_constraint' ) ) throw new BoxError ( BoxError . CONFLICT , 'Domain is in use in a mailbox, list or an alias' ) ;
2023-07-08 17:46:51 +05:30
if ( error . message . includes ( 'mailboxes_domain_constraint' ) ) throw new BoxError ( BoxError . CONFLICT , 'Domain is in use in a mailbox, list or an alias' ) ;
if ( error . message . includes ( 'apps_mailDomain_constraint' ) ) throw new BoxError ( BoxError . CONFLICT , 'Domain is in use in an app\'s mailbox section' ) ;
if ( error . message . includes ( 'locations' ) ) throw new BoxError ( BoxError . CONFLICT , 'Domain is in use in an app\'s location' ) ;
2021-08-13 17:22:28 -07:00
throw new BoxError ( BoxError . CONFLICT , error . message ) ;
}
if ( error ) throw error ;
if ( results [ 1 ] . affectedRows !== 1 ) throw new BoxError ( BoxError . NOT _FOUND , 'Domain not found' ) ;
2017-10-29 00:15:11 +02:00
2022-02-24 20:04:46 -08:00
await eventlog . add ( eventlog . ACTION _DOMAIN _REMOVE , auditSource , { domain } ) ;
2017-10-29 00:15:11 +02:00
2023-08-04 20:54:16 +05:30
safe ( mailServer . onDomainRemoved ( domain ) ) ;
2017-11-21 19:18:03 -08:00
}
2017-10-29 00:15:11 +02:00
2021-08-13 17:22:28 -07:00
async function clear ( ) {
await database . query ( 'DELETE FROM domains' ) ;
2017-11-11 22:02:34 +01:00
}
2018-01-01 19:19:07 -08:00
2018-06-25 15:12:20 -07:00
// removes all fields that are strictly private and should never be returned by API calls
2018-04-27 11:38:09 -07:00
function removePrivateFields ( domain ) {
2025-02-13 14:03:25 +01:00
const result = _ . pick ( domain , [ 'domain' , 'zoneName' , 'provider' , 'config' , 'tlsConfig' , 'fallbackCertificate' , 'wellKnown' ] ) ;
2024-04-30 09:47:48 +02:00
const out = api ( result . provider ) . removePrivateFields ( result ) ;
delete out . fallbackCertificate . key ;
return out ;
2018-04-29 11:20:12 -07:00
}
2018-06-25 15:12:20 -07:00
2024-04-30 09:47:48 +02:00
// removes all fields that are not accessible by a normal user. currently, this is same as for admin users since config tokens are removed
2018-06-25 15:12:20 -07:00
function removeRestrictedFields ( domain ) {
2024-04-30 09:47:48 +02:00
return removePrivateFields ( domain ) ;
2018-09-05 22:58:43 -07:00
}
2022-11-11 18:09:10 +01:00
async function getDomainObjectMap ( ) {
const domainObjects = await list ( ) ;
2024-04-29 13:05:07 +02:00
const domainObjectMap = { } ;
for ( const d of domainObjects ) { domainObjectMap [ d . domain ] = d ; }
2022-11-11 18:09:10 +01:00
return domainObjectMap ;
}
2025-02-17 19:01:53 +01:00
async function checkConfigs ( auditSource ) {
assert . strictEqual ( typeof auditSource , 'object' ) ;
debug ( ` checkConfig: validating domain configs ` ) ;
for ( const domainObject of await list ( ) ) {
if ( domainObject . provider === 'noop' || domainObject . provider === 'manual' || domainObject . provider === 'wildcard' ) {
await notifications . unpin ( notifications . TYPE _DOMAIN _CONFIG _CHECK _FAILED , { context : domainObject . domain } ) ;
continue ;
}
const [ error ] = await safe ( api ( domainObject . provider ) . verifyDomainConfig ( domainObject ) ) ;
if ( ! error ) {
await notifications . unpin ( notifications . TYPE _DOMAIN _CONFIG _CHECK _FAILED , { context : domainObject . domain } ) ;
continue ;
}
let errorMessage ;
if ( error . reason === BoxError . ACCESS _DENIED ) {
errorMessage = ` Access denied: ${ error . message } ` ;
} else if ( error . reason === BoxError . NOT _FOUND ) {
errorMessage = ` Zone not found: ${ error . message } ` ;
} else if ( error . reason === BoxError . EXTERNAL _ERROR ) {
errorMessage = ` Configuration error: ${ error . message } ` ;
} else {
errorMessage = ` General error: ${ error . message } ` ;
}
await notifications . pin ( notifications . TYPE _DOMAIN _CONFIG _CHECK _FAILED , ` Domain ${ domainObject . domain } is not configured properly ` ,
errorMessage , { context : domainObject . domain } ) ;
}
}