2019-11-08 05:02:47 +01:00
|
|
|
const fs = require('fs');
|
|
|
|
const path = require('path');
|
|
|
|
const nconf = require('nconf');
|
|
|
|
const assert = require('assert');
|
|
|
|
const lokinet = require('loki-launcher/lokinet');
|
|
|
|
const crypto = require('crypto');
|
|
|
|
const bb = require('bytebuffer');
|
|
|
|
const libsignal = require('libsignal');
|
2019-09-10 06:04:20 +02:00
|
|
|
const adnServerAPI = require('../fetchWrapper');
|
2019-11-08 05:02:47 +01:00
|
|
|
const config = require('../config');
|
|
|
|
|
|
|
|
const ADN_SCOPES = 'basic stream write_post follow messages update_profile files export';
|
2019-09-10 06:04:20 +02:00
|
|
|
|
2019-09-09 07:42:49 +02:00
|
|
|
// Look for a config file
|
2019-11-08 05:02:47 +01:00
|
|
|
const disk_config = config.getDiskConfig();
|
2019-09-09 07:42:49 +02:00
|
|
|
//console.log('disk_config', disk_config)
|
|
|
|
|
2019-12-30 08:48:36 +01:00
|
|
|
const config_path = path.join(__dirname, '/../config.json');
|
2019-11-08 05:02:47 +01:00
|
|
|
nconf.argv().env('__').file({file: config_path});
|
2020-01-29 08:08:40 +01:00
|
|
|
console.log('test config_path', config_path);
|
2019-11-08 05:02:47 +01:00
|
|
|
|
2020-01-29 08:08:40 +01:00
|
|
|
const webport = nconf.get('web:port') || 7070;
|
|
|
|
const webbind = nconf.get('web:listen') || '127.0.0.1';
|
2020-01-29 08:16:57 +01:00
|
|
|
const webclient = webbind !== '0.0.0.0' ? webbind : '127.0.0.1';
|
2020-01-29 08:08:40 +01:00
|
|
|
const base_url = 'http://' + webclient + ':' + webport + '/';
|
|
|
|
|
|
|
|
const overlay_bindhost = process.env.overlay__host || nconf.get('web:listen') || '127.0.0.1';
|
|
|
|
console.log('overlay_bindhost', overlay_bindhost);
|
|
|
|
const overlay_host = overlay_bindhost !== '0.0.0.0' ? overlay_bindhost : '127.0.0.1';
|
|
|
|
console.log('overlay_host ', overlay_host);
|
2019-12-30 08:48:36 +01:00
|
|
|
const overlay_port = parseInt(disk_config.api && disk_config.api.port) || nconf.get('web:port') || 7070;
|
|
|
|
// has to have the trailing slash
|
2020-01-29 08:08:40 +01:00
|
|
|
const overlay_url = base_url;
|
2019-12-30 08:48:36 +01:00
|
|
|
|
2020-01-29 08:08:40 +01:00
|
|
|
const platform_api_url = disk_config.api && disk_config.api.api_url || base_url;
|
2020-01-30 09:46:51 +01:00
|
|
|
|
|
|
|
// is it set up?
|
|
|
|
const admin_modkey=nconf.get('admin:modKey');
|
|
|
|
const hasAdminAPI = !!admin_modkey;
|
|
|
|
|
2020-01-29 08:08:40 +01:00
|
|
|
let platform_admin_url = disk_config.api && disk_config.api.admin_url && disk_config.api.admin_url.replace(/\/$/, '');
|
|
|
|
if (!platform_admin_url) {
|
|
|
|
// http://localhost:3000
|
|
|
|
var admin_port=nconf.get('admin:port') || 3000;
|
|
|
|
var admin_listen=nconf.get('admin:listen') || '127.0.0.1';
|
2020-01-30 09:46:51 +01:00
|
|
|
platform_admin_url = 'http://' + admin_listen + ':' + admin_port + '/';
|
2020-01-29 08:08:40 +01:00
|
|
|
}
|
2020-01-30 09:46:51 +01:00
|
|
|
//console.log('env/config.json ', base_url); // platform
|
|
|
|
//console.log('loki.ini ', platform_api_url); // platform
|
|
|
|
//console.log('overlay_url ', overlay_url); // copied from base_url...
|
2020-01-29 08:08:40 +01:00
|
|
|
console.log('platform_api_url ', platform_api_url);
|
2020-01-30 09:46:51 +01:00
|
|
|
//console.log('platform_admin_url', platform_admin_url);
|
|
|
|
|
|
|
|
// This may require the admin interface to be configure, hrm...
|
|
|
|
// do we really need that for unit tests?
|
|
|
|
// well if we're not starting the server, cache would have to be proxied...
|
2019-09-10 06:04:20 +02:00
|
|
|
|
2019-11-08 05:02:47 +01:00
|
|
|
// configure the admin interface for use
|
|
|
|
// can be easily swapped out later
|
|
|
|
const proxyAdmin = require('../server/dataaccess.proxy-admin');
|
|
|
|
// fake dispatcher that only implements what we need
|
|
|
|
proxyAdmin.dispatcher = {
|
|
|
|
// ignore local user updates
|
|
|
|
updateUser: (user, ts, cb) => { cb(user); },
|
|
|
|
// ignore local message updates
|
|
|
|
setMessage: (message, cb) => { if (cb) cb(message); },
|
|
|
|
}
|
|
|
|
// backward compatible
|
|
|
|
if (proxyAdmin.start) {
|
|
|
|
proxyAdmin.start(nconf);
|
|
|
|
}
|
2019-12-02 01:42:42 +01:00
|
|
|
proxyAdmin.apiroot = platform_api_url;
|
2019-11-08 05:02:47 +01:00
|
|
|
if (proxyAdmin.apiroot.replace) {
|
|
|
|
proxyAdmin.apiroot = proxyAdmin.apiroot.replace(/\/$/, '');
|
|
|
|
}
|
2019-12-02 01:42:42 +01:00
|
|
|
proxyAdmin.adminroot = platform_admin_url;
|
2019-11-08 05:02:47 +01:00
|
|
|
if (proxyAdmin.adminroot.replace) {
|
|
|
|
proxyAdmin.adminroot = proxyAdmin.adminroot.replace(/\/$/, '');
|
|
|
|
}
|
|
|
|
|
|
|
|
const cache = proxyAdmin
|
|
|
|
|
2019-12-30 08:48:36 +01:00
|
|
|
let weStartedUnifiedServer = false;
|
|
|
|
const ensureUnifiedServer = () => {
|
2019-09-10 10:16:57 +02:00
|
|
|
return new Promise((resolve, rej) => {
|
2020-01-29 08:08:40 +01:00
|
|
|
//const platformURL = new URL(base_url)
|
|
|
|
//console.log('platform port', platformURL.port)
|
|
|
|
console.log('unified port', webport);
|
|
|
|
lokinet.portIsFree(overlay_bindhost, webport, function(free) {
|
|
|
|
//console.log('overlay_bindhost', overlay_bindhost, 'overlay_host', overlay_host, 'free', free)
|
2019-09-10 10:16:57 +02:00
|
|
|
if (free) {
|
2020-01-29 08:08:40 +01:00
|
|
|
// make sure we use the same config...
|
|
|
|
process.env['config-file-path'] = config_path
|
|
|
|
const startPlatform = require('../server/app');
|
2019-12-30 08:48:36 +01:00
|
|
|
weStartedUnifiedServer = true;
|
2019-09-10 10:16:57 +02:00
|
|
|
} else {
|
|
|
|
console.log('detected running overlay server testing that');
|
|
|
|
}
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
2019-09-10 06:49:54 +02:00
|
|
|
|
2019-09-10 10:16:57 +02:00
|
|
|
const overlayApi = new adnServerAPI(overlay_url);
|
|
|
|
const platformApi = new adnServerAPI(platform_api_url);
|
2020-01-30 09:46:51 +01:00
|
|
|
// probably should never be used...
|
|
|
|
// const adminApi = new adnServerAPI(platform_admin_url, disk_config.api && disk_config.api.modKey || '123abc');
|
2019-09-10 10:16:57 +02:00
|
|
|
|
2019-09-10 06:04:20 +02:00
|
|
|
let modPubKey = '';
|
|
|
|
|
|
|
|
// grab a mod from ini
|
2019-11-25 07:01:50 +01:00
|
|
|
const selectModToken = async (channelId) => {
|
2020-01-30 09:46:51 +01:00
|
|
|
if (process.env.mod_token) {
|
|
|
|
// assuming it's valid
|
|
|
|
return process.env.mod_token;
|
|
|
|
}
|
2020-01-30 09:50:39 +01:00
|
|
|
if (disk_config.test && disk_config.test.mod_token) {
|
2020-01-30 09:46:51 +01:00
|
|
|
// assuming it's valid
|
|
|
|
return disk_config.test.mod_token;
|
|
|
|
}
|
2019-11-25 07:01:50 +01:00
|
|
|
//console.log('selectModToken for', channelId);
|
|
|
|
const modRes = await overlayApi.serverRequest(`loki/v1/channel/${channelId}/get_moderators`);
|
|
|
|
//console.log('modRes', modRes);
|
|
|
|
if (!modRes.response.moderators) {
|
|
|
|
console.warn('cant read moderators for channel', channelId, res);
|
2019-09-10 10:16:57 +02:00
|
|
|
return;
|
|
|
|
}
|
2019-12-30 08:48:36 +01:00
|
|
|
if (!modRes.response.moderators.length && !weStartedUnifiedServer) {
|
2019-12-02 02:40:54 +01:00
|
|
|
console.warn('no moderators for channel', channelId + ', cant addTempMod skipping moderation tests');
|
2019-11-25 07:01:50 +01:00
|
|
|
return;
|
2019-11-08 05:02:47 +01:00
|
|
|
}
|
2019-11-25 07:01:50 +01:00
|
|
|
const modKeys = modRes.response.moderators;
|
|
|
|
//console.log('found moderators', modKeys)
|
2019-11-08 05:02:47 +01:00
|
|
|
let modToken = '';
|
|
|
|
if (!modKeys.length) {
|
|
|
|
// we started platform?
|
2019-12-30 08:48:36 +01:00
|
|
|
if (weStartedUnifiedServer) {
|
2019-11-08 05:02:47 +01:00
|
|
|
console.warn('test.js - no moderators configured and we control overlayServer, creating temporary moderator');
|
|
|
|
const ourModKey = libsignal.curve.generateKeyPair();
|
|
|
|
// encode server's pubKey in base64
|
|
|
|
const ourModPubKey64 = bb.wrap(ourModKey.pubKey).toString('base64');
|
|
|
|
const modPubKey = bb.wrap(ourModKey.pubKey).toString('hex');
|
|
|
|
modToken = await get_challenge(ourModKey, modPubKey);
|
|
|
|
await submit_challenge(modToken, modPubKey);
|
|
|
|
// now elevate to a moderator
|
2020-01-30 09:46:51 +01:00
|
|
|
const user = await getUserID(modPubKey)
|
|
|
|
if (user && user.id) {
|
|
|
|
await config.addTempModerator(user.id);
|
|
|
|
}
|
2019-11-08 05:02:47 +01:00
|
|
|
return modToken;
|
|
|
|
} else {
|
2019-12-02 02:40:54 +01:00
|
|
|
console.warn('no moderators configured and cant addTempMod, skipping moderation tests');
|
2019-11-08 05:02:47 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2020-01-30 09:46:51 +01:00
|
|
|
if (!hasAdminAPI) {
|
|
|
|
console.log('Admin API is not enabled, so we can\'t run moderator tests without a key');
|
|
|
|
return;
|
|
|
|
}
|
2019-09-10 10:16:57 +02:00
|
|
|
const selectedMod = Math.floor(Math.random() * modKeys.length);
|
|
|
|
modPubKey = modKeys[selectedMod];
|
2019-11-25 07:01:50 +01:00
|
|
|
console.log('selected mod @' + modPubKey);
|
2019-09-10 10:16:57 +02:00
|
|
|
if (!modPubKey) {
|
|
|
|
console.warn('selectedMod', selectedMod, 'not in', modKeys.length);
|
|
|
|
return;
|
2019-09-10 06:04:20 +02:00
|
|
|
}
|
2020-01-29 08:08:40 +01:00
|
|
|
// FIXME
|
|
|
|
function getModTokenByUsername(username) {
|
|
|
|
return new Promise((resolve, reject) => {
|
2020-01-30 09:46:51 +01:00
|
|
|
// not available without proxy-admin...
|
2020-01-29 08:08:40 +01:00
|
|
|
cache.getAPITokenByUsername(username, function(data, err) {
|
2020-01-30 09:46:51 +01:00
|
|
|
if (err) console.error('getModTokenByUsername err', err);
|
|
|
|
//console.log('data', data)
|
|
|
|
resolve(data.token);
|
2020-01-29 08:08:40 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
const res = await getModTokenByUsername(modPubKey);
|
|
|
|
if (res) {
|
2020-01-30 09:46:51 +01:00
|
|
|
modToken = res;
|
2020-01-29 08:08:40 +01:00
|
|
|
}
|
|
|
|
/*
|
2019-09-10 06:04:20 +02:00
|
|
|
const res = await adminApi.serverRequest('tokens/@'+modPubKey, {});
|
2019-11-08 05:02:47 +01:00
|
|
|
if (res.response && res.response.data) {
|
|
|
|
modToken = res.response.data.token;
|
|
|
|
}
|
2020-01-29 08:08:40 +01:00
|
|
|
*/
|
|
|
|
|
2019-11-08 05:02:47 +01:00
|
|
|
// it's async
|
|
|
|
/*
|
|
|
|
if (res.response && res.response.data === null) {
|
|
|
|
console.log('need to create a token for this moderator')
|
|
|
|
cache.getUserID(modPubKey, (user, err) => {
|
|
|
|
if (err) console.error('getUserID err', err)
|
|
|
|
if (!user || !user.id) {
|
|
|
|
console.warn('No such moderator user object for', modPubKey);
|
|
|
|
// create user...
|
|
|
|
process.exit();
|
|
|
|
}
|
|
|
|
cache.createOrFindUserToken(user.id, 'messenger', ADN_SCOPES, (tokenObj, err) => {
|
|
|
|
if (err) console.error('createOrFindUserToken err', err)
|
|
|
|
console.log('tokenObj', tokenObj);
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
if (!modToken) console.warn('modToken failure! res', res);
|
2019-09-10 06:04:20 +02:00
|
|
|
return modToken;
|
|
|
|
}
|
2019-09-09 07:42:49 +02:00
|
|
|
|
|
|
|
// make our local keypair
|
|
|
|
const ourKey = libsignal.curve.generateKeyPair();
|
|
|
|
// encode server's pubKey in base64
|
|
|
|
const ourPubKey64 = bb.wrap(ourKey.pubKey).toString('base64');
|
|
|
|
const ourPubKeyHex = bb.wrap(ourKey.pubKey).toString('hex');
|
2019-11-08 05:02:47 +01:00
|
|
|
console.log('running as', ourPubKeyHex);
|
2019-09-09 07:42:49 +02:00
|
|
|
|
2019-11-09 01:20:58 +01:00
|
|
|
const IV_LENGTH = 16;
|
2019-11-08 05:02:47 +01:00
|
|
|
const DHDecrypt = async (symmetricKey, ivAndCiphertext) => {
|
2019-09-09 07:42:49 +02:00
|
|
|
const iv = ivAndCiphertext.slice(0, IV_LENGTH);
|
|
|
|
const ciphertext = ivAndCiphertext.slice(IV_LENGTH);
|
|
|
|
return libsignal.crypto.decrypt(symmetricKey, ciphertext, iv);
|
|
|
|
}
|
|
|
|
|
2019-09-10 10:16:57 +02:00
|
|
|
// globally passing overlayApi
|
|
|
|
function get_challenge(ourKey, ourPubKeyHex) {
|
|
|
|
return new Promise((resolve, rej) => {
|
2019-11-08 05:02:47 +01:00
|
|
|
describe(`get challenge for ${ourPubKeyHex} /loki/v1/get_challenge`, async function() {
|
2019-09-10 10:16:57 +02:00
|
|
|
// this can be broken into more it() if desired
|
2019-09-10 10:49:18 +02:00
|
|
|
//it("returns status code 200", async () => {
|
2019-11-08 05:02:47 +01:00
|
|
|
let tokenString
|
|
|
|
try {
|
2019-09-10 10:16:57 +02:00
|
|
|
const result = await overlayApi.serverRequest('loki/v1/get_challenge', {
|
|
|
|
params: {
|
|
|
|
pubKey: ourPubKeyHex
|
|
|
|
}
|
|
|
|
});
|
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
const body = result.response;
|
|
|
|
//console.log('get challenge body', body);
|
|
|
|
// body.cipherText64
|
|
|
|
// body.serverPubKey64 // base64 encoded pubkey
|
|
|
|
|
|
|
|
// console.log('serverPubKey64', body.serverPubKey64);
|
|
|
|
const serverPubKeyBuff = Buffer.from(body.serverPubKey64, 'base64')
|
|
|
|
const serverPubKeyHex = serverPubKeyBuff.toString('hex');
|
|
|
|
//console.log('serverPubKeyHex', serverPubKeyHex)
|
|
|
|
|
|
|
|
const ivAndCiphertext = Buffer.from(body.cipherText64, 'base64');
|
|
|
|
|
|
|
|
const symmetricKey = libsignal.curve.calculateAgreement(
|
|
|
|
serverPubKeyBuff,
|
|
|
|
ourKey.privKey
|
|
|
|
);
|
|
|
|
const token = await DHDecrypt(symmetricKey, ivAndCiphertext);
|
2019-11-08 05:02:47 +01:00
|
|
|
tokenString = token.toString('utf8');
|
|
|
|
} catch (e) {
|
|
|
|
console.error('platformApi.serverRequest err', e, result)
|
|
|
|
tokenString = '';
|
2019-12-02 02:19:03 +01:00
|
|
|
return rej();
|
2019-11-08 05:02:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//console.log('tokenString', tokenString);
|
|
|
|
resolve(tokenString);
|
2019-09-10 10:49:18 +02:00
|
|
|
//});
|
2019-09-10 10:16:57 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-11-08 05:02:47 +01:00
|
|
|
const submit_challenge = (tokenString, pubKey) => {
|
|
|
|
// we use this promise to delay resolution
|
2019-09-10 10:16:57 +02:00
|
|
|
return new Promise((resolve, rej) => {
|
2019-11-08 05:02:47 +01:00
|
|
|
// I don't think we need or want this describe at all...
|
|
|
|
describe(`submit challenge for ${tokenString} /loki/v1/submit_challenge`, async function() {
|
2019-09-10 10:49:18 +02:00
|
|
|
//it("returns status code 200", async () => {
|
2019-09-10 10:16:57 +02:00
|
|
|
const result = await overlayApi.serverRequest('loki/v1/submit_challenge', {
|
|
|
|
method: 'POST',
|
|
|
|
objBody: {
|
2019-11-08 05:02:47 +01:00
|
|
|
pubKey: pubKey,
|
2019-09-10 10:16:57 +02:00
|
|
|
token: tokenString,
|
|
|
|
},
|
|
|
|
noJson: true
|
|
|
|
});
|
|
|
|
assert.equal(200, result.statusCode);
|
2019-09-10 06:04:20 +02:00
|
|
|
// body should be ''
|
|
|
|
//console.log('submit challenge body', body);
|
2019-09-10 10:16:57 +02:00
|
|
|
resolve();
|
2019-09-10 10:49:18 +02:00
|
|
|
//});
|
2019-09-10 10:16:57 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// requires overlayApi to be configured with a token
|
2019-11-08 05:02:47 +01:00
|
|
|
function getUserID(pubKey) {
|
2019-09-10 10:16:57 +02:00
|
|
|
return new Promise((resolve, rej) => {
|
2019-11-08 05:02:47 +01:00
|
|
|
cache.getUserID(pubKey, function(user, err, meta) {
|
|
|
|
//assert.equal(200, result.statusCode);
|
2019-12-30 09:38:32 +01:00
|
|
|
resolve(user && user.id);
|
2019-09-10 10:16:57 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2019-09-10 06:04:20 +02:00
|
|
|
|
2019-09-10 10:16:57 +02:00
|
|
|
function get_deletes(channelId) {
|
|
|
|
return new Promise((resolve, rej) => {
|
2019-11-08 05:02:47 +01:00
|
|
|
describe("get deletes /loki/v1/channels/1/deletes", async function() {
|
2019-09-10 10:49:18 +02:00
|
|
|
//it("returns status code 200", async () => {
|
2019-09-13 08:09:07 +02:00
|
|
|
const result = await overlayApi.serverRequest('loki/v1/channels/1/deletes');
|
2019-09-10 10:16:57 +02:00
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
resolve();
|
2019-09-10 10:49:18 +02:00
|
|
|
//});
|
2019-09-10 10:16:57 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function create_message(channelId) {
|
|
|
|
return new Promise((resolve, rej) => {
|
2019-11-08 05:02:47 +01:00
|
|
|
describe("create message /channels/1/messages", async function() {
|
2019-09-10 10:49:18 +02:00
|
|
|
//it("returns status code 200", async () => {
|
2019-09-10 10:16:57 +02:00
|
|
|
// create a dummy message
|
2019-11-08 05:02:47 +01:00
|
|
|
let result;
|
|
|
|
try {
|
|
|
|
result = await platformApi.serverRequest('channels/1/messages', {
|
|
|
|
method: 'POST',
|
|
|
|
objBody: {
|
|
|
|
text: 'testing message',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
//console.log('create message result', result, 'token', platformApi.token);
|
2019-12-30 09:38:32 +01:00
|
|
|
if (result.statusCode === 401) {
|
|
|
|
console.error('used token', platformApi.token);
|
|
|
|
const linfo = await overlayApi.serverRequest('loki/v1/user_info');
|
|
|
|
console.log('lokiInfo', linfo);
|
|
|
|
const tinfo = await platformApi.serverRequest('token');
|
|
|
|
console.log('tokenInfo', tinfo);
|
|
|
|
}
|
2019-11-08 05:02:47 +01:00
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
} catch (e) {
|
|
|
|
console.error('platformApi.serverRequest err', e, result)
|
2019-12-02 02:19:03 +01:00
|
|
|
return rej();
|
2019-11-08 05:02:47 +01:00
|
|
|
}
|
2019-09-10 10:16:57 +02:00
|
|
|
resolve(result.response.data.id);
|
2019-09-10 10:49:18 +02:00
|
|
|
//});
|
2019-09-10 10:16:57 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2019-09-10 06:04:20 +02:00
|
|
|
|
2019-11-08 05:02:47 +01:00
|
|
|
function get_message(messageId) {
|
2019-09-10 10:16:57 +02:00
|
|
|
return new Promise(async (resolve, rej) => {
|
|
|
|
// not really a test
|
2019-11-08 05:02:47 +01:00
|
|
|
//describe(`get channel /channels/${channelId}`, function() {
|
2019-09-10 10:16:57 +02:00
|
|
|
//it("returns status code 200", async () => {
|
|
|
|
// get a channel
|
2019-11-08 05:02:47 +01:00
|
|
|
const result = await platformApi.serverRequest(`channels/messages`, {
|
2019-10-30 08:51:48 +01:00
|
|
|
params: {
|
2019-11-08 05:02:47 +01:00
|
|
|
ids: messageId
|
2019-10-30 08:51:48 +01:00
|
|
|
}
|
|
|
|
});
|
2019-11-08 05:02:47 +01:00
|
|
|
//assert.equal(200, result.statusCode);
|
|
|
|
resolve(result.response.data);
|
|
|
|
//});
|
2019-10-30 08:51:48 +01:00
|
|
|
//});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-09-10 10:16:57 +02:00
|
|
|
const runIntegrationTests = async (ourKey, ourPubKeyHex) => {
|
2019-12-02 01:42:42 +01:00
|
|
|
let channelId = 1; // default channel to try to test first
|
2019-09-10 10:16:57 +02:00
|
|
|
|
|
|
|
// get our token
|
2019-11-09 01:20:58 +01:00
|
|
|
let tokenString, userid, mod_userid;
|
2019-11-08 05:02:47 +01:00
|
|
|
describe('get our token', function() {
|
|
|
|
it('get token', async function() {
|
2019-09-10 10:49:18 +02:00
|
|
|
tokenString = await get_challenge(ourKey, ourPubKeyHex);
|
2019-11-25 07:01:50 +01:00
|
|
|
// console.log('tokenString', tokenString);
|
2019-09-10 10:49:18 +02:00
|
|
|
});
|
2019-11-08 05:02:47 +01:00
|
|
|
it('activate token', async function() {
|
2019-09-10 10:49:18 +02:00
|
|
|
// activate token
|
2019-11-08 05:02:47 +01:00
|
|
|
await submit_challenge(tokenString, ourPubKeyHex);
|
2019-09-10 10:49:18 +02:00
|
|
|
});
|
2019-11-08 05:02:47 +01:00
|
|
|
it('set token', async function() {
|
2019-09-10 10:49:18 +02:00
|
|
|
// set token
|
|
|
|
overlayApi.token = tokenString;
|
|
|
|
platformApi.token = tokenString;
|
2019-11-09 01:20:58 +01:00
|
|
|
//userid = await getUserID(ourPubKeyHex);
|
2019-09-10 10:49:18 +02:00
|
|
|
});
|
2019-09-10 10:16:57 +02:00
|
|
|
|
2019-11-08 05:02:47 +01:00
|
|
|
it('user info (non-mod)', async function() {
|
2019-09-10 10:49:18 +02:00
|
|
|
// test token endpoints
|
2019-11-08 05:02:47 +01:00
|
|
|
const result = await overlayApi.serverRequest('loki/v1/user_info');
|
|
|
|
//console.log('user user_info result', result)
|
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
assert.ok(result.response);
|
|
|
|
assert.ok(result.response.data);
|
|
|
|
// we're a freshly created user (hopefully)
|
|
|
|
assert.ok(!result.response.data.moderator_status);
|
2019-11-09 01:20:58 +01:00
|
|
|
assert.ok(result.response.data.user_id);
|
|
|
|
userid = result.response.data.user_id;
|
2019-11-08 05:02:47 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
// test moderator security...
|
|
|
|
describe('moderator security tests', function() {
|
2019-11-09 01:20:58 +01:00
|
|
|
it('cant promote to moderator', async function() {
|
|
|
|
const result = await overlayApi.serverRequest(`loki/v1/moderators/${userid}`, {
|
|
|
|
method: 'POST',
|
|
|
|
});
|
|
|
|
assert.equal(401, result.statusCode);
|
|
|
|
});
|
2019-11-08 05:02:47 +01:00
|
|
|
it('cant blacklist', async function() {
|
|
|
|
const result = await overlayApi.serverRequest(`loki/v1/moderation/blacklist/${userid}`, {
|
|
|
|
method: 'POST',
|
|
|
|
});
|
|
|
|
/*
|
|
|
|
{
|
|
|
|
err: 'statusCode',
|
|
|
|
statusCode: 401,
|
|
|
|
response: {
|
|
|
|
meta: {
|
|
|
|
code: 401,
|
|
|
|
error_message: 'Call requires authentication: Authentication required to fetch token.'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
assert.equal(401, result.statusCode);
|
|
|
|
});
|
2019-09-10 10:49:18 +02:00
|
|
|
});
|
2019-09-10 10:16:57 +02:00
|
|
|
|
2019-09-10 10:49:18 +02:00
|
|
|
// make sure we have a channel to test with
|
2019-11-08 05:02:47 +01:00
|
|
|
describe('channel testing', function() {
|
|
|
|
it('make sure we have a channel to test', async function() {
|
|
|
|
const result = await platformApi.serverRequest(`channels/${channelId}`, {
|
|
|
|
params: {
|
|
|
|
include_recent_message: 1
|
|
|
|
}
|
|
|
|
});
|
|
|
|
const chnlCheck = result.response.data;
|
2019-09-10 10:49:18 +02:00
|
|
|
if (Array.isArray(chnlCheck)) {
|
|
|
|
// make a channel for testing
|
2019-11-08 05:02:47 +01:00
|
|
|
const result = await platformApi.serverRequest('channels', {
|
|
|
|
method: 'POST',
|
|
|
|
objBody: {
|
|
|
|
type: 'moe.sapphire.test',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
channelId = result.response.data.id;
|
2019-09-10 11:17:19 +02:00
|
|
|
console.log('created channel', channelId);
|
2019-09-10 10:49:18 +02:00
|
|
|
}
|
|
|
|
});
|
2019-12-30 09:38:32 +01:00
|
|
|
let messageId, messageId1, messageId2, messageId3, messageId4, messageId5
|
2019-11-08 05:02:47 +01:00
|
|
|
it('create message to test with', async function() {
|
2019-09-10 10:49:18 +02:00
|
|
|
// well we need to create a new message for moderation test
|
|
|
|
messageId = await create_message(channelId);
|
2019-10-30 08:51:48 +01:00
|
|
|
messageId1 = await create_message(channelId);
|
|
|
|
messageId2 = await create_message(channelId);
|
|
|
|
messageId3 = await create_message(channelId);
|
|
|
|
messageId4 = await create_message(channelId);
|
2019-11-12 03:24:08 +01:00
|
|
|
messageId5 = await create_message(channelId);
|
2019-09-10 10:49:18 +02:00
|
|
|
});
|
2019-11-09 01:20:58 +01:00
|
|
|
it('user cant mod delete message', async function() {
|
2019-11-08 05:02:47 +01:00
|
|
|
const result = await overlayApi.serverRequest(`loki/v1/moderation/message/${messageId}`, {
|
|
|
|
method: 'DELETE',
|
|
|
|
});
|
|
|
|
assert.equal(401, result.statusCode);
|
2020-01-29 08:08:40 +01:00
|
|
|
// result.response.data will be undefined
|
2019-11-08 05:02:47 +01:00
|
|
|
});
|
|
|
|
it('user multi delete test', async function () {
|
|
|
|
//let message = await get_message(messageId);
|
2019-10-30 08:51:48 +01:00
|
|
|
if (messageId3 && messageId4) {
|
2019-11-08 05:02:47 +01:00
|
|
|
const result = await overlayApi.serverRequest('loki/v1/messages', {
|
|
|
|
method: 'DELETE',
|
|
|
|
params: {
|
|
|
|
ids: [messageId3, messageId4].join(',')
|
|
|
|
}
|
|
|
|
});
|
2019-11-12 03:24:08 +01:00
|
|
|
assert.equal(200, result.statusCode);
|
2020-01-29 08:08:40 +01:00
|
|
|
assert.ok(result.response.data.every(x => x.is_deleted));
|
2019-11-12 03:24:08 +01:00
|
|
|
} else {
|
|
|
|
console.log('skipping');
|
|
|
|
}
|
|
|
|
//message = await get_message(messageId);
|
|
|
|
//console.log('message after', message);
|
|
|
|
});
|
|
|
|
it('user single delete through multi endpoint test', async function () {
|
|
|
|
//let message = await get_message(messageId);
|
|
|
|
if (messageId5) {
|
|
|
|
const result = await overlayApi.serverRequest('loki/v1/messages', {
|
|
|
|
method: 'DELETE',
|
|
|
|
params: {
|
|
|
|
ids: [messageId5].join(',')
|
|
|
|
}
|
|
|
|
});
|
|
|
|
assert.equal(200, result.statusCode);
|
2020-01-29 08:08:40 +01:00
|
|
|
assert.ok(result.response.data.every(x => x.is_deleted));
|
2019-10-30 08:51:48 +01:00
|
|
|
} else {
|
2019-11-12 03:24:08 +01:00
|
|
|
console.log('skipping');
|
2019-10-30 08:51:48 +01:00
|
|
|
}
|
2019-11-08 05:02:47 +01:00
|
|
|
//message = await get_message(messageId);
|
|
|
|
//console.log('message after', message);
|
2019-10-30 08:51:48 +01:00
|
|
|
});
|
2019-11-12 03:24:08 +01:00
|
|
|
|
2019-11-08 05:02:47 +01:00
|
|
|
it('can get deletes for channel', function() {
|
2019-09-10 10:49:18 +02:00
|
|
|
get_deletes(channelId);
|
|
|
|
});
|
2019-11-12 03:24:08 +01:00
|
|
|
it('can get moderators for channel', async function() {
|
|
|
|
result = await overlayApi.serverRequest('loki/v1/channels/1/moderators');
|
|
|
|
assert.equal(200, result.statusCode);
|
2019-09-13 08:03:01 +02:00
|
|
|
});
|
2019-10-30 10:17:55 +01:00
|
|
|
// Moderator only functions
|
2019-11-09 01:20:58 +01:00
|
|
|
let modToken
|
2019-11-08 05:02:47 +01:00
|
|
|
describe('channel moderator testing', function() {
|
|
|
|
it('we have moderator to test with', async function() {
|
2019-10-30 10:17:55 +01:00
|
|
|
// now do moderation tests
|
2019-11-25 07:01:50 +01:00
|
|
|
modToken = await selectModToken(channelId);
|
2019-10-30 10:17:55 +01:00
|
|
|
if (!modToken) {
|
|
|
|
console.error('No modToken, skipping moderation tests');
|
|
|
|
// all tests should be complete
|
|
|
|
//process.exit(0);
|
|
|
|
return;
|
|
|
|
}
|
2019-11-08 05:02:47 +01:00
|
|
|
console.log('Setting modToken to', modToken);
|
2019-10-30 10:17:55 +01:00
|
|
|
overlayApi.token = modToken;
|
|
|
|
});
|
2019-11-08 05:02:47 +01:00
|
|
|
it('mod user info', async function() {
|
2019-12-02 01:42:42 +01:00
|
|
|
if (!modToken) {
|
|
|
|
console.log('no mods skipping');
|
|
|
|
return;
|
|
|
|
}
|
2019-11-08 05:02:47 +01:00
|
|
|
// test token endpoints
|
2020-01-30 09:46:51 +01:00
|
|
|
// console.log('token', overlayApi.token);
|
2019-11-08 05:02:47 +01:00
|
|
|
const result = await overlayApi.serverRequest('loki/v1/user_info');
|
2019-11-25 07:01:50 +01:00
|
|
|
// console.log('mod user_info result', result)
|
2019-11-08 05:02:47 +01:00
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
assert.ok(result.response);
|
|
|
|
assert.ok(result.response.data);
|
|
|
|
assert.ok(result.response.data.moderator_status);
|
|
|
|
// || result.response.moderator_status.match(',')
|
|
|
|
// I think we only should be global here for now...
|
|
|
|
assert.equal(true, result.response.data.moderator_status === true);
|
2019-11-09 01:20:58 +01:00
|
|
|
assert.ok(result.response.data.user_id);
|
|
|
|
mod_userid=result.response.data.user_id;
|
|
|
|
});
|
|
|
|
it('user cant demote moderators', async function() {
|
|
|
|
overlayApi.token = tokenString; // switch to user
|
|
|
|
const result = await overlayApi.serverRequest(`loki/v1/moderators/${mod_userid}`, {
|
|
|
|
method: 'DELETE',
|
|
|
|
});
|
|
|
|
assert.equal(401, result.statusCode);
|
2019-11-08 05:02:47 +01:00
|
|
|
});
|
|
|
|
it('mod delete test', async function() {
|
2019-12-02 01:42:42 +01:00
|
|
|
if (!modToken) {
|
|
|
|
console.log('no mods skipping');
|
|
|
|
return;
|
|
|
|
}
|
2019-11-09 01:20:58 +01:00
|
|
|
overlayApi.token = modToken; // switch back to mod
|
2019-10-30 10:17:55 +01:00
|
|
|
if (modToken && messageId) {
|
2019-11-08 05:02:47 +01:00
|
|
|
//let message = await get_message(messageId);
|
|
|
|
//console.log('message1', message);
|
|
|
|
const result = await overlayApi.serverRequest(`loki/v1/moderation/message/${messageId}`, {
|
|
|
|
method: 'DELETE',
|
|
|
|
});
|
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
} else {
|
|
|
|
console.log('skipping modSingleDelete');
|
2019-10-30 10:17:55 +01:00
|
|
|
}
|
|
|
|
});
|
2019-11-12 03:24:08 +01:00
|
|
|
it('get moderators for channel has content', async function() {
|
2019-12-02 01:42:42 +01:00
|
|
|
if (!modToken) {
|
|
|
|
console.log('no mods skipping');
|
|
|
|
return;
|
|
|
|
}
|
2019-11-12 03:24:08 +01:00
|
|
|
result = await overlayApi.serverRequest('loki/v1/channels/1/moderators');
|
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
assert.ok(result.response.moderators.length > 0);
|
|
|
|
});
|
2019-11-08 05:02:47 +01:00
|
|
|
it('mod multi delete test', async function() {
|
2019-10-30 10:17:55 +01:00
|
|
|
if (modToken && messageId1 && messageId2) {
|
2019-11-08 05:02:47 +01:00
|
|
|
const result = await overlayApi.serverRequest('loki/v1/moderation/messages', {
|
|
|
|
method: 'DELETE',
|
|
|
|
params: {
|
|
|
|
ids: [messageId1, messageId2].join(',')
|
|
|
|
}
|
|
|
|
});
|
|
|
|
assert.equal(200, result.statusCode);
|
2019-10-30 10:17:55 +01:00
|
|
|
} else {
|
2019-11-08 05:02:47 +01:00
|
|
|
console.log('skipping modMutliDelete');
|
2019-10-30 10:17:55 +01:00
|
|
|
}
|
|
|
|
});
|
2020-01-30 09:46:51 +01:00
|
|
|
it('mod update channel', async function() {
|
|
|
|
if (modToken) {
|
|
|
|
const chanObj = await platformApi.serverRequest('channels/' + channelId, {
|
|
|
|
params: {
|
|
|
|
include_annotations: 1,
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (!chanObj.response.data) {
|
|
|
|
console.log('Can not safely test moderatorUpdateChannel, skipping');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const result = await overlayApi.serverRequest('loki/v1/channels/' + channelId, {
|
|
|
|
method: 'PUT',
|
|
|
|
body: chanObj.data
|
|
|
|
});
|
|
|
|
// why is there two responses..
|
|
|
|
//console.log('result', result.response.response.data);
|
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
assert.equal(200, result.response.response.meta.code);
|
|
|
|
assert.equal(channelId, result.response.response.data.id);
|
|
|
|
} else {
|
|
|
|
console.log('skipping moderatorUpdateChannel');
|
|
|
|
}
|
|
|
|
});
|
2019-10-30 10:17:55 +01:00
|
|
|
});
|
2019-11-08 05:02:47 +01:00
|
|
|
|
|
|
|
describe('blacklist testing', function() {
|
|
|
|
it('make sure token is still valid', async function() {
|
2019-12-02 01:42:42 +01:00
|
|
|
if (!modToken) {
|
|
|
|
console.log('no mods skipping');
|
|
|
|
return;
|
|
|
|
}
|
2019-11-08 05:02:47 +01:00
|
|
|
// test token endpoints
|
|
|
|
const result = await overlayApi.serverRequest('loki/v1/user_info');
|
|
|
|
//console.log('user user_info result', result)
|
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
assert.ok(result.response);
|
|
|
|
assert.ok(result.response.data);
|
|
|
|
});
|
2019-11-25 07:01:50 +01:00
|
|
|
it('blacklist ourself @', async function() {
|
2019-12-02 01:42:42 +01:00
|
|
|
if (!modToken) {
|
|
|
|
console.log('no mods skipping');
|
|
|
|
return;
|
|
|
|
}
|
2019-11-25 07:01:50 +01:00
|
|
|
const result = await overlayApi.serverRequest(`loki/v1/moderation/blacklist/@${ourPubKeyHex}`, {
|
|
|
|
method: 'POST',
|
|
|
|
});
|
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
assert.ok(result.response);
|
|
|
|
assert.ok(result.response.data);
|
|
|
|
});
|
|
|
|
it('blacklist clear', async function() {
|
2019-12-02 01:42:42 +01:00
|
|
|
if (!modToken) {
|
|
|
|
console.log('no mods skipping');
|
|
|
|
return;
|
|
|
|
}
|
2019-11-25 07:01:50 +01:00
|
|
|
const userid = await getUserID(ourPubKeyHex);
|
|
|
|
assert.ok(userid);
|
|
|
|
const result = await overlayApi.serverRequest(`loki/v1/moderation/blacklist/@${ourPubKeyHex}`, {
|
|
|
|
method: 'DELETE',
|
|
|
|
});
|
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
assert.ok(result.response);
|
|
|
|
assert.ok(result.response.data);
|
|
|
|
});
|
|
|
|
it('blacklist self by integer id', async function() {
|
2019-12-02 01:42:42 +01:00
|
|
|
if (!modToken) {
|
|
|
|
console.log('no mods skipping');
|
|
|
|
return;
|
|
|
|
}
|
2019-11-08 05:02:47 +01:00
|
|
|
//console.log('key', ourPubKeyHex);
|
|
|
|
const userid = await getUserID(ourPubKeyHex);
|
|
|
|
assert.ok(userid);
|
|
|
|
//console.log('userid', userid);
|
|
|
|
const result = await overlayApi.serverRequest(`loki/v1/moderation/blacklist/${userid}`, {
|
|
|
|
method: 'POST',
|
|
|
|
});
|
|
|
|
//console.log('after blacklist', result);
|
|
|
|
assert.equal(200, result.statusCode);
|
|
|
|
assert.ok(result.response);
|
|
|
|
assert.ok(result.response.data);
|
|
|
|
});
|
|
|
|
it('switch back to banned user', async function() {
|
|
|
|
//console.log('changing back to', tokenString);
|
|
|
|
overlayApi.token = tokenString;
|
|
|
|
});
|
|
|
|
it('banned token vs platform', async function() {
|
2019-12-02 02:40:54 +01:00
|
|
|
if (!modToken) {
|
|
|
|
console.log('no mods skipping');
|
|
|
|
return;
|
|
|
|
}
|
2019-11-08 05:02:47 +01:00
|
|
|
//user_info();
|
2019-12-02 02:19:03 +01:00
|
|
|
const result = await platformApi.serverRequest('token');
|
|
|
|
// console.log('token for', platformApi.token, result);
|
|
|
|
assert.equal(401, result.statusCode);
|
2019-11-08 05:02:47 +01:00
|
|
|
});
|
|
|
|
it('banned token vs overlay', async function() {
|
2019-12-02 02:40:54 +01:00
|
|
|
if (!modToken) {
|
|
|
|
console.log('no mods skipping');
|
|
|
|
return;
|
|
|
|
}
|
2019-11-08 05:02:47 +01:00
|
|
|
//user_info();
|
2019-12-02 02:19:03 +01:00
|
|
|
const result = await overlayApi.serverRequest('loki/v1/user_info');
|
|
|
|
// console.log('token for', platformApi.token, result);
|
|
|
|
assert.equal(401, result.statusCode);
|
2019-11-08 05:02:47 +01:00
|
|
|
});
|
|
|
|
it('try to reregister with banned token', async function() {
|
2019-12-02 01:42:42 +01:00
|
|
|
// need to be able to ban it
|
|
|
|
if (!modToken) {
|
|
|
|
console.log('no mods skipping');
|
|
|
|
return;
|
|
|
|
}
|
2019-11-08 05:02:47 +01:00
|
|
|
const result = await overlayApi.serverRequest('loki/v1/get_challenge', {
|
|
|
|
params: {
|
|
|
|
pubKey: ourPubKeyHex
|
|
|
|
}
|
|
|
|
});
|
|
|
|
assert.equal(401, result.statusCode);
|
|
|
|
//console.log('tokenString', result)
|
|
|
|
});
|
|
|
|
});
|
2019-09-10 10:49:18 +02:00
|
|
|
});
|
|
|
|
});
|
2019-09-10 10:16:57 +02:00
|
|
|
}
|
|
|
|
|
2019-11-08 05:02:47 +01:00
|
|
|
// you can't use => with mocha, you'll loose this context
|
|
|
|
before(async function() {
|
|
|
|
//this.timeout(60 * 1000); // can't be in an arrow function
|
2019-12-30 08:48:36 +01:00
|
|
|
await ensureUnifiedServer();
|
|
|
|
console.log('unified server ready');
|
2019-11-08 05:02:47 +01:00
|
|
|
})
|
2019-09-10 10:16:57 +02:00
|
|
|
runIntegrationTests(ourKey, ourPubKeyHex);
|