122 lines
5.5 KiB
JavaScript
122 lines
5.5 KiB
JavaScript
'use strict';
|
|
|
|
var async = require('async'),
|
|
crypto = require('crypto'),
|
|
fs = require('fs'),
|
|
os = require('os'),
|
|
path = require('path'),
|
|
safe = require('safetydance'),
|
|
tldjs = require('tldjs');
|
|
|
|
exports.up = function(db, callback) {
|
|
db.all('SELECT * FROM apps', function (error, apps) {
|
|
if (error) return callback(error);
|
|
|
|
async.eachSeries(apps, function (app, callback) {
|
|
if (!app.altDomain) {
|
|
console.log('App %s does not use altDomain, skip', app.id);
|
|
return callback();
|
|
}
|
|
|
|
const domain = tldjs.getDomain(app.altDomain);
|
|
const subdomain = tldjs.getSubdomain(app.altDomain);
|
|
const mailboxName = (subdomain ? subdomain : JSON.parse(app.manifestJson).title.toLowerCase().replace(/[^a-zA-Z0-9]/g, '')) + '.app';
|
|
|
|
console.log('App %s is on domain %s and subdomain %s with mailbox', app.id, domain, subdomain, mailboxName);
|
|
|
|
async.series([
|
|
// Add domain if not exists
|
|
function (callback) {
|
|
const query = 'INSERT INTO domains (domain, zoneName, provider, configJson, tlsConfigJson) VALUES (?, ?, ?, ?, ?)';
|
|
const args = [ domain, domain, 'manual', JSON.stringify({}), JSON.stringify({ provider: 'letsencrypt-prod' }) ];
|
|
|
|
db.runSql(query, args, function (error) {
|
|
if (error && error.code !== 'ER_DUP_ENTRY') return callback(error);
|
|
|
|
console.log('Added domain %s', domain);
|
|
|
|
// ensure we have a fallback cert for the newly added domain. This is the same as in reverseproxy.js
|
|
// WARNING this will only work on the cloudron itself not during local testing!
|
|
const certFilePath = `/home/yellowtent/boxdata/certs/${domain}.host.cert`;
|
|
const keyFilePath = `/home/yellowtent/boxdata/certs/${domain}.host.key`;
|
|
|
|
if (!fs.existsSync(certFilePath) || !fs.existsSync(keyFilePath)) { // generate it
|
|
let opensslConf = safe.fs.readFileSync('/etc/ssl/openssl.cnf', 'utf8');
|
|
let opensslConfWithSan = `${opensslConf}\n[SAN]\nsubjectAltName=DNS:${domain}\n`;
|
|
let configFile = path.join(os.tmpdir(), 'openssl-' + crypto.randomBytes(4).readUInt32LE(0) + '.conf');
|
|
let certCommand = `openssl req -x509 -newkey rsa:2048 -keyout ${keyFilePath} -out ${certFilePath} -days 3650 -subj /CN=*.${domain} -extensions SAN -config ${configFile} -nodes`;
|
|
|
|
safe.fs.writeFileSync(configFile, opensslConfWithSan, 'utf8');
|
|
if (!safe.child_process.execSync(certCommand)) return callback(safe.error.message);
|
|
safe.fs.unlinkSync(configFile);
|
|
}
|
|
|
|
callback();
|
|
});
|
|
},
|
|
// Add domain to mail table if not exists
|
|
function (callback) {
|
|
const query = 'INSERT INTO mail (domain, enabled, mailFromValidation, catchAllJson, relayJson) VALUES (?, ?, ?, ?, ?)';
|
|
const args = [ domain, 0, 1, '[]', JSON.stringify({ provider: 'cloudron-smtp' }) ];
|
|
|
|
db.runSql(query, args, function (error) {
|
|
if (error && error.code !== 'ER_DUP_ENTRY') return callback(error);
|
|
|
|
console.log('Added domain %s to mail table', domain);
|
|
|
|
callback();
|
|
});
|
|
},
|
|
// Remove old mailbox record if any
|
|
function (callback) {
|
|
const query = 'DELETE FROM mailboxes WHERE ownerId=?';
|
|
const args = [ app.id ];
|
|
|
|
db.runSql(query, args, function (error) {
|
|
if (error) return callback(error);
|
|
|
|
console.log('Cleaned up mailbox record for app %s', app.id);
|
|
|
|
callback();
|
|
});
|
|
},
|
|
// Add new mailbox record
|
|
function (callback) {
|
|
const query = 'INSERT INTO mailboxes (name, domain, ownerId, ownerType) VALUES (?, ?, ?, ?)';
|
|
const args = [ mailboxName, domain, app.id, 'app' /* mailboxdb.TYPE_APP */ ];
|
|
|
|
db.runSql(query, args, function (error) {
|
|
if (error) return callback(error);
|
|
|
|
console.log('Added mailbox record for app %s', app.id);
|
|
|
|
callback();
|
|
});
|
|
},
|
|
// Update app record
|
|
function (callback) {
|
|
const query = 'UPDATE apps SET location=?, domain=?, altDomain=? WHERE id=?';
|
|
const args = [ subdomain, domain, '', app.id ];
|
|
|
|
db.runSql(query, args, function (error) {
|
|
if (error) return error;
|
|
|
|
console.log('Updated app %s with new domain', app.id);
|
|
|
|
callback();
|
|
});
|
|
}
|
|
], callback);
|
|
}, function (error) {
|
|
if (error) return callback(error);
|
|
|
|
// finally drop the altDomain db field
|
|
db.runSql('ALTER TABLE apps DROP COLUMN altDomain', [], callback);
|
|
});
|
|
});
|
|
};
|
|
|
|
exports.down = function(db, callback) {
|
|
db.runSql('ALTER TABLE apps ADD COLUMN altDomain VARCHAR(256)', [], callback);
|
|
};
|