Compare commits
7 Commits
docker_tests
...
v4.0.3
| Author | SHA1 | Date | |
|---|---|---|---|
| 51a69cce41 | |||
| 8686832bd1 | |||
| c93c06ba88 | |||
| 36d64b3566 | |||
| e0c531564c | |||
| 1e0ec75f0a | |||
| 36ac02d29f |
@@ -1593,3 +1593,10 @@
|
|||||||
* Make it easier to import email
|
* Make it easier to import email
|
||||||
* Give SFTP access only to admins
|
* Give SFTP access only to admins
|
||||||
|
|
||||||
|
[4.0.2]
|
||||||
|
* Fix GCDNS crash
|
||||||
|
* Add option to update without backing up
|
||||||
|
|
||||||
|
[4.0.3]
|
||||||
|
* Fix dashboard issue for non-admins
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -204,7 +204,7 @@ function boxAutoupdatePatternChanged(pattern) {
|
|||||||
var updateInfo = updateChecker.getUpdateInfo();
|
var updateInfo = updateChecker.getUpdateInfo();
|
||||||
if (updateInfo.box) {
|
if (updateInfo.box) {
|
||||||
debug('Starting autoupdate to %j', updateInfo.box);
|
debug('Starting autoupdate to %j', updateInfo.box);
|
||||||
updater.updateToLatest(auditSource.CRON, NOOP_CALLBACK);
|
updater.updateToLatest({ skipBackup: false }, auditSource.CRON, NOOP_CALLBACK);
|
||||||
} else {
|
} else {
|
||||||
debug('No box auto updates available');
|
debug('No box auto updates available');
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -15,7 +15,7 @@ var assert = require('assert'),
|
|||||||
dns = require('../native-dns.js'),
|
dns = require('../native-dns.js'),
|
||||||
domains = require('../domains.js'),
|
domains = require('../domains.js'),
|
||||||
DomainsError = require('../domains.js').DomainsError,
|
DomainsError = require('../domains.js').DomainsError,
|
||||||
GCDNS = require('@google-cloud/dns'),
|
GCDNS = require('@google-cloud/dns').DNS,
|
||||||
util = require('util'),
|
util = require('util'),
|
||||||
waitForDns = require('./waitfordns.js'),
|
waitForDns = require('./waitfordns.js'),
|
||||||
_ = require('underscore');
|
_ = require('underscore');
|
||||||
@@ -46,7 +46,7 @@ function getZoneByName(dnsConfig, zoneName, callback) {
|
|||||||
assert.strictEqual(typeof zoneName, 'string');
|
assert.strictEqual(typeof zoneName, 'string');
|
||||||
assert.strictEqual(typeof callback, 'function');
|
assert.strictEqual(typeof callback, 'function');
|
||||||
|
|
||||||
var gcdns = GCDNS(getDnsCredentials(dnsConfig));
|
var gcdns = new GCDNS(getDnsCredentials(dnsConfig));
|
||||||
|
|
||||||
gcdns.getZones(function (error, zones) {
|
gcdns.getZones(function (error, zones) {
|
||||||
if (error && error.message === 'invalid_grant') return callback(new DomainsError(DomainsError.ACCESS_DENIED, 'The key was probably revoked'));
|
if (error && error.message === 'invalid_grant') return callback(new DomainsError(DomainsError.ACCESS_DENIED, 'The key was probably revoked'));
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ function listByUserIdPaged(userId, page, perPage, callback) {
|
|||||||
var data = [ userId ];
|
var data = [ userId ];
|
||||||
var query = 'SELECT ' + NOTIFICATION_FIELDS + ' FROM notifications WHERE userId=?';
|
var query = 'SELECT ' + NOTIFICATION_FIELDS + ' FROM notifications WHERE userId=?';
|
||||||
|
|
||||||
query += ' ORDER BY creationTime, title DESC LIMIT ?,?';
|
query += ' ORDER BY creationTime DESC LIMIT ?,?';
|
||||||
|
|
||||||
data.push((page-1)*perPage);
|
data.push((page-1)*perPage);
|
||||||
data.push(perPage);
|
data.push(perPage);
|
||||||
|
|||||||
@@ -57,8 +57,10 @@ function getDisks(req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function update(req, res, next) {
|
function update(req, res, next) {
|
||||||
|
if ('skipBackup' in req.body && typeof req.body.skipBackup !== 'boolean') return next(new HttpError(400, 'skipBackup must be a boolean'));
|
||||||
|
|
||||||
// this only initiates the update, progress can be checked via the progress route
|
// this only initiates the update, progress can be checked via the progress route
|
||||||
updater.updateToLatest(auditSource.fromRequest(req), function (error, taskId) {
|
updater.updateToLatest(req.body, auditSource.fromRequest(req), function (error, taskId) {
|
||||||
if (error && error.reason === UpdaterError.ALREADY_UPTODATE) return next(new HttpError(422, error.message));
|
if (error && error.reason === UpdaterError.ALREADY_UPTODATE) return next(new HttpError(422, error.message));
|
||||||
if (error && error.reason === UpdaterError.BAD_STATE) return next(new HttpError(409, error.message));
|
if (error && error.reason === UpdaterError.BAD_STATE) return next(new HttpError(409, error.message));
|
||||||
if (error) return next(new HttpError(500, error));
|
if (error) return next(new HttpError(500, error));
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ function update(req, res, next) {
|
|||||||
debug('triggering update');
|
debug('triggering update');
|
||||||
|
|
||||||
// this only initiates the update, progress can be checked via the progress route
|
// this only initiates the update, progress can be checked via the progress route
|
||||||
updater.updateToLatest(auditSource.SYSADMIN, function (error, taskId) {
|
updater.updateToLatest({ skipBackup: false }, auditSource.SYSADMIN, function (error, taskId) {
|
||||||
if (error && error.reason === UpdaterError.ALREADY_UPTODATE) return next(new HttpError(422, error.message));
|
if (error && error.reason === UpdaterError.ALREADY_UPTODATE) return next(new HttpError(422, error.message));
|
||||||
if (error && error.reason === UpdaterError.BAD_STATE) return next(new HttpError(409, error.message));
|
if (error && error.reason === UpdaterError.BAD_STATE) return next(new HttpError(409, error.message));
|
||||||
if (error) return next(new HttpError(500, error));
|
if (error) return next(new HttpError(500, error));
|
||||||
|
|||||||
+2
-2
@@ -25,7 +25,7 @@ var assert = require('assert'),
|
|||||||
BackupsError = require('../backups.js').BackupsError,
|
BackupsError = require('../backups.js').BackupsError,
|
||||||
debug = require('debug')('box:storage/gcs'),
|
debug = require('debug')('box:storage/gcs'),
|
||||||
EventEmitter = require('events'),
|
EventEmitter = require('events'),
|
||||||
GCS = require('@google-cloud/storage'),
|
GCS = require('@google-cloud/storage').Storage,
|
||||||
PassThrough = require('stream').PassThrough,
|
PassThrough = require('stream').PassThrough,
|
||||||
path = require('path');
|
path = require('path');
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ function getBucket(apiConfig) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return GCS(gcsConfig).bucket(apiConfig.bucket);
|
return new GCS(gcsConfig).bucket(apiConfig.bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
// storage api
|
// storage api
|
||||||
|
|||||||
+7
-7
@@ -263,7 +263,7 @@ function copy(apiConfig, oldFilePath, newFilePath) {
|
|||||||
endBytes = startBytes + chunkSize;
|
endBytes = startBytes + chunkSize;
|
||||||
if (endBytes > size) endBytes = size;
|
if (endBytes > size) endBytes = size;
|
||||||
|
|
||||||
var params = {
|
var partCopyParams = {
|
||||||
Bucket: apiConfig.bucket,
|
Bucket: apiConfig.bucket,
|
||||||
Key: path.join(newFilePath, relativePath),
|
Key: path.join(newFilePath, relativePath),
|
||||||
CopySource: encodeCopySource(apiConfig.bucket, entry.fullPath), // See aws-sdk-js/issues/1302
|
CopySource: encodeCopySource(apiConfig.bucket, entry.fullPath), // See aws-sdk-js/issues/1302
|
||||||
@@ -272,12 +272,12 @@ function copy(apiConfig, oldFilePath, newFilePath) {
|
|||||||
UploadId: uploadId
|
UploadId: uploadId
|
||||||
};
|
};
|
||||||
|
|
||||||
events.emit('progress', `Copying part ${params.PartNumber} - ${params.CopySource} ${params.CopySourceRange}`);
|
events.emit('progress', `Copying part ${partCopyParams.PartNumber} - ${partCopyParams.CopySource} ${partCopyParams.CopySourceRange}`);
|
||||||
|
|
||||||
s3.uploadPartCopy(params, function (error, result) {
|
s3.uploadPartCopy(partCopyParams, function (error, result) {
|
||||||
if (error) return done(error);
|
if (error) return done(error);
|
||||||
|
|
||||||
events.emit('progress', `Uploaded part ${params.PartNumber} - Etag: ${result.CopyPartResult.ETag}`);
|
events.emit('progress', `Uploaded part ${partCopyParams.PartNumber} - Etag: ${result.CopyPartResult.ETag}`);
|
||||||
|
|
||||||
uploadedParts.push({ ETag: result.CopyPartResult.ETag, PartNumber: partNumber });
|
uploadedParts.push({ ETag: result.CopyPartResult.ETag, PartNumber: partNumber });
|
||||||
|
|
||||||
@@ -287,16 +287,16 @@ function copy(apiConfig, oldFilePath, newFilePath) {
|
|||||||
return copyNextChunk();
|
return copyNextChunk();
|
||||||
}
|
}
|
||||||
|
|
||||||
var params = {
|
var completeMultipartParams = {
|
||||||
Bucket: apiConfig.bucket,
|
Bucket: apiConfig.bucket,
|
||||||
Key: path.join(newFilePath, relativePath),
|
Key: path.join(newFilePath, relativePath),
|
||||||
MultipartUpload: { Parts: uploadedParts },
|
MultipartUpload: { Parts: uploadedParts },
|
||||||
UploadId: uploadId
|
UploadId: uploadId
|
||||||
};
|
};
|
||||||
|
|
||||||
events.emit('progress', `Finishing multipart copy - ${params.Key}`);
|
events.emit('progress', `Finishing multipart copy - ${completeMultipartParams.Key}`);
|
||||||
|
|
||||||
s3.completeMultipartUpload(params, done);
|
s3.completeMultipartUpload(completeMultipartParams, done);
|
||||||
}).on('retry', function (response) {
|
}).on('retry', function (response) {
|
||||||
++retryCount;
|
++retryCount;
|
||||||
events.emit('progress', `Retrying (${response.retryCount+1}) multipart copy of ${relativePath || oldFilePath}. Error: ${response.error} ${response.httpResponse.statusCode}`);
|
events.emit('progress', `Retrying (${response.retryCount+1}) multipart copy of ${relativePath || oldFilePath}. Error: ${response.error} ${response.httpResponse.statusCode}`);
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ var async = require('async'),
|
|||||||
users = require('../users.js'),
|
users = require('../users.js'),
|
||||||
userdb = require('../userdb.js'),
|
userdb = require('../userdb.js'),
|
||||||
eventlogdb = require('../eventlogdb.js'),
|
eventlogdb = require('../eventlogdb.js'),
|
||||||
notificationdb = require('../notificationdb.js'),
|
|
||||||
notifications = require('../notifications.js'),
|
notifications = require('../notifications.js'),
|
||||||
NotificationsError = notifications.NotificationsError,
|
NotificationsError = notifications.NotificationsError,
|
||||||
expect = require('expect.js');
|
expect = require('expect.js');
|
||||||
@@ -152,20 +151,24 @@ describe('Notifications', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('getAllPaged succeeds for second page', function (done) {
|
it('getAllPaged succeeds for second page (takes 5 seconds to add)', function (done) {
|
||||||
async.timesSeries(20, function (n, callback) {
|
async.timesSeries(5, function (n, callback) {
|
||||||
notifications._add(USER_0.id, EVENT_0.id, 'title' + n, 'some message', callback);
|
// timeout is for database TIMESTAMP resolution
|
||||||
|
setTimeout(function () {
|
||||||
|
notifications._add(USER_0.id, EVENT_0.id, 'title' + n, 'some message', callback);
|
||||||
|
}, 1000);
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
expect(error).to.eql(null);
|
expect(error).to.eql(null);
|
||||||
|
|
||||||
notifications.getAllPaged(USER_0.id, null /* ack */, 2, 10, function (error, results) {
|
notifications.getAllPaged(USER_0.id, null /* ack */, 2, 3, function (error, results) {
|
||||||
expect(error).to.eql(null);
|
expect(error).to.eql(null);
|
||||||
expect(results).to.be.an(Array);
|
expect(results).to.be.an(Array);
|
||||||
expect(results.length).to.be(10);
|
expect(results.length).to.be(3);
|
||||||
|
|
||||||
// we cannot compare the title because ordering is by time which is stored in mysql with seconds
|
expect(results[0].title).to.equal('title1');
|
||||||
// precision. making the ordering random...
|
expect(results[1].title).to.equal('title0');
|
||||||
// expect(results[0].title).to.equal('title9');
|
// the previous tests already add one notification with 'title'
|
||||||
|
expect(results[2].title).to.equal('title');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|||||||
+13
-5
@@ -154,8 +154,9 @@ function downloadAndVerifyRelease(updateInfo, callback) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function update(boxUpdateInfo, progressCallback, callback) {
|
function update(boxUpdateInfo, options, progressCallback, callback) {
|
||||||
assert(boxUpdateInfo && typeof boxUpdateInfo === 'object');
|
assert(boxUpdateInfo && typeof boxUpdateInfo === 'object');
|
||||||
|
assert(options && typeof options === 'object');
|
||||||
assert.strictEqual(typeof progressCallback, 'function');
|
assert.strictEqual(typeof progressCallback, 'function');
|
||||||
assert.strictEqual(typeof callback, 'function');
|
assert.strictEqual(typeof callback, 'function');
|
||||||
|
|
||||||
@@ -164,9 +165,15 @@ function update(boxUpdateInfo, progressCallback, callback) {
|
|||||||
downloadAndVerifyRelease(boxUpdateInfo, function (error, packageInfo) {
|
downloadAndVerifyRelease(boxUpdateInfo, function (error, packageInfo) {
|
||||||
if (error) return callback(error);
|
if (error) return callback(error);
|
||||||
|
|
||||||
progressCallback({ percent: 10, message: 'Backing up' });
|
function maybeBackup(next) {
|
||||||
|
if (options.skipBackup) return next();
|
||||||
|
|
||||||
backups.backupBoxAndApps((progress) => progressCallback({ percent: 10+progress.percent*70/100, message: progress.message }), function (error) {
|
progressCallback({ percent: 10, message: 'Backing up' });
|
||||||
|
|
||||||
|
backups.backupBoxAndApps((progress) => progressCallback({ percent: 10+progress.percent*70/100, message: progress.message }), next);
|
||||||
|
}
|
||||||
|
|
||||||
|
maybeBackup(function (error) {
|
||||||
if (error) return callback(error);
|
if (error) return callback(error);
|
||||||
|
|
||||||
debug('updating box %s', boxUpdateInfo.sourceTarballUrl);
|
debug('updating box %s', boxUpdateInfo.sourceTarballUrl);
|
||||||
@@ -201,7 +208,8 @@ function canUpdate(boxUpdateInfo, callback) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateToLatest(auditSource, callback) {
|
function updateToLatest(options, auditSource, callback) {
|
||||||
|
assert.strictEqual(typeof options, 'object');
|
||||||
assert.strictEqual(typeof auditSource, 'object');
|
assert.strictEqual(typeof auditSource, 'object');
|
||||||
assert.strictEqual(typeof callback, 'function');
|
assert.strictEqual(typeof callback, 'function');
|
||||||
|
|
||||||
@@ -215,7 +223,7 @@ function updateToLatest(auditSource, callback) {
|
|||||||
error = locker.lock(locker.OP_BOX_UPDATE);
|
error = locker.lock(locker.OP_BOX_UPDATE);
|
||||||
if (error) return callback(new UpdaterError(UpdaterError.BAD_STATE, `Cannot update now: ${error.message}`));
|
if (error) return callback(new UpdaterError(UpdaterError.BAD_STATE, `Cannot update now: ${error.message}`));
|
||||||
|
|
||||||
let task = tasks.startTask(tasks.TASK_UPDATE, [ boxUpdateInfo ]);
|
let task = tasks.startTask(tasks.TASK_UPDATE, [ boxUpdateInfo, options ]);
|
||||||
task.on('error', (error) => callback(new UpdaterError(UpdaterError.INTERNAL_ERROR, error)));
|
task.on('error', (error) => callback(new UpdaterError(UpdaterError.INTERNAL_ERROR, error)));
|
||||||
task.on('start', (taskId) => {
|
task.on('start', (taskId) => {
|
||||||
eventlog.add(eventlog.ACTION_UPDATE, auditSource, { taskId, boxUpdateInfo });
|
eventlog.add(eventlog.ACTION_UPDATE, auditSource, { taskId, boxUpdateInfo });
|
||||||
|
|||||||
Reference in New Issue
Block a user