community: store versionsUrl in the database
This commit is contained in:
37
src/apps.js
37
src/apps.js
@@ -190,7 +190,7 @@ const appTaskManager = require('./apptaskmanager.js'),
|
||||
_ = require('./underscore.js');
|
||||
|
||||
// NOTE: when adding fields here, update the clone and unarchive logic as well
|
||||
const APPS_FIELDS_PREFIXED = [ 'apps.id', 'apps.appStoreId', 'apps.installationState', 'apps.errorJson', 'apps.runState',
|
||||
const APPS_FIELDS_PREFIXED = [ 'apps.id', 'apps.appStoreId', 'apps.versionsUrl', 'apps.installationState', 'apps.errorJson', 'apps.runState',
|
||||
'apps.health', 'apps.containerId', 'apps.manifestJson', 'apps.accessRestrictionJson', 'apps.memoryLimit', 'apps.cpuQuota',
|
||||
'apps.label', 'apps.notes', 'apps.tagsJson', 'apps.taskId', 'apps.reverseProxyConfigJson', 'apps.servicesConfigJson', 'apps.operatorsJson',
|
||||
'apps.sso', 'apps.devicesJson', 'apps.debugModeJson', 'apps.enableBackup', 'apps.proxyAuth', 'apps.containerIp', 'apps.crontab',
|
||||
@@ -592,12 +592,12 @@ function pickFields(app, accessLevel) {
|
||||
let result;
|
||||
if (accessLevel === exports.ACCESS_LEVEL_USER) {
|
||||
result = _.pick(app, [
|
||||
'id', 'appStoreId', 'installationState', 'error', 'runState', 'health', 'taskId', 'accessRestriction',
|
||||
'id', 'appStoreId', 'versionsUrl', 'installationState', 'error', 'runState', 'health', 'taskId', 'accessRestriction',
|
||||
'secondaryDomains', 'redirectDomains', 'aliasDomains', 'sso', 'subdomain', 'domain', 'fqdn', 'certificate',
|
||||
'manifest', 'portBindings', 'iconUrl', 'creationTime', 'ts', 'tags', 'label', 'upstreamUri']);
|
||||
} else { // admin or operator
|
||||
result = _.pick(app, [
|
||||
'id', 'appStoreId', 'installationState', 'error', 'runState', 'health', 'taskId',
|
||||
'id', 'appStoreId', 'versionsUrl', 'installationState', 'error', 'runState', 'health', 'taskId',
|
||||
'subdomain', 'domain', 'fqdn', 'certificate', 'crontab', 'upstreamUri',
|
||||
'accessRestriction', 'manifest', 'portBindings', 'iconUrl', 'memoryLimit', 'cpuQuota', 'operators',
|
||||
'sso', 'debugMode', 'reverseProxyConfig', 'enableBackup', 'creationTime', 'updateTime', 'ts', 'tags',
|
||||
@@ -884,9 +884,10 @@ async function checkForPortBindingConflict(portBindings, options) {
|
||||
}
|
||||
}
|
||||
|
||||
async function add(id, appStoreId, manifest, subdomain, domain, portBindings, data) {
|
||||
async function add(id, appStoreId, versionsUrl, manifest, subdomain, domain, portBindings, data) {
|
||||
assert.strictEqual(typeof id, 'string');
|
||||
assert.strictEqual(typeof appStoreId, 'string');
|
||||
assert.strictEqual(typeof versionsUrl, 'string');
|
||||
assert(manifest && typeof manifest === 'object');
|
||||
assert.strictEqual(typeof manifest.version, 'string');
|
||||
assert.strictEqual(typeof subdomain, 'string');
|
||||
@@ -930,11 +931,11 @@ async function add(id, appStoreId, manifest, subdomain, domain, portBindings, da
|
||||
const queries = [];
|
||||
|
||||
queries.push({
|
||||
query: 'INSERT INTO apps (id, appStoreId, manifestJson, installationState, runState, accessRestrictionJson, operatorsJson, memoryLimit, cpuQuota, '
|
||||
query: 'INSERT INTO apps (id, appStoreId, versionsUrl, manifestJson, installationState, runState, accessRestrictionJson, operatorsJson, memoryLimit, cpuQuota, '
|
||||
+ 'sso, debugModeJson, mailboxName, mailboxDomain, label, tagsJson, reverseProxyConfigJson, checklistJson, servicesConfigJson, icon, '
|
||||
+ 'enableMailbox, mailboxDisplayName, upstreamUri, enableTurn, enableRedis, devicesJson, notes, crontab, enableBackup, enableAutomaticUpdate) '
|
||||
+ ' VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
||||
args: [ id, appStoreId, manifestJson, installationState, runState, accessRestrictionJson, operatorsJson, memoryLimit, cpuQuota,
|
||||
+ ' VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
||||
args: [ id, appStoreId, versionsUrl, manifestJson, installationState, runState, accessRestrictionJson, operatorsJson, memoryLimit, cpuQuota,
|
||||
sso, debugModeJson, mailboxName, mailboxDomain, label, tagsJson, reverseProxyConfigJson, checklistJson, servicesConfigJson, icon,
|
||||
enableMailbox, mailboxDisplayName, upstreamUri, enableTurn, enableRedis, devicesJson, notes, crontab,
|
||||
enableBackup, enableAutomaticUpdate
|
||||
@@ -1400,7 +1401,8 @@ async function install(data, auditSource) {
|
||||
overwriteDns = 'overwriteDns' in data ? data.overwriteDns : false,
|
||||
skipDnsSetup = 'skipDnsSetup' in data ? data.skipDnsSetup : false,
|
||||
enableTurn = 'enableTurn' in data ? data.enableTurn : true,
|
||||
appStoreId = data.appStoreId,
|
||||
appStoreId = data.appStoreId || '',
|
||||
versionsUrl = data.versionsUrl || '',
|
||||
upstreamUri = data.upstreamUri || '',
|
||||
manifest = data.manifest,
|
||||
notes = data.notes || null,
|
||||
@@ -1520,7 +1522,7 @@ async function install(data, auditSource) {
|
||||
installationState: exports.ISTATE_PENDING_INSTALL
|
||||
};
|
||||
|
||||
const [addError] = await safe(add(appId, appStoreId, manifest, subdomain, domain, portBindings, app));
|
||||
const [addError] = await safe(add(appId, appStoreId, versionsUrl, manifest, subdomain, domain, portBindings, app));
|
||||
if (addError && addError.reason === BoxError.ALREADY_EXISTS) throw getDuplicateErrorDetails(addError.message, locations, portBindings);
|
||||
if (addError) throw addError;
|
||||
|
||||
@@ -1532,7 +1534,7 @@ async function install(data, auditSource) {
|
||||
|
||||
const taskId = await addTask(appId, app.installationState, task, auditSource);
|
||||
|
||||
const newApp = Object.assign({}, _.omit(app, ['icon']), { appStoreId, manifest, subdomain, domain, portBindings });
|
||||
const newApp = Object.assign({}, _.omit(app, ['icon']), { appStoreId, versionsUrl, manifest, subdomain, domain, portBindings });
|
||||
newApp.fqdn = dns.fqdn(newApp.subdomain, newApp.domain);
|
||||
newApp.secondaryDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, ad.domain); });
|
||||
newApp.redirectDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, ad.domain); });
|
||||
@@ -2129,8 +2131,9 @@ async function updateApp(app, data, auditSource) {
|
||||
error = await checkManifest(manifest);
|
||||
if (error) throw error;
|
||||
|
||||
const updateConfig = { skipBackup, manifest }; // this will clear appStoreId when updating from a repo and set it if passed in for update route
|
||||
const updateConfig = { skipBackup, manifest }; // this will clear appStoreId/versionsUrl when updating from a repo and set it if passed in for update route
|
||||
if ('appStoreId' in data) updateConfig.appStoreId = data.appStoreId;
|
||||
if ('versionsUrl' in data) updateConfig.versionsUrl = data.versionsUrl;
|
||||
|
||||
// prevent user from installing a app with different manifest id over an existing app
|
||||
// this allows cloudron install -f --app <appid> for an app installed from the appStore
|
||||
@@ -2141,8 +2144,8 @@ async function updateApp(app, data, auditSource) {
|
||||
// suffix '0' if prerelease is missing for semver.lte to work as expected
|
||||
const currentVersion = semver.prerelease(app.manifest.version) ? app.manifest.version : `${app.manifest.version}-0`;
|
||||
const updateVersion = semver.prerelease(updateConfig.manifest.version) ? updateConfig.manifest.version : `${updateConfig.manifest.version}-0`;
|
||||
if (app.appStoreId !== '' && semver.lte(updateVersion, currentVersion)) {
|
||||
if (!data.force) throw new BoxError(BoxError.BAD_FIELD, 'Downgrades are not permitted for apps installed from AppStore. force to override');
|
||||
if ((app.appStoreId !== '' || app.versionsUrl !== '') && semver.lte(updateVersion, currentVersion)) {
|
||||
if (!data.force) throw new BoxError(BoxError.BAD_FIELD, 'Downgrades are not permitted for apps installed from AppStore or Community. force to override');
|
||||
}
|
||||
|
||||
if ('icon' in data) {
|
||||
@@ -2438,7 +2441,7 @@ async function clone(app, data, user, auditSource) {
|
||||
if (!backup.manifest) throw new BoxError(BoxError.EXTERNAL_ERROR, 'Could not detect restore manifest');
|
||||
if (backup.encryptionVersion === 1) throw new BoxError(BoxError.BAD_FIELD, 'This encrypted backup was created with an older Cloudron version and cannot be cloned');
|
||||
|
||||
const manifest = backup.manifest, appStoreId = app.appStoreId;
|
||||
const manifest = backup.manifest, appStoreId = app.appStoreId, versionsUrl = app.versionsUrl;
|
||||
|
||||
let error = validateSecondaryDomains(data.secondaryDomains || {}, manifest);
|
||||
if (error) throw error;
|
||||
@@ -2483,7 +2486,7 @@ async function clone(app, data, user, auditSource) {
|
||||
label: dolly.label ? `${dolly.label}-clone` : '',
|
||||
});
|
||||
|
||||
const [addError] = await safe(add(newAppId, appStoreId, manifest, subdomain, domain, portBindings, obj));
|
||||
const [addError] = await safe(add(newAppId, appStoreId, versionsUrl, manifest, subdomain, domain, portBindings, obj));
|
||||
if (addError && addError.reason === BoxError.ALREADY_EXISTS) throw getDuplicateErrorDetails(addError.message, locations, portBindings);
|
||||
if (addError) throw addError;
|
||||
|
||||
@@ -2518,7 +2521,7 @@ async function unarchive(archive, data, auditSource) {
|
||||
domain = data.domain.toLowerCase(),
|
||||
overwriteDns = 'overwriteDns' in data ? data.overwriteDns : false;
|
||||
|
||||
const manifest = backup.manifest, appStoreId = backup.manifest.id;
|
||||
const manifest = backup.manifest, appStoreId = backup.manifest.id, versionsUrl = backup.appConfig?.versionsUrl || '';
|
||||
|
||||
let error = validateSecondaryDomains(data.secondaryDomains || {}, manifest);
|
||||
if (error) throw error;
|
||||
@@ -2558,7 +2561,7 @@ async function unarchive(archive, data, auditSource) {
|
||||
});
|
||||
obj.icon = (await archives.getIcons(archive.id))?.icon;
|
||||
|
||||
const [addError] = await safe(add(appId, appStoreId, manifest, subdomain, domain, portBindings, obj));
|
||||
const [addError] = await safe(add(appId, appStoreId, versionsUrl, manifest, subdomain, domain, portBindings, obj));
|
||||
if (addError && addError.reason === BoxError.ALREADY_EXISTS) throw getDuplicateErrorDetails(addError.message, locations, portBindings);
|
||||
if (addError) throw addError;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user