2015-07-28 21:53:36 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
const assert = require('insist');
|
|
|
|
const crypto = require('crypto');
|
|
|
|
const fs = require('fs');
|
|
|
|
const path = require('path');
|
|
|
|
|
|
|
|
const db = require('../lib/db');
|
|
|
|
const P = require('../lib/promise');
|
2017-01-13 07:59:19 +03:00
|
|
|
const assertSecurityHeaders = require('./lib/util').assertSecurityHeaders;
|
2015-07-28 21:53:36 +03:00
|
|
|
|
|
|
|
const UID = crypto.randomBytes(16).toString('hex');
|
|
|
|
const mock = require('./lib/mock')({ userid: UID });
|
|
|
|
const Server = require('./lib/server');
|
|
|
|
const Static = require('./lib/static');
|
|
|
|
|
2017-09-19 04:46:02 +03:00
|
|
|
const events = require('../lib/events')(Server.server);
|
|
|
|
|
2015-07-28 21:53:36 +03:00
|
|
|
const imagePath = path.join(__dirname, 'lib', 'firefox.png');
|
|
|
|
const imageData = fs.readFileSync(imagePath);
|
|
|
|
|
2017-09-19 04:46:02 +03:00
|
|
|
const sinon = require('sinon');
|
|
|
|
|
2015-07-28 21:53:36 +03:00
|
|
|
const SIZES = require('../lib/img').SIZES;
|
|
|
|
const SIZE_SUFFIXES = Object.keys(SIZES).map(function(val) {
|
|
|
|
if (val === 'default') {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
return '_' + val;
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
/*global describe,it,beforeEach,afterEach*/
|
|
|
|
|
|
|
|
afterEach(function() {
|
|
|
|
mock.done();
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
describe('events', function() {
|
|
|
|
describe('onDeleteMessage', function() {
|
|
|
|
var tok = crypto.randomBytes(32).toString('hex');
|
|
|
|
function Message(type, onDel) {
|
|
|
|
if (typeof type === 'function') {
|
|
|
|
onDel = type;
|
|
|
|
type = 'delete';
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
event: type,
|
2017-09-19 04:46:02 +03:00
|
|
|
uid: UID,
|
2015-07-28 21:53:36 +03:00
|
|
|
del: onDel
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('avatar', function() {
|
|
|
|
beforeEach(function() {
|
|
|
|
mock.token({
|
|
|
|
user: UID,
|
|
|
|
email: 'user@example.domain',
|
|
|
|
scope: ['profile:avatar:write']
|
|
|
|
});
|
2015-10-19 21:26:53 +03:00
|
|
|
mock.image(imageData.length);
|
2015-07-28 21:53:36 +03:00
|
|
|
return Server.api.post({
|
|
|
|
url: '/avatar/upload',
|
|
|
|
payload: imageData,
|
|
|
|
headers: { authorization: 'Bearer ' + tok,
|
|
|
|
'content-type': 'image/png',
|
|
|
|
'content-length': imageData.length
|
|
|
|
}
|
|
|
|
}).then(function(res) {
|
|
|
|
assert.equal(res.statusCode, 201);
|
|
|
|
assert(res.result.url);
|
|
|
|
assert(res.result.id);
|
2017-01-13 07:59:19 +03:00
|
|
|
assertSecurityHeaders(res);
|
2015-07-28 21:53:36 +03:00
|
|
|
return res.result.url;
|
|
|
|
}).then(function(s3url) {
|
|
|
|
return P.all(SIZE_SUFFIXES).map(function(suffix) {
|
|
|
|
return Static.get(s3url + suffix);
|
|
|
|
});
|
|
|
|
}).then(function(responses) {
|
|
|
|
assert.equal(responses.length, SIZE_SUFFIXES.length);
|
|
|
|
responses.forEach(function(res) {
|
|
|
|
assert.equal(res.statusCode, 200);
|
|
|
|
});
|
|
|
|
mock.done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should delete avatars', function(done) {
|
|
|
|
mock.deleteImage();
|
|
|
|
events.onData(new Message(function() {
|
2016-11-10 07:51:02 +03:00
|
|
|
db.getSelectedAvatar(UID).then(function(avatar) {
|
|
|
|
assert.equal(avatar, undefined);
|
2015-07-28 21:53:36 +03:00
|
|
|
}).done(done, done);
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not delete message on error', function(done) {
|
2015-10-19 21:26:53 +03:00
|
|
|
mock.workerFailure('delete', 0);
|
2015-07-28 21:53:36 +03:00
|
|
|
events.onData(new Message(function() {
|
|
|
|
assert(false, 'message.del() should not be called');
|
|
|
|
}));
|
|
|
|
mock.log('events', function(record) {
|
2017-09-19 04:46:02 +03:00
|
|
|
if (record.levelname === 'ERROR' && record.args[0] === 'delete') {
|
2015-07-28 21:53:36 +03:00
|
|
|
setTimeout(function() {
|
|
|
|
done();
|
|
|
|
}, 1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should ignore unknown messages', function(done) {
|
|
|
|
db.setDisplayName(UID, 'foo bar').then(function() {
|
|
|
|
events.onData(new Message('baz', function() {
|
|
|
|
db.getDisplayName(UID).then(function(profile) {
|
|
|
|
assert.equal(profile.displayName, 'foo bar');
|
|
|
|
}).done(done, done);
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
2017-09-19 04:46:02 +03:00
|
|
|
|
|
|
|
describe('onPrimaryEmailChangedMessage', function () {
|
|
|
|
describe('should invalidate user cache', function () {
|
|
|
|
function Message(type, onDel) {
|
|
|
|
if (typeof type === 'function') {
|
|
|
|
onDel = type;
|
|
|
|
type = 'primaryEmailChanged';
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
event: type,
|
|
|
|
uid: UID,
|
|
|
|
del: onDel
|
|
|
|
};
|
|
|
|
}
|
|
|
|
beforeEach(function () {
|
2018-04-13 07:46:50 +03:00
|
|
|
Server.server.methods.profileCache.drop = sinon.spy(function (uid, cb) {
|
2017-09-19 04:46:02 +03:00
|
|
|
cb();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('invalidate cache', function (done) {
|
|
|
|
events.onData(new Message(function () {
|
2018-04-13 07:46:50 +03:00
|
|
|
var args = Server.server.methods.profileCache.drop.getCall(0).args;
|
|
|
|
var callCount = Server.server.methods.profileCache.drop.callCount;
|
2017-09-19 04:46:02 +03:00
|
|
|
assert.equal(callCount, 1);
|
|
|
|
assert.equal(args.length, 2);
|
2018-04-13 07:46:50 +03:00
|
|
|
assert.equal(args[0], UID);
|
2017-09-19 04:46:02 +03:00
|
|
|
assert.equal(typeof args[1] === 'function', true);
|
|
|
|
done();
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('should delete message on invalid uid', function () {
|
|
|
|
function Message(type, onDel) {
|
|
|
|
if (typeof type === 'function') {
|
|
|
|
onDel = type;
|
|
|
|
type = 'primaryEmailChanged';
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
event: type,
|
|
|
|
uid: 'notahexuid',
|
|
|
|
del: onDel
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
it('invalid uid', function (done) {
|
|
|
|
events.onData(new Message(function () {
|
|
|
|
assert(true, 'message.del() should be called');
|
|
|
|
}));
|
|
|
|
|
|
|
|
mock.log('events', function(record) {
|
|
|
|
if (record.levelname === 'WARN' && record.args[0] === 'getUserId') {
|
|
|
|
assert.equal(record.args[1].userId, 'notahexuid');
|
|
|
|
setTimeout(function() {
|
|
|
|
done();
|
|
|
|
}, 1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2018-04-12 06:08:29 +03:00
|
|
|
|
|
|
|
describe('onProfileDataChanged', function () {
|
|
|
|
describe('should invalidate user cache', function () {
|
|
|
|
function Message(type, onDel) {
|
|
|
|
if (typeof type === 'function') {
|
|
|
|
onDel = type;
|
|
|
|
type = 'profileDataChanged';
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
event: type,
|
|
|
|
uid: UID,
|
|
|
|
del: onDel
|
|
|
|
};
|
|
|
|
}
|
|
|
|
beforeEach(function () {
|
2018-04-16 03:47:46 +03:00
|
|
|
Server.server.methods.profileCache.drop = sinon.spy(function (uid, cb) {
|
2018-04-12 06:08:29 +03:00
|
|
|
cb();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('invalidate cache', function (done) {
|
|
|
|
events.onData(new Message(function () {
|
2018-04-16 03:47:46 +03:00
|
|
|
var args = Server.server.methods.profileCache.drop.getCall(0).args;
|
|
|
|
var callCount = Server.server.methods.profileCache.drop.callCount;
|
2018-04-12 06:08:29 +03:00
|
|
|
assert.equal(callCount, 1);
|
|
|
|
assert.equal(args.length, 2);
|
2018-04-16 03:47:46 +03:00
|
|
|
assert.equal(args[0], UID);
|
2018-04-12 06:08:29 +03:00
|
|
|
assert.equal(typeof args[1] === 'function', true);
|
|
|
|
done();
|
|
|
|
}));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('should delete message on invalid uid', function () {
|
|
|
|
function Message(type, onDel) {
|
|
|
|
if (typeof type === 'function') {
|
|
|
|
onDel = type;
|
|
|
|
type = 'profileDataChanged';
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
event: type,
|
|
|
|
uid: 'notahexuid',
|
|
|
|
del: onDel
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
it('invalid uid', function (done) {
|
|
|
|
events.onData(new Message(function () {
|
|
|
|
assert(true, 'message.del() should be called');
|
|
|
|
}));
|
|
|
|
|
|
|
|
mock.log('events', function(record) {
|
|
|
|
if (record.levelname === 'WARN' && record.args[0] === 'getUserId') {
|
|
|
|
assert.equal(record.args[1].userId, 'notahexuid');
|
|
|
|
setTimeout(function() {
|
|
|
|
done();
|
|
|
|
}, 1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2015-07-28 21:53:36 +03:00
|
|
|
});
|
2018-03-27 06:52:59 +03:00
|
|
|
|
|
|
|
after(() => {
|
|
|
|
return db._teardown();
|
|
|
|
});
|