Compare commits

...

4 Commits

Author SHA1 Message Date
Johannes Zellner
50c344033c Add 0.160.1 changes 2017-07-22 11:12:51 +02:00
Girish Ramakrishnan
0c269925c2 Add the dialog text to the email 2017-07-21 12:40:04 -07:00
Johannes Zellner
dcd84a9636 send lastLogin event timestamp with alive status 2017-07-19 23:05:14 +02:00
Johannes Zellner
fa7273025b Send update notification every 4 days regardless of update pattern 2017-07-18 14:50:53 +02:00
4 changed files with 80 additions and 64 deletions

View File

@@ -885,3 +885,5 @@
* Prevent email view from flickering * Prevent email view from flickering
* Prepare for 1.0 * Prepare for 1.0
[0.160.1]
* Improved update notification

View File

@@ -15,6 +15,7 @@ exports = module.exports = {
var assert = require('assert'), var assert = require('assert'),
config = require('./config.js'), config = require('./config.js'),
debug = require('debug')('box:appstore'), debug = require('debug')('box:appstore'),
eventlog = require('./eventlog.js'),
os = require('os'), os = require('os'),
settings = require('./settings.js'), settings = require('./settings.js'),
superagent = require('superagent'), superagent = require('superagent'),
@@ -127,45 +128,52 @@ function sendAliveStatus(data, callback) {
settings.getAll(function (error, result) { settings.getAll(function (error, result) {
if (error) return callback(new AppstoreError(AppstoreError.INTERNAL_ERROR, error)); if (error) return callback(new AppstoreError(AppstoreError.INTERNAL_ERROR, error));
var backendSettings = { eventlog.getAllPaged(eventlog.ACTION_USER_LOGIN, null, 1, 1, function (error, loginEvents) {
dnsConfig: { if (error) return callback(new AppstoreError(AppstoreError.INTERNAL_ERROR, error));
provider: result[settings.DNS_CONFIG_KEY].provider,
wildcard: result[settings.DNS_CONFIG_KEY].provider === 'manual' ? result[settings.DNS_CONFIG_KEY].wildcard : undefined
},
tlsConfig: {
provider: result[settings.TLS_CONFIG_KEY].provider
},
backupConfig: {
provider: result[settings.BACKUP_CONFIG_KEY].provider
},
mailConfig: {
enabled: result[settings.MAIL_CONFIG_KEY].enabled
},
autoupdatePattern: result[settings.AUTOUPDATE_PATTERN_KEY],
timeZone: result[settings.TIME_ZONE_KEY]
};
var data = { var backendSettings = {
domain: config.fqdn(), dnsConfig: {
version: config.version(), provider: result[settings.DNS_CONFIG_KEY].provider,
provider: config.provider(), wildcard: result[settings.DNS_CONFIG_KEY].provider === 'manual' ? result[settings.DNS_CONFIG_KEY].wildcard : undefined
backendSettings: backendSettings, },
machine: { tlsConfig: {
cpus: os.cpus(), provider: result[settings.TLS_CONFIG_KEY].provider
totalmem: os.totalmem() },
} backupConfig: {
}; provider: result[settings.BACKUP_CONFIG_KEY].provider
},
mailConfig: {
enabled: result[settings.MAIL_CONFIG_KEY].enabled
},
autoupdatePattern: result[settings.AUTOUPDATE_PATTERN_KEY],
timeZone: result[settings.TIME_ZONE_KEY],
};
getAppstoreConfig(function (error, appstoreConfig) { var data = {
if (error) return callback(error); domain: config.fqdn(),
version: config.version(),
provider: config.provider(),
backendSettings: backendSettings,
machine: {
cpus: os.cpus(),
totalmem: os.totalmem()
},
events: {
lastLogin: loginEvents[0] ? (new Date(loginEvents[0].creationTime).getTime()) : 0
}
};
var url = config.apiServerOrigin() + '/api/v1/users/' + appstoreConfig.userId + '/cloudrons/' + appstoreConfig.cloudronId + '/alive'; getAppstoreConfig(function (error, appstoreConfig) {
superagent.post(url).send(data).query({ accessToken: appstoreConfig.token }).timeout(30 * 1000).end(function (error, result) { if (error) return callback(error);
if (error && !error.response) return callback(new AppstoreError(AppstoreError.EXTERNAL_ERROR, error));
if (result.statusCode === 404) return callback(new AppstoreError(AppstoreError.NOT_FOUND));
if (result.statusCode !== 201) return callback(new AppstoreError(AppstoreError.EXTERNAL_ERROR, util.format('Sending alive status failed. %s %j', result.status, result.body)));
callback(null); var url = config.apiServerOrigin() + '/api/v1/users/' + appstoreConfig.userId + '/cloudrons/' + appstoreConfig.cloudronId + '/alive';
superagent.post(url).send(data).query({ accessToken: appstoreConfig.token }).timeout(30 * 1000).end(function (error, result) {
if (error && !error.response) return callback(new AppstoreError(AppstoreError.EXTERNAL_ERROR, error));
if (result.statusCode === 404) return callback(new AppstoreError(AppstoreError.NOT_FOUND));
if (result.statusCode !== 201) return callback(new AppstoreError(AppstoreError.EXTERNAL_ERROR, util.format('Sending alive status failed. %s %j', result.status, result.body)));
callback(null);
});
}); });
}); });
}); });

View File

@@ -2,17 +2,21 @@
Dear <%= cloudronName %> Admin, Dear <%= cloudronName %> Admin,
Version <%= newBoxVersion %> for Cloudron <%= fqdn %> is now available! Cloudron Version <%= newBoxVersion %> is now available!
Your Cloudron will update automatically tonight. Alternately, update immediately at <%= webadminUrl %>. Your Cloudron will update to 1.0 once you have selected a plan (https://cloudron.io/pricing.html).
Changelog: With a paid plan, you get continuous updates for the Cloudron and apps just like you had until now.
<% for (var i = 0; i < changelog.length; i++) { %> This ensures you are running the latest versions of apps and keeps your server secure. All paid
* <%- changelog[i] %> plans come with support via email (support@cloudron.io) and live chat (https://chat.cloudron.io).
<% } %>
You can read more about our pricing changes in our blog at https://cloudron.io/blog/2017-06-06-pricing.html.
Visit our pricing page https://cloudron.io/pricing.html for pricing information.
Visit your Cloudron at <%= webadminUrl %> to perform the update.
Thank you, Thank you,
your Cloudron Cloudron.io team
<% } else { %> <% } else { %>
@@ -24,20 +28,22 @@ your Cloudron
<div style="width: 650px; text-align: left;"> <div style="width: 650px; text-align: left;">
<p> <p>
Version <b><%= newBoxVersion %></b> for Cloudron <%= fqdn %> is now available! Cloudron Version <b><%= newBoxVersion %></b> is now available!
</p> </p>
<p> <p>
Your Cloudron will update automatically tonight.<br/> Your Cloudron will update to 1.0 once you have selected a <a href="https://cloudron.io/pricing.html">plan</a>.
Alternately, update immediately <a href="<%= webadminUrl %>">here</a>. </p>
<p>
With a paid plan, you get continuous updates for the Cloudron and apps just like you had until now. This ensures you are running the latest versions of apps and keeps your server secure. All paid plans come with support via <a href="mailto:support@cloudron.io">email</a> and <a target="_blank" href="https://chat.cloudron.io">live chat</a>.
</p>
<p>
You can read more about our pricing changes in our <a href="https://cloudron.io/blog/2017-06-06-pricing.html" target="_blank">blog</a>.
</p> </p>
<h5>Changelog:</h5> <p>
<ul> Visit your Cloudron <a href="<%= webadminUrl %>">here</a> to perform the update.
<% for (var i = 0; i < changelogHTML.length; i++) { %> </p>
<li><%- changelogHTML[i] %></li>
<% } %>
</ul>
<br/> <br/>
<br/> <br/>
@@ -52,4 +58,3 @@ your Cloudron
<img src="https://analytics.cloudron.io/piwik.php?idsite=2&rec=1&e_c=CloudronEmail&e_a=update" style="border:0" alt="" /> <img src="https://analytics.cloudron.io/piwik.php?idsite=2&rec=1&e_c=CloudronEmail&e_a=update" style="border:0" alt="" />
<% } %> <% } %>

View File

@@ -12,7 +12,6 @@ exports = module.exports = {
var apps = require('./apps.js'), var apps = require('./apps.js'),
appstore = require('./appstore.js'), appstore = require('./appstore.js'),
async = require('async'), async = require('async'),
config = require('./config.js'),
constants = require('./constants.js'), constants = require('./constants.js'),
debug = require('debug')('box:updatechecker'), debug = require('debug')('box:updatechecker'),
mailer = require('./mailer.js'), mailer = require('./mailer.js'),
@@ -28,7 +27,7 @@ var NOOP_CALLBACK = function (error) { if (error) debug(error); };
function loadState() { function loadState() {
var state = safe.JSON.parse(safe.fs.readFileSync(paths.UPDATE_CHECKER_FILE, 'utf8')); var state = safe.JSON.parse(safe.fs.readFileSync(paths.UPDATE_CHECKER_FILE, 'utf8'));
return state || { }; return state || {};
} }
function saveState(mailedUser) { function saveState(mailedUser) {
@@ -111,7 +110,10 @@ function checkAppUpdates(callback) {
iteratorDone(); iteratorDone();
}); });
}, function () { }, function () {
newState.box = loadState().box; // preserve the latest box state information // preserve the latest box state information
newState.box = loadState().box;
newState.boxTimestamp = loadState().boxTimestamp;
saveState(newState); saveState(newState);
callback(); callback();
}); });
@@ -143,22 +145,21 @@ function checkBoxUpdates(callback) {
// decide whether to send email // decide whether to send email
var state = loadState(); var state = loadState();
if (state.box === gBoxUpdateInfo.version) { const NOTIFICATION_OFFSET = 1000 * 60 * 60 * 24 * 5; // 5 days
debug('Skipping notification of box update as user was already notified');
if (state.box === gBoxUpdateInfo.version && state.boxTimestamp > Date.now() - NOTIFICATION_OFFSET) {
debug('Skipping notification of box update as user was already notified within the last 5 days');
return callback(); return callback();
} }
state.boxTimestamp = Date.now();
state.box = updateInfo.version; state.box = updateInfo.version;
mailer.boxUpdateAvailable(updateInfo.version, updateInfo.changelog);
saveState(state); saveState(state);
// only send notifications if update pattern is 'never' callback();
settings.getAutoupdatePattern(function (error, result) {
if (error) debug(error);
else if (result === constants.AUTOUPDATE_PATTERN_NEVER) mailer.boxUpdateAvailable(updateInfo.version, updateInfo.changelog);
callback();
});
}); });
}); });
} }