2017-10-28 22:18:07 +02:00
'use strict' ;
exports = module . exports = {
2021-02-24 18:42:39 -08:00
add ,
get ,
2021-08-13 17:22:28 -07:00
list ,
2021-12-03 13:46:54 -08:00
setConfig ,
setWellKnown ,
2021-02-24 18:42:39 -08:00
del ,
2018-09-05 22:58:43 -07:00
2021-02-24 18:42:39 -08:00
checkDnsRecords ,
2023-08-04 12:53:11 +05:30
syncDnsRecords ,
2017-10-28 22:18:07 +02:00
} ;
2021-05-04 21:40:11 -07:00
const assert = require ( 'assert' ) ,
2021-09-30 09:50:30 -07:00
AuditSource = require ( '../auditsource.js' ) ,
2019-10-23 10:02:04 -07:00
BoxError = require ( '../boxerror.js' ) ,
2021-08-13 17:22:28 -07:00
dns = require ( '../dns.js' ) ,
2017-10-28 22:18:07 +02:00
domains = require ( '../domains.js' ) ,
HttpError = require ( 'connect-lastmile' ) . HttpError ,
2021-08-13 17:22:28 -07:00
HttpSuccess = require ( 'connect-lastmile' ) . HttpSuccess ,
safe = require ( 'safetydance' ) ;
2018-10-24 13:01:45 -07:00
2021-08-13 17:22:28 -07:00
async function add ( req , res , next ) {
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof req . body , 'object' ) ;
if ( typeof req . body . domain !== 'string' ) return next ( new HttpError ( 400 , 'domain must be a string' ) ) ;
2018-01-09 14:46:38 -08:00
if ( typeof req . body . provider !== 'string' ) return next ( new HttpError ( 400 , 'provider must be a string' ) ) ;
2018-09-11 22:17:40 -07:00
if ( ! req . body . config || typeof req . body . config !== 'object' ) return next ( new HttpError ( 400 , 'config must be an object' ) ) ;
2018-09-11 22:46:17 -07:00
if ( 'wildcard' in req . body . config && typeof req . body . config . wildcard !== 'boolean' ) return next ( new HttpError ( 400 , 'wildcard must be a boolean' ) ) ;
2018-09-11 22:17:40 -07:00
2017-11-07 02:15:55 +01:00
if ( 'zoneName' in req . body && typeof req . body . zoneName !== 'string' ) return next ( new HttpError ( 400 , 'zoneName must be a string' ) ) ;
2017-11-09 02:06:36 +01:00
if ( 'fallbackCertificate' in req . body && typeof req . body . fallbackCertificate !== 'object' ) return next ( new HttpError ( 400 , 'fallbackCertificate must be a object with cert and key strings' ) ) ;
2018-10-30 18:11:10 -07:00
if ( req . body . fallbackCertificate ) {
2018-11-05 21:13:34 -08:00
let fallbackCertificate = req . body . fallbackCertificate ;
if ( ! fallbackCertificate . cert || typeof fallbackCertificate . cert !== 'string' ) return next ( new HttpError ( 400 , 'fallbackCertificate.cert must be a string' ) ) ;
if ( ! fallbackCertificate . key || typeof fallbackCertificate . key !== 'string' ) return next ( new HttpError ( 400 , 'fallbackCertificate.key must be a string' ) ) ;
2018-10-30 18:11:10 -07:00
}
2018-09-11 22:17:40 -07:00
if ( 'tlsConfig' in req . body ) {
if ( ! req . body . tlsConfig || typeof req . body . tlsConfig !== 'object' ) return next ( new HttpError ( 400 , 'tlsConfig must be a object with a provider string property' ) ) ;
if ( ! req . body . tlsConfig . provider || typeof req . body . tlsConfig . provider !== 'string' ) return next ( new HttpError ( 400 , 'tlsConfig.provider must be a string' ) ) ;
}
2017-10-28 22:18:07 +02:00
2018-03-08 09:27:56 -08:00
// some DNS providers like DigitalOcean take a really long time to verify credentials (https://github.com/expressjs/timeout/issues/26)
req . clearTimeout ( ) ;
2018-11-10 00:43:46 -08:00
let data = {
zoneName : req . body . zoneName || '' ,
provider : req . body . provider ,
config : req . body . config ,
fallbackCertificate : req . body . fallbackCertificate || null ,
tlsConfig : req . body . tlsConfig || { provider : 'letsencrypt-prod' }
} ;
2021-09-30 09:50:30 -07:00
const [ error ] = await safe ( domains . add ( req . body . domain , data , AuditSource . fromRequest ( req ) ) ) ;
2021-08-13 17:22:28 -07:00
if ( error ) return next ( BoxError . toHttpError ( error ) ) ;
2017-10-28 22:18:07 +02:00
2021-08-13 17:22:28 -07:00
next ( new HttpSuccess ( 201 , { } ) ) ;
2017-10-28 22:18:07 +02:00
}
2021-08-13 17:22:28 -07:00
async function get ( req , res , next ) {
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof req . params . domain , 'string' ) ;
2021-08-13 17:22:28 -07:00
const [ error , result ] = await safe ( domains . get ( req . params . domain ) ) ;
if ( error ) return next ( BoxError . toHttpError ( error ) ) ;
if ( ! result ) return next ( new HttpError ( 404 , 'Domain not found' ) ) ;
2017-10-28 22:18:07 +02:00
2021-08-13 17:22:28 -07:00
next ( new HttpSuccess ( 200 , domains . removePrivateFields ( result ) ) ) ;
2017-10-28 22:18:07 +02:00
}
2021-08-13 17:22:28 -07:00
async function list ( req , res , next ) {
let [ error , results ] = await safe ( domains . list ( ) ) ;
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
2018-04-27 11:38:09 -07:00
2021-08-13 17:22:28 -07:00
results = results . map ( domains . removeRestrictedFields ) ;
next ( new HttpSuccess ( 200 , { domains : results } ) ) ;
2017-10-28 22:18:07 +02:00
}
2021-12-03 13:46:54 -08:00
async function setConfig ( req , res , next ) {
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof req . params . domain , 'string' ) ;
assert . strictEqual ( typeof req . body , 'object' ) ;
2018-01-09 14:46:38 -08:00
if ( typeof req . body . provider !== 'string' ) return next ( new HttpError ( 400 , 'provider must be an object' ) ) ;
2018-09-11 22:17:40 -07:00
if ( ! req . body . config || typeof req . body . config !== 'object' ) return next ( new HttpError ( 400 , 'config must be an object' ) ) ;
2018-09-11 22:46:17 -07:00
if ( 'wildcard' in req . body . config && typeof req . body . config . wildcard !== 'boolean' ) return next ( new HttpError ( 400 , 'wildcard must be a boolean' ) ) ;
2018-09-11 22:17:40 -07:00
2018-05-15 13:51:00 -07:00
if ( 'zoneName' in req . body && typeof req . body . zoneName !== 'string' ) return next ( new HttpError ( 400 , 'zoneName must be a string' ) ) ;
2017-11-09 02:06:36 +01:00
if ( 'fallbackCertificate' in req . body && typeof req . body . fallbackCertificate !== 'object' ) return next ( new HttpError ( 400 , 'fallbackCertificate must be a object with cert and key strings' ) ) ;
2018-11-05 21:13:34 -08:00
if ( req . body . fallbackCertificate ) {
let fallbackCertificate = req . body . fallbackCertificate ;
if ( ! fallbackCertificate . cert || typeof fallbackCertificate . cert !== 'string' ) return next ( new HttpError ( 400 , 'fallbackCertificate.cert must be a string' ) ) ;
if ( ! fallbackCertificate . key || typeof fallbackCertificate . key !== 'string' ) return next ( new HttpError ( 400 , 'fallbackCertificate.key must be a string' ) ) ;
}
2018-09-11 22:17:40 -07:00
if ( 'tlsConfig' in req . body ) {
if ( ! req . body . tlsConfig || typeof req . body . tlsConfig !== 'object' ) return next ( new HttpError ( 400 , 'tlsConfig must be a object with a provider string property' ) ) ;
if ( ! req . body . tlsConfig . provider || typeof req . body . tlsConfig . provider !== 'string' ) return next ( new HttpError ( 400 , 'tlsConfig.provider must be a string' ) ) ;
}
2017-10-28 22:18:07 +02:00
2018-03-08 09:27:56 -08:00
// some DNS providers like DigitalOcean take a really long time to verify credentials (https://github.com/expressjs/timeout/issues/26)
req . clearTimeout ( ) ;
2021-12-03 13:46:54 -08:00
const data = {
2018-11-10 00:43:46 -08:00
zoneName : req . body . zoneName || '' ,
provider : req . body . provider ,
config : req . body . config ,
fallbackCertificate : req . body . fallbackCertificate || null ,
2021-12-03 13:46:54 -08:00
tlsConfig : req . body . tlsConfig || { provider : 'letsencrypt-prod' }
2018-11-10 00:43:46 -08:00
} ;
2021-12-03 13:46:54 -08:00
const [ error ] = await safe ( domains . setConfig ( req . params . domain , data , AuditSource . fromRequest ( req ) ) ) ;
if ( error ) return next ( BoxError . toHttpError ( error ) ) ;
next ( new HttpSuccess ( 204 , { } ) ) ;
}
async function setWellKnown ( req , res , next ) {
assert . strictEqual ( typeof req . params . domain , 'string' ) ;
assert . strictEqual ( typeof req . body , 'object' ) ;
if ( typeof req . body . wellKnown !== 'object' ) return next ( new HttpError ( 400 , 'wellKnown must be an object' ) ) ;
if ( req . body . wellKnown ) {
if ( Object . keys ( req . body . wellKnown ) . some ( k => typeof req . body . wellKnown [ k ] !== 'string' ) ) return next ( new HttpError ( 400 , 'wellKnown is a map of strings' ) ) ;
}
const [ error ] = await safe ( domains . setWellKnown ( req . params . domain , req . body . wellKnown || null , AuditSource . fromRequest ( req ) ) ) ;
2021-08-13 17:22:28 -07:00
if ( error ) return next ( BoxError . toHttpError ( error ) ) ;
2017-10-28 22:18:07 +02:00
2021-08-13 17:22:28 -07:00
next ( new HttpSuccess ( 204 , { } ) ) ;
2017-10-28 22:18:07 +02:00
}
2021-08-13 17:22:28 -07:00
async function del ( req , res , next ) {
2017-10-28 22:18:07 +02:00
assert . strictEqual ( typeof req . params . domain , 'string' ) ;
2021-09-30 09:50:30 -07:00
const [ error ] = await safe ( domains . del ( req . params . domain , AuditSource . fromRequest ( req ) ) ) ;
2021-08-13 17:22:28 -07:00
if ( error ) return next ( BoxError . toHttpError ( error ) ) ;
2017-10-28 22:18:07 +02:00
2021-08-13 17:22:28 -07:00
next ( new HttpSuccess ( 204 ) ) ;
2017-10-28 22:18:07 +02:00
}
2019-09-19 15:10:27 -07:00
2021-08-27 09:52:24 -07:00
async function checkDnsRecords ( req , res , next ) {
2019-09-20 01:55:28 +02:00
assert . strictEqual ( typeof req . params . domain , 'string' ) ;
2019-09-19 15:10:27 -07:00
if ( ! ( 'subdomain' in req . query ) ) return next ( new HttpError ( 400 , 'subdomain is required' ) ) ;
2019-09-23 18:17:05 -07:00
// some DNS providers like DigitalOcean take a really long time to verify credentials (https://github.com/expressjs/timeout/issues/26)
req . clearTimeout ( ) ;
2021-08-27 09:52:24 -07:00
const [ error , result ] = await safe ( dns . checkDnsRecords ( req . query . subdomain , req . params . domain ) ) ;
if ( error && error . reason === BoxError . ACCESS _DENIED ) return next ( new HttpSuccess ( 200 , { error : { reason : error . reason , message : error . message } } ) ) ;
if ( error ) return next ( BoxError . toHttpError ( error ) ) ;
2019-09-19 15:10:27 -07:00
2021-08-27 09:52:24 -07:00
next ( new HttpSuccess ( 200 , { needsOverwrite : result . needsOverwrite } ) ) ;
2020-02-13 21:12:49 -08:00
}
2023-08-04 12:53:11 +05:30
async function syncDnsRecords ( req , res , next ) {
assert . strictEqual ( typeof req . body , 'object' ) ;
if ( 'domain' in req . body && typeof req . body . domain !== 'string' ) return next ( new HttpError ( 400 , 'domain must be a string' ) ) ;
if ( 'type' in req . body && typeof req . body . type !== 'string' ) return next ( new HttpError ( 400 , 'type must be a string' ) ) ;
const [ error , taskId ] = await safe ( dns . startSyncDnsRecords ( req . body ) ) ;
if ( error && error . reason === BoxError . ACCESS _DENIED ) return next ( new HttpSuccess ( 200 , { error : { reason : error . reason , message : error . message } } ) ) ;
if ( error ) return next ( BoxError . toHttpError ( error ) ) ;
next ( new HttpSuccess ( 201 , { taskId } ) ) ;
}