Files
cloudron-box/src/routes/domains.js
T

171 lines
8.1 KiB
JavaScript
Raw Normal View History

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,
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,
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'));
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-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
// 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
}
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
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
// some DNS providers like DigitalOcean take a really long time to verify credentials (https://github.com/expressjs/timeout/issues/26)
req.clearTimeout();
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,
tlsConfig: req.body.tlsConfig || { provider: 'letsencrypt-prod' }
2018-11-10 00:43:46 -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
}
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 }));
}