diff --git a/src/appstore.js b/src/appstore.js index 582923585..9e0bb7f02 100644 --- a/src/appstore.js +++ b/src/appstore.js @@ -1,6 +1,8 @@ 'use strict'; exports = module.exports = { + getFeatures: getFeatures, + getApps: getApps, getApp: getApp, getAppVersion: getAppVersion, @@ -35,7 +37,9 @@ var apps = require('./apps.js'), eventlog = require('./eventlog.js'), groups = require('./groups.js'), mail = require('./mail.js'), + moment = require('moment'), os = require('os'), + paths = require('./paths.js'), safe = require('safetydance'), semver = require('semver'), settings = require('./settings.js'), @@ -45,6 +49,64 @@ var apps = require('./apps.js'), const NOOP_CALLBACK = function (error) { if (error) debug(error); }; +// these are the default options and will be adjusted once a subscription state is obtained +let gFeatures = { + userMaxCount: 3, + externalLdap: false, + eventLog: false, + privateDockerRegistry: false, + branding: false +}; + +// attempt to load feature cache in case appstore would be down +let tmp = safe.JSON.parse(safe.fs.readFileSync(paths.FEATURES_INFO_FILE, 'utf8')); +if (tmp) { + gFeatures.userMaxCount = tmp.userMaxCount; + gFeatures.externalLdap = tmp.externalLdap; + gFeatures.eventLog = tmp.eventLog; + gFeatures.privateDockerRegistry = tmp.privateDockerRegistry; + gFeatures.branding = tmp.branding; +} + +function getFeatures() { + return gFeatures; +} + +function updateFeatures(subscriptionInfo) { + assert.strictEqual(typeof subscriptionInfo, 'object'); + + // FIXME adjust the time + if (moment(subscriptionInfo.cloudronCreatedAt).isBefore('2020-02-10')) { + gFeatures.userMaxCount = null; // unlimited + gFeatures.externalLdap = true; + gFeatures.eventLog = true; + gFeatures.privateDockerRegistry = true; + gFeatures.branding = false; + } else { + if (subscriptionInfo.plan.id === '2020-03_personal') { + gFeatures.userMaxCount = 5; + gFeatures.externalLdap = false; + gFeatures.eventLog = false; + gFeatures.privateDockerRegistry = false; + gFeatures.branding = false; + } else if (subscriptionInfo.plan.id === '2020-03_business') { + gFeatures.userMaxCount = null; // unlimited + gFeatures.externalLdap = true; + gFeatures.eventLog = true; + gFeatures.privateDockerRegistry = true; + gFeatures.branding = true; + } else { + gFeatures.userMaxCount = 3; + gFeatures.externalLdap = false; + gFeatures.eventLog = false; + gFeatures.privateDockerRegistry = false; + gFeatures.branding = false; + } + } + + safe.fs.writeFileSync(paths.FEATURES_INFO_FILE, JSON.stringify(gFeatures), 'utf8'); +} + function isAppAllowed(appstoreId, listingConfig) { assert.strictEqual(typeof listingConfig, 'object'); assert.strictEqual(typeof appstoreId, 'string'); @@ -123,7 +185,10 @@ function getSubscription(callback) { if (result.statusCode === 502) return callback(new BoxError(BoxError.EXTERNAL_ERROR, `Stripe error: ${error.message}`)); if (result.statusCode !== 200) return callback(new BoxError(BoxError.EXTERNAL_ERROR, `Unknown error: ${error.message}`)); - callback(null, result.body); // { email, subscription } + // update the features + updateFeatures(result.body); + + callback(null, result.body); }); }); } diff --git a/src/cloudron.js b/src/cloudron.js index dce877845..3c34f2026 100644 --- a/src/cloudron.js +++ b/src/cloudron.js @@ -22,6 +22,7 @@ exports = module.exports = { }; var apps = require('./apps.js'), + appstore = require('./appstore.js'), assert = require('assert'), async = require('async'), auditSource = require('./auditsource.js'), @@ -134,13 +135,7 @@ function getConfig(callback) { provider: settings.provider(), cloudronName: allSettings[settings.CLOUDRON_NAME_KEY], footer: allSettings[settings.FOOTER_KEY], - features: { - userMaxCount: null, // Infinity does not translate in JSON - externalLdap: true, - eventLog: true, - privateDockerRegistry: true, - branding: true - } + features: appstore.getFeatures() }); }); } diff --git a/src/paths.js b/src/paths.js index 57bf66ccb..b2ac03506 100644 --- a/src/paths.js +++ b/src/paths.js @@ -35,6 +35,7 @@ exports = module.exports = { UPDATE_DIR: path.join(baseDir(), 'platformdata/update'), SNAPSHOT_INFO_FILE: path.join(baseDir(), 'platformdata/backup/snapshot-info.json'), DYNDNS_INFO_FILE: path.join(baseDir(), 'platformdata/dyndns-info.json'), + FEATURES_INFO_FILE: path.join(baseDir(), 'platformdata/features-info.json'), VERSION_FILE: path.join(baseDir(), 'platformdata/VERSION'), // this is not part of appdata because an icon may be set before install