LOCATION_TYPE can move into location.js

This commit is contained in:
Girish Ramakrishnan
2023-08-17 16:05:19 +05:30
parent 5c98b6f080
commit 28bfab6700
3 changed files with 59 additions and 71 deletions
+37 -49
View File
@@ -132,17 +132,6 @@ exports = module.exports = {
HEALTH_ERROR: 'error',
HEALTH_DEAD: 'dead',
// subdomain table types
LOCATION_TYPE_PRIMARY: 'primary',
LOCATION_TYPE_SECONDARY: 'secondary',
LOCATION_TYPE_REDIRECT: 'redirect',
LOCATION_TYPE_ALIAS: 'alias',
// should probably be in table as well
LOCATION_TYPE_DASHBOARD: 'dashboard',
LOCATION_TYPE_MAIL: 'mail',
LOCATION_TYPE_DIRECTORY_SERVER: 'directoryserver',
// exported for testing
_validatePortBindings: validatePortBindings,
_validateAccessRestriction: validateAccessRestriction,
@@ -168,6 +157,7 @@ const appstore = require('./appstore.js'),
domains = require('./domains.js'),
eventlog = require('./eventlog.js'),
fs = require('fs'),
Location = require('./location.js'),
logs = require('./logs.js'),
mail = require('./mail.js'),
manifestFormat = require('cloudron-manifestformat'),
@@ -715,15 +705,15 @@ function postProcess(result) {
for (let i = 0; i < subdomainTypes.length; i++) {
const subdomain = subdomains[i], domain = domains[i], certificate = safe.JSON.parse(subdomainCertificateJsons[i]);
if (subdomainTypes[i] === exports.LOCATION_TYPE_PRIMARY) {
if (subdomainTypes[i] === Location.TYPE_PRIMARY) {
result.subdomain = subdomain;
result.domain = domain;
result.certificate = certificate;
} else if (subdomainTypes[i] === exports.LOCATION_TYPE_SECONDARY) {
} else if (subdomainTypes[i] === Location.TYPE_SECONDARY) {
result.secondaryDomains.push({ domain, subdomain, certificate, environmentVariable: subdomainEnvironmentVariables[i] });
} else if (subdomainTypes[i] === exports.LOCATION_TYPE_REDIRECT) {
} else if (subdomainTypes[i] === Location.TYPE_REDIRECT) {
result.redirectDomains.push({ domain, subdomain, certificate });
} else if (subdomainTypes[i] === exports.LOCATION_TYPE_ALIAS) {
} else if (subdomainTypes[i] === Location.TYPE_ALIAS) {
result.aliasDomains.push({ domain, subdomain, certificate });
}
}
@@ -852,7 +842,7 @@ async function add(id, appStoreId, manifest, subdomain, domain, portBindings, da
queries.push({
query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)',
args: [ id, domain, subdomain, exports.LOCATION_TYPE_PRIMARY ]
args: [ id, domain, subdomain, Location.TYPE_PRIMARY ]
});
Object.keys(portBindings).forEach(function (env) {
@@ -873,7 +863,7 @@ async function add(id, appStoreId, manifest, subdomain, domain, portBindings, da
data.secondaryDomains.forEach(function (d) {
queries.push({
query: 'INSERT INTO locations (appId, domain, subdomain, type, environmentVariable) VALUES (?, ?, ?, ?, ?)',
args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_SECONDARY, d.environmentVariable ]
args: [ id, d.domain, d.subdomain, Location.TYPE_SECONDARY, d.environmentVariable ]
});
});
}
@@ -882,7 +872,7 @@ async function add(id, appStoreId, manifest, subdomain, domain, portBindings, da
data.redirectDomains.forEach(function (d) {
queries.push({
query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)',
args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_REDIRECT ]
args: [ id, d.domain, d.subdomain, Location.TYPE_REDIRECT ]
});
});
}
@@ -891,7 +881,7 @@ async function add(id, appStoreId, manifest, subdomain, domain, portBindings, da
data.aliasDomains.forEach(function (d) {
queries.push({
query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)',
args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_ALIAS ]
args: [ id, d.domain, d.subdomain, Location.TYPE_ALIAS ]
});
});
}
@@ -947,23 +937,23 @@ async function updateWithConstraints(id, app, constraints) {
if ('subdomain' in app && 'domain' in app) { // must be updated together as they are unique together
queries.push({ query: 'DELETE FROM locations WHERE appId = ?', args: [ id ]}); // all locations of an app must be updated together
queries.push({ query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, app.domain, app.subdomain, exports.LOCATION_TYPE_PRIMARY ]});
queries.push({ query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, app.domain, app.subdomain, Location.TYPE_PRIMARY ]});
if ('secondaryDomains' in app) {
app.secondaryDomains.forEach(function (d) {
queries.push({ query: 'INSERT INTO locations (appId, domain, subdomain, type, environmentVariable) VALUES (?, ?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_SECONDARY, d.environmentVariable ]});
queries.push({ query: 'INSERT INTO locations (appId, domain, subdomain, type, environmentVariable) VALUES (?, ?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, Location.TYPE_SECONDARY, d.environmentVariable ]});
});
}
if ('redirectDomains' in app) {
app.redirectDomains.forEach(function (d) {
queries.push({ query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_REDIRECT ]});
queries.push({ query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, Location.TYPE_REDIRECT ]});
});
}
if ('aliasDomains' in app) {
app.aliasDomains.forEach(function (d) {
queries.push({ query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, exports.LOCATION_TYPE_ALIAS ]});
queries.push({ query: 'INSERT INTO locations (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)', args: [ id, d.domain, d.subdomain, Location.TYPE_ALIAS ]});
});
}
}
@@ -1261,19 +1251,19 @@ async function validateLocations(locations) {
constants.IMAP_SUBDOMAIN
];
const { fqdn:dashboardFqdn } = await dashboard.getLocation();
const dashboardLocation = await dashboard.getLocation();
for (const location of locations) {
if (!(location.domain in domainObjectMap)) return new BoxError(BoxError.BAD_FIELD, `No such domain in ${location.type} location`);
let subdomain = location.subdomain;
if (location.type === exports.LOCATION_TYPE_ALIAS && subdomain.startsWith('*')) {
if (location.type === Location.TYPE_ALIAS && subdomain.startsWith('*')) {
if (subdomain === '*') continue;
subdomain = subdomain.replace(/^\*\./, ''); // remove *.
}
if (RESERVED_SUBDOMAINS.indexOf(subdomain) !== -1) return new BoxError(BoxError.BAD_FIELD, `subdomain '${subdomain}' is reserved`);
if (dns.fqdn(subdomain, location.domain) === dashboardFqdn) return new BoxError(BoxError.BAD_FIELD, `subdomain '${subdomain}' is reserved for dashboard`);
if (location.fqdn === dashboardLocation.fqdn) return new BoxError(BoxError.BAD_FIELD, `subdomain '${subdomain}' is reserved for dashboard`);
const error = dns.validateHostname(subdomain, location.domain);
if (error) return new BoxError(BoxError.BAD_FIELD, `Bad ${location.type} location: ${error.message}`);
@@ -1366,10 +1356,10 @@ async function install(data, auditSource) {
icon = Buffer.from(icon, 'base64');
}
const locations = [{ subdomain, domain, type: exports.LOCATION_TYPE_PRIMARY }]
.concat(secondaryDomains.map(ad => Object.assign(ad, { type: exports.LOCATION_TYPE_SECONDARY })))
.concat(redirectDomains.map(ad => Object.assign(ad, { type: exports.LOCATION_TYPE_REDIRECT })))
.concat(aliasDomains.map(ad => Object.assign(ad, { type: exports.LOCATION_TYPE_ALIAS })));
const locations = [new Location(subdomain, domain, Location.TYPE_PRIMARY)]
.concat(secondaryDomains.map(sd => new Location(sd.subdomain, sd.domain, Location.TYPE_SECONDARY)))
.concat(redirectDomains.map(rd => new Location(rd.subdomain, rd.domain, Location.TYPE_REDIRECT)))
.concat(aliasDomains.map(ad => new Location(ad.subdomain, ad.domain, Location.TYPE_ALIAS)));
error = await validateLocations(locations);
if (error) throw error;
@@ -1808,6 +1798,16 @@ async function setReverseProxyConfig(app, reverseProxyConfig, auditSource) {
await eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId, app, reverseProxyConfig });
}
async function getLocation(subdomain, domain) {
assert.strictEqual(typeof subdomain, 'string');
assert.strictEqual(typeof domain, 'string');
const result = await database.query(`SELECT ${LOCATION_FIELDS} FROM locations WHERE subdomain=? AND domain=?`, [ subdomain, domain ]);
if (result.length === 0) return null;
return new Location(subdomain, domain, result[0].type, safe.JSON.parse(result[0].certificateJson));
}
async function setCertificate(app, data, auditSource) {
assert.strictEqual(typeof app, 'object');
assert(data && typeof data === 'object');
@@ -1827,23 +1827,11 @@ async function setCertificate(app, data, auditSource) {
const result = await database.query('UPDATE locations SET certificateJson=? WHERE location=? AND domain=?', [ certificate ? JSON.stringify(certificate) : null, subdomain, domain ]);
if (result.affectedRows === 0) throw new BoxError(BoxError.NOT_FOUND, 'Location not found');
const location = await getLocation(subdomain, domain); // fresh location object
const location = await getLocation(subdomain, domain); // fresh location object with type
await reverseProxy.setUserCertificate(app, location);
await eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId: app.id, app, subdomain, domain, cert });
}
async function getLocation(subdomain, domain) {
assert.strictEqual(typeof subdomain, 'string');
assert.strictEqual(typeof domain, 'string');
const result = await database.query(`SELECT ${LOCATION_FIELDS} FROM locations WHERE subdomain=? AND domain=?`, [ subdomain, domain ]);
if (result.length === 0) return null;
result[0].certificate = safe.JSON.parse(result[0].certificateJson);
result[0].fqdn = dns.fqdn(subdomain, domain);
return result[0];
}
async function setLocation(app, data, auditSource) {
assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof data, 'object');
@@ -1888,10 +1876,10 @@ async function setLocation(app, data, auditSource) {
values.aliasDomains = data.aliasDomains;
}
const locations = [{ subdomain: values.subdomain, domain: values.domain, type: exports.LOCATION_TYPE_PRIMARY }]
.concat(values.secondaryDomains.map(ad => Object.assign(ad, { type: exports.LOCATION_TYPE_SECONDARY })))
.concat(values.redirectDomains.map(ad => Object.assign(ad, { type: exports.LOCATION_TYPE_REDIRECT })))
.concat(values.aliasDomains.map(ad => Object.assign(ad, { type: exports.LOCATION_TYPE_ALIAS })));
const locations = [new Location(values.subdomain, values.domain, Location.TYPE_PRIMARY)]
.concat(values.secondaryDomains.map(sd => new Location(sd.subdomain, sd.domain, Location.TYPE_SECONDARY)))
.concat(values.redirectDomains.map(rd => new Location(rd.subdomain, rd.domain, Location.TYPE_REDIRECT)))
.concat(values.aliasDomains.map(ad => new Location(ad.subdomain, ad.domain, Location.TYPE_ALIAS)));
error = await validateLocations(locations);
if (error) throw error;
@@ -2293,8 +2281,8 @@ async function clone(app, data, user, auditSource) {
if (error) throw error;
const secondaryDomains = translateSecondaryDomains(data.secondaryDomains || {});
const locations = [{ subdomain, domain, type: exports.LOCATION_TYPE_PRIMARY }]
.concat(secondaryDomains.map(ad => Object.assign(ad, { type: exports.LOCATION_TYPE_SECONDARY })));
const locations = [new Location(subdomain, domain, Location.TYPE_PRIMARY)]
.concat(secondaryDomains.map(sd => new Location(sd.subdomain, sd.domain, Location.TYPE_SECONDARY)));
error = await validateLocations(locations);
if (error) throw error;