app.portBindings and newManifest.tcpPorts may be null
This commit is contained in:
161
src/test/apps-test.js
Normal file
161
src/test/apps-test.js
Normal file
@@ -0,0 +1,161 @@
|
||||
/* jslint node:true */
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
var appdb = require('../appdb.js'),
|
||||
apps = require('../apps.js'),
|
||||
AppsError = apps.AppsError,
|
||||
async = require('async'),
|
||||
config = require('../config.js'),
|
||||
constants = require('../constants.js'),
|
||||
database = require('../database.js'),
|
||||
expect = require('expect.js');
|
||||
|
||||
describe('Apps', function () {
|
||||
var APP_0 = {
|
||||
id: 'appid-0',
|
||||
appStoreId: 'appStoreId-0',
|
||||
installationState: appdb.ISTATE_PENDING_INSTALL,
|
||||
installationProgress: null,
|
||||
runState: null,
|
||||
location: 'some-location-0',
|
||||
manifest: {
|
||||
version: '0.1', dockerImage: 'docker/app0', healthCheckPath: '/', httpPort: 80, title: 'app0',
|
||||
tcpPorts: {
|
||||
PORT: {
|
||||
description: 'this is a port that i expose',
|
||||
containerPort: '1234'
|
||||
}
|
||||
}
|
||||
},
|
||||
httpPort: null,
|
||||
containerId: null,
|
||||
portBindings: { PORT: 5678 },
|
||||
healthy: null,
|
||||
accessRestriction: ''
|
||||
};
|
||||
|
||||
before(function (done) {
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear,
|
||||
appdb.add.bind(null, APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction)
|
||||
], done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
database._clear(done);
|
||||
});
|
||||
|
||||
describe('validateHostname', function () {
|
||||
it('does not allow admin subdomain', function () {
|
||||
expect(apps._validateHostname(constants.ADMIN_LOCATION, 'cloudron.us')).to.be.an(Error);
|
||||
});
|
||||
|
||||
it('cannot have >63 length subdomains', function () {
|
||||
var s = '';
|
||||
for (var i = 0; i < 64; i++) s += 's';
|
||||
expect(apps._validateHostname(s, 'cloudron.us')).to.be.an(Error);
|
||||
});
|
||||
|
||||
it('allows only alphanumerics and hypen', function () {
|
||||
expect(apps._validateHostname('#2r', 'cloudron.us')).to.be.an(Error);
|
||||
expect(apps._validateHostname('a%b', 'cloudron.us')).to.be.an(Error);
|
||||
expect(apps._validateHostname('ab_', 'cloudron.us')).to.be.an(Error);
|
||||
expect(apps._validateHostname('a.b', 'cloudron.us')).to.be.an(Error);
|
||||
expect(apps._validateHostname('-ab', 'cloudron.us')).to.be.an(Error);
|
||||
expect(apps._validateHostname('ab-', 'cloudron.us')).to.be.an(Error);
|
||||
});
|
||||
|
||||
it('total length cannot exceed 255', function () {
|
||||
var s = '';
|
||||
for (var i = 0; i < (255 - 'cloudron.us'.length); i++) s += 's';
|
||||
|
||||
expect(apps._validateHostname(s, 'cloudron.us')).to.be.an(Error);
|
||||
});
|
||||
|
||||
it('allow valid domains', function () {
|
||||
expect(apps._validateHostname('a', 'cloudron.us')).to.be(null);
|
||||
expect(apps._validateHostname('a0-x', 'cloudron.us')).to.be(null);
|
||||
expect(apps._validateHostname('01', 'cloudron.us')).to.be(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('validatePortBindings', function () {
|
||||
it('does not allow invalid host port', function () {
|
||||
expect(apps._validatePortBindings({ port: -1 })).to.be.an(Error);
|
||||
expect(apps._validatePortBindings({ port: 0 })).to.be.an(Error);
|
||||
expect(apps._validatePortBindings({ port: 'text' })).to.be.an(Error);
|
||||
expect(apps._validatePortBindings({ port: 65536 })).to.be.an(Error);
|
||||
expect(apps._validatePortBindings({ port: 1024 })).to.be.an(Error);
|
||||
});
|
||||
|
||||
it('does not allow ports not as part of manifest', function () {
|
||||
expect(apps._validatePortBindings({ port: 1567 })).to.be.an(Error);
|
||||
expect(apps._validatePortBindings({ port: 1567 }, { port3: null })).to.be.an(Error);
|
||||
});
|
||||
|
||||
it('allows valid bindings', function () {
|
||||
expect(apps._validatePortBindings({ port: 1025 }, { port: null })).to.be(null);
|
||||
expect(apps._validatePortBindings({
|
||||
port1: 4033,
|
||||
port2: 3242,
|
||||
port3: 1234
|
||||
}, { port1: null, port2: null, port3: null })).to.be(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getters', function () {
|
||||
it('cannot get invalid app', function (done) {
|
||||
apps.get('nope', function (error, app) {
|
||||
expect(error).to.be.ok();
|
||||
expect(error.reason).to.be(AppsError.NOT_FOUND);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can get valid app', function (done) {
|
||||
apps.get(APP_0.id, function (error, app) {
|
||||
expect(error).to.be(null);
|
||||
expect(app).to.be.ok();
|
||||
expect(app.iconUrl).to.be(null);
|
||||
expect(app.fqdn).to.eql(APP_0.location + '-' + config.fqdn());
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot getBySubdomain', function (done) {
|
||||
apps.getBySubdomain('moang', function (error, app) {
|
||||
expect(error).to.be.ok();
|
||||
expect(error.reason).to.be(AppsError.NOT_FOUND);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can getBySubdomain', function (done) {
|
||||
apps.getBySubdomain(APP_0.location, function (error, app) {
|
||||
expect(error).to.be(null);
|
||||
expect(app).to.be.ok();
|
||||
expect(app.iconUrl).to.eql(null);
|
||||
expect(app.fqdn).to.eql(APP_0.location + '-' + config.fqdn());
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can getAll', function (done) {
|
||||
apps.getAll(function (error, apps) {
|
||||
expect(error).to.be(null);
|
||||
expect(apps).to.be.an(Array);
|
||||
expect(apps[0].id).to.be(APP_0.id);
|
||||
expect(apps[0].iconUrl).to.be(null);
|
||||
expect(apps[0].fqdn).to.eql(APP_0.location + '-' + config.fqdn());
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
212
src/test/apptask-test.js
Normal file
212
src/test/apptask-test.js
Normal file
@@ -0,0 +1,212 @@
|
||||
/* jslint node:true */
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
var addons = require('../addons.js'),
|
||||
appdb = require('../appdb.js'),
|
||||
apptask = require('../apptask.js'),
|
||||
config = require('../config.js'),
|
||||
database = require('../database.js'),
|
||||
expect = require('expect.js'),
|
||||
fs = require('fs'),
|
||||
net = require('net'),
|
||||
nock = require('nock'),
|
||||
paths = require('../paths.js'),
|
||||
sysinfo = require('../sysinfo.js'),
|
||||
_ = require('underscore');
|
||||
|
||||
var MANIFEST = {
|
||||
"id": "io.cloudron.test",
|
||||
"author": "The Presidents Of the United States Of America",
|
||||
"title": "test title",
|
||||
"description": "test description",
|
||||
"tagline": "test rocks",
|
||||
"website": "http://test.cloudron.io",
|
||||
"contactEmail": "support@cloudron.io",
|
||||
"version": "0.1.0",
|
||||
"manifestVersion": 1,
|
||||
"dockerImage": "girish/test:0.2.0",
|
||||
"healthCheckPath": "/",
|
||||
"httpPort": 7777,
|
||||
"tcpPorts": {
|
||||
"ECHO_SERVER_PORT": {
|
||||
"title": "Echo Server Port",
|
||||
"description": "Echo server",
|
||||
"containerPort": 7778
|
||||
}
|
||||
},
|
||||
"addons": {
|
||||
"oauth": { },
|
||||
"redis": { },
|
||||
"mysql": { },
|
||||
"postgresql": { }
|
||||
}
|
||||
};
|
||||
|
||||
var APP = {
|
||||
id: 'appid',
|
||||
appStoreId: 'appStoreId',
|
||||
installationState: appdb.ISTATE_PENDING_INSTALL,
|
||||
runState: null,
|
||||
location: 'applocation',
|
||||
manifest: MANIFEST,
|
||||
containerId: null,
|
||||
httpPort: 4567,
|
||||
portBindings: null,
|
||||
accessRestriction: '',
|
||||
dnsRecordId: 'someDnsRecordId'
|
||||
};
|
||||
|
||||
describe('apptask', function () {
|
||||
before(function (done) {
|
||||
config.set('version', '0.5.0');
|
||||
database.initialize(function (error) {
|
||||
expect(error).to.be(null);
|
||||
appdb.add(APP.id, APP.appStoreId, APP.manifest, APP.location, APP.portBindings, APP.accessRestriction, done);
|
||||
});
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
database._clear(done);
|
||||
});
|
||||
|
||||
it('initializes succesfully', function (done) {
|
||||
apptask.initialize(done);
|
||||
});
|
||||
|
||||
it('free port', function (done) {
|
||||
apptask._getFreePort(function (error, port) {
|
||||
expect(error).to.be(null);
|
||||
expect(port).to.be.a('number');
|
||||
var client = net.connect(port);
|
||||
client.on('connect', function () { done(new Error('Port is not free:' + port)); });
|
||||
client.on('error', function (error) { done(); });
|
||||
});
|
||||
});
|
||||
|
||||
it('configure nginx correctly', function (done) {
|
||||
apptask._configureNginx(APP, function (error) {
|
||||
expect(fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + APP.id + '.conf'));
|
||||
// expect(error).to.be(null); // this fails because nginx cannot be restarted
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('unconfigure nginx', function (done) {
|
||||
apptask._unconfigureNginx(APP, function (error) {
|
||||
expect(!fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + APP.id + '.conf'));
|
||||
// expect(error).to.be(null); // this fails because nginx cannot be restarted
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('create volume', function (done) {
|
||||
apptask._createVolume(APP, function (error) {
|
||||
expect(fs.existsSync(paths.DATA_DIR + '/' + APP.id + '/data')).to.be(true);
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('delete volume', function (done) {
|
||||
apptask._deleteVolume(APP, function (error) {
|
||||
expect(!fs.existsSync(paths.DATA_DIR + '/' + APP.id + '/data')).to.be(true);
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('allocate OAuth credentials', function (done) {
|
||||
addons._allocateOAuthCredentials(APP, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('remove OAuth credentials', function (done) {
|
||||
addons._removeOAuthCredentials(APP, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('remove OAuth credentials twice succeeds', function (done) {
|
||||
addons._removeOAuthCredentials(APP, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('barfs on empty manifest', function (done) {
|
||||
var badApp = _.extend({ }, APP);
|
||||
badApp.manifest = { };
|
||||
|
||||
apptask._verifyManifest(badApp, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('barfs on bad manifest', function (done) {
|
||||
var badApp = _.extend({ }, APP);
|
||||
badApp.manifest = _.extend({ }, APP.manifest);
|
||||
delete badApp.manifest['id'];
|
||||
|
||||
apptask._verifyManifest(badApp, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('barfs on incompatible manifest', function (done) {
|
||||
var badApp = _.extend({ }, APP);
|
||||
badApp.manifest = _.extend({ }, APP.manifest);
|
||||
badApp.manifest.maxBoxVersion = '0.0.0'; // max box version is too small
|
||||
|
||||
apptask._verifyManifest(badApp, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('verifies manifest', function (done) {
|
||||
var goodApp = _.extend({ }, APP);
|
||||
|
||||
apptask._verifyManifest(goodApp, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('registers subdomain', function (done) {
|
||||
nock.cleanAll();
|
||||
var scope = nock(config.apiServerOrigin())
|
||||
.post('/api/v1/subdomains?token=' + config.token(), { records: [ { subdomain: APP.location, type: 'A', value: sysinfo.getIp() } ] })
|
||||
.reply(201, { ids: [ APP.dnsRecordId ] });
|
||||
|
||||
apptask._registerSubdomain(APP, function (error) {
|
||||
expect(error).to.be(null);
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('unregisters subdomain', function (done) {
|
||||
nock.cleanAll();
|
||||
var scope = nock(config.apiServerOrigin())
|
||||
.delete('/api/v1/subdomains/' + APP.dnsRecordId + '?token=' + config.token())
|
||||
.reply(204, {});
|
||||
|
||||
apptask._unregisterSubdomain(APP, function (error) {
|
||||
expect(error).to.be(null);
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
58
src/test/checkInstall
Executable file
58
src/test/checkInstall
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
readonly SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
# reset sudo timestamp to avoid wrong success
|
||||
sudo -k || sudo --reset-timestamp
|
||||
|
||||
# checks if all scripts are sudo access
|
||||
scripts=("${SOURCE_DIR}/scripts/rmappdir.sh" \
|
||||
"${SOURCE_DIR}/scripts/createappdir.sh" \
|
||||
"${SOURCE_DIR}/scripts/reloadnginx.sh" \
|
||||
"${SOURCE_DIR}/scripts/backupbox.sh" \
|
||||
"${SOURCE_DIR}/scripts/backupapp.sh" \
|
||||
"${SOURCE_DIR}/scripts/restoreapp.sh" \
|
||||
"${SOURCE_DIR}/scripts/reboot.sh" \
|
||||
"${SOURCE_DIR}/scripts/backupswap.sh" \
|
||||
"${SOURCE_DIR}/scripts/reloadcollectd.sh")
|
||||
|
||||
for script in "${scripts[@]}"; do
|
||||
if [[ $(sudo -n "${script}" --check 2>/dev/null) != "OK" ]]; then
|
||||
echo ""
|
||||
echo "${script} does not have sudo access."
|
||||
echo "You have to add the lines below to /etc/sudoers.d/yellowtent."
|
||||
echo ""
|
||||
echo "Defaults!${script} env_keep=\"HOME NODE_ENV\""
|
||||
echo "${USER} ALL=(ALL) NOPASSWD: ${script}"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if ! docker inspect girish/test:0.2.0 >/dev/null 2>/dev/null; then
|
||||
echo "docker pull girish/test:0.2.0 for tests to run"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker inspect cloudron/redis:0.3.0 >/dev/null 2>/dev/null; then
|
||||
echo "docker pull cloudron/redis:0.3.0 for tests to run"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker inspect cloudron/mysql:0.3.0 >/dev/null 2>/dev/null; then
|
||||
echo "docker pull cloudron/mysql:0.3.0 for tests to run"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker inspect cloudron/postgresql:0.3.0 >/dev/null 2>/dev/null; then
|
||||
echo "docker pull cloudron/postgresql:0.3.0 for tests to run"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker inspect cloudron/mongodb:0.3.0 >/dev/null 2>/dev/null; then
|
||||
echo "docker pull cloudron/mongodb:0.3.0 for tests to run"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
95
src/test/config-test.js
Normal file
95
src/test/config-test.js
Normal file
@@ -0,0 +1,95 @@
|
||||
/* jslint node:true */
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global after:false */
|
||||
/* global before:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
var constants = require('../constants.js'),
|
||||
expect = require('expect.js'),
|
||||
fs = require('fs'),
|
||||
path = require('path');
|
||||
|
||||
var config = null;
|
||||
|
||||
describe('config', function () {
|
||||
before(function () {
|
||||
delete require.cache[require.resolve('../config.js')];
|
||||
config = require('../config.js');
|
||||
});
|
||||
|
||||
after(function () {
|
||||
delete require.cache[require.resolve('../config.js')];
|
||||
});
|
||||
|
||||
it('baseDir() is set', function (done) {
|
||||
expect(config.baseDir()).to.be.ok();
|
||||
done();
|
||||
});
|
||||
|
||||
it('cloudron.conf generated automatically', function (done) {
|
||||
expect(fs.existsSync(path.join(config.baseDir(), 'configs/cloudron.conf'))).to.be.ok();
|
||||
done();
|
||||
});
|
||||
|
||||
it('did set default values', function () {
|
||||
expect(config.isCustomDomain()).to.equal(false);
|
||||
expect(config.fqdn()).to.equal('localhost');
|
||||
expect(config.adminOrigin()).to.equal('https://' + constants.ADMIN_LOCATION + '-localhost');
|
||||
expect(config.appFqdn('app')).to.equal('app-localhost');
|
||||
expect(config.zoneName()).to.equal('localhost');
|
||||
});
|
||||
|
||||
it('set saves value in file', function (done) {
|
||||
config.set('foobar', 'somevalue');
|
||||
expect(JSON.parse(fs.readFileSync(path.join(config.baseDir(), 'configs/cloudron.conf'))).foobar).to.eql('somevalue');
|
||||
done();
|
||||
});
|
||||
|
||||
it('set - simple key value', function (done) {
|
||||
config.set('foobar', 'somevalue2');
|
||||
expect(config.get('foobar')).to.eql('somevalue2');
|
||||
done();
|
||||
});
|
||||
|
||||
it('set - object', function (done) {
|
||||
config.set( { fqdn: 'something.com' } );
|
||||
expect(config.fqdn()).to.eql('something.com');
|
||||
done();
|
||||
});
|
||||
|
||||
it('uses dotted locations with custom domain', function () {
|
||||
config.set('fqdn', 'example.com');
|
||||
config.set('isCustomDomain', true);
|
||||
|
||||
expect(config.isCustomDomain()).to.equal(true);
|
||||
expect(config.fqdn()).to.equal('example.com');
|
||||
expect(config.adminOrigin()).to.equal('https://' + constants.ADMIN_LOCATION + '.example.com');
|
||||
expect(config.appFqdn('app')).to.equal('app.example.com');
|
||||
expect(config.zoneName()).to.equal('example.com');
|
||||
});
|
||||
|
||||
it('uses hyphen locations with non-custom domain', function () {
|
||||
config.set('fqdn', 'test.example.com');
|
||||
config.set('isCustomDomain', false);
|
||||
|
||||
expect(config.isCustomDomain()).to.equal(false);
|
||||
expect(config.fqdn()).to.equal('test.example.com');
|
||||
expect(config.adminOrigin()).to.equal('https://' + constants.ADMIN_LOCATION + '-test.example.com');
|
||||
expect(config.appFqdn('app')).to.equal('app-test.example.com');
|
||||
expect(config.zoneName()).to.equal('example.com');
|
||||
});
|
||||
|
||||
it('can set arbitrary values', function (done) {
|
||||
config.set('random', 'value');
|
||||
expect(config.get('random')).to.equal('value');
|
||||
|
||||
config.set('this.is.madness', 42);
|
||||
expect(config.get('this.is.madness')).to.equal(42);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
933
src/test/database-test.js
Normal file
933
src/test/database-test.js
Normal file
@@ -0,0 +1,933 @@
|
||||
/* jslint node:true */
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
var appdb = require('../appdb.js'),
|
||||
authcodedb = require('../authcodedb.js'),
|
||||
clientdb = require('../clientdb.js'),
|
||||
hat = require('hat'),
|
||||
database = require('../database'),
|
||||
DatabaseError = require('../databaseerror.js'),
|
||||
expect = require('expect.js'),
|
||||
async = require('async'),
|
||||
settingsdb = require('../settingsdb.js'),
|
||||
tokendb = require('../tokendb.js'),
|
||||
userdb = require('../userdb.js');
|
||||
|
||||
describe('database', function () {
|
||||
before(function (done) {
|
||||
async.series([
|
||||
database.initialize,
|
||||
database._clear
|
||||
], done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
database._clear(done);
|
||||
});
|
||||
|
||||
describe('userdb', function () {
|
||||
var USER_0 = {
|
||||
id: 'uuid213',
|
||||
username: 'uuid213',
|
||||
password: 'secret',
|
||||
email: 'safe@me.com',
|
||||
admin: false,
|
||||
salt: 'morton',
|
||||
createdAt: 'sometime back',
|
||||
modifiedAt: 'now',
|
||||
resetToken: hat(256)
|
||||
};
|
||||
|
||||
var ADMIN_0 = {
|
||||
id: 'uuid456',
|
||||
username: 'uuid456',
|
||||
password: 'secret',
|
||||
email: 'safe2@me.com',
|
||||
admin: true,
|
||||
salt: 'tata',
|
||||
createdAt: 'sometime back',
|
||||
modifiedAt: 'now',
|
||||
resetToken: ''
|
||||
};
|
||||
|
||||
it('can add user', function (done) {
|
||||
userdb.add(USER_0.id, USER_0, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can add admin user', function (done) {
|
||||
userdb.add(ADMIN_0.id, ADMIN_0, function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot add same user again', function (done) {
|
||||
userdb.add(USER_0.id, USER_0, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
expect(error.reason).to.be(DatabaseError.ALREADY_EXISTS);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can get by user id', function (done) {
|
||||
userdb.get(USER_0.id, function (error, user) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(user).to.eql(USER_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can get by user name', function (done) {
|
||||
userdb.getByUsername(USER_0.username, function (error, user) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(user).to.eql(USER_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can get by email', function (done) {
|
||||
userdb.getByEmail(USER_0.email, function (error, user) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(user).to.eql(USER_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can get by resetToken fails for empty resetToken', function (done) {
|
||||
userdb.getByResetToken('', function (error, user) {
|
||||
expect(error).to.be.ok();
|
||||
expect(error.reason).to.be(DatabaseError.INTERNAL_ERROR);
|
||||
expect(user).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can get by resetToken', function (done) {
|
||||
userdb.getByResetToken(USER_0.resetToken, function (error, user) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(user).to.eql(USER_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can get all', function (done) {
|
||||
userdb.getAll(function (error, all) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(all.length).to.equal(2);
|
||||
expect(all[0]).to.eql(USER_0);
|
||||
expect(all[1]).to.eql(ADMIN_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can get all admins', function (done) {
|
||||
userdb.getAllAdmins(function (error, all) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(all.length).to.equal(1);
|
||||
expect(all[0]).to.eql(ADMIN_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('counts the users', function (done) {
|
||||
userdb.count(function (error, count) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(count).to.equal(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('counts the admin users', function (done) {
|
||||
userdb.adminCount(function (error, count) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(count).to.equal(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can update the user', function (done) {
|
||||
userdb.update(USER_0.id, { email: 'some@thing.com' }, function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
userdb.get(USER_0.id, function (error, user) {
|
||||
expect(user.email).to.equal('some@thing.com');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot update with null field', function (done) {
|
||||
userdb.update(USER_0.id, { email: null }, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot del non-existing user', function (done) {
|
||||
userdb.del(USER_0.id + USER_0.id, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can del existing user', function (done) {
|
||||
userdb.del(USER_0.id, function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('did remove the user', function (done) {
|
||||
userdb.count(function (error, count) {
|
||||
expect(count).to.equal(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can clear table', function (done) {
|
||||
userdb._clear(function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
userdb.count(function (error, count) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(count).to.equal(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('authcode', function () {
|
||||
var AUTHCODE_0 = {
|
||||
authCode: 'authcode-0',
|
||||
clientId: 'clientid-0',
|
||||
userId: 'userid-0',
|
||||
expiresAt: Date.now() + 5000
|
||||
};
|
||||
var AUTHCODE_1 = {
|
||||
authCode: 'authcode-1',
|
||||
clientId: 'clientid-1',
|
||||
userId: 'userid-1',
|
||||
expiresAt: Date.now() + 5000
|
||||
};
|
||||
var AUTHCODE_2 = {
|
||||
authCode: 'authcode-2',
|
||||
clientId: 'clientid-2',
|
||||
userId: 'userid-2',
|
||||
expiresAt: Date.now()
|
||||
};
|
||||
|
||||
it('add fails due to missing arguments', function () {
|
||||
expect(function () { authcodedb.add(AUTHCODE_0.authCode, AUTHCODE_0.clientId, AUTHCODE_0.userId); }).to.throwError();
|
||||
expect(function () { authcodedb.add(AUTHCODE_0.authCode, AUTHCODE_0.clientId, function () {}); }).to.throwError();
|
||||
expect(function () { authcodedb.add(AUTHCODE_0.authCode, function () {}); }).to.throwError();
|
||||
});
|
||||
|
||||
it('add succeeds', function (done) {
|
||||
authcodedb.add(AUTHCODE_0.authCode, AUTHCODE_0.clientId, AUTHCODE_0.userId, AUTHCODE_0.expiresAt, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('add of same authcode fails', function (done) {
|
||||
authcodedb.add(AUTHCODE_0.authCode, AUTHCODE_0.clientId, AUTHCODE_0.userId, AUTHCODE_0.expiresAt, function (error) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.ALREADY_EXISTS);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('get succeeds', function (done) {
|
||||
authcodedb.get(AUTHCODE_0.authCode, function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.be.an('object');
|
||||
expect(result).to.be.eql(AUTHCODE_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('get of nonexisting code fails', function (done) {
|
||||
authcodedb.get(AUTHCODE_1.authCode, function (error, result) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
|
||||
expect(result).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('get of expired code fails', function (done) {
|
||||
authcodedb.add(AUTHCODE_2.authCode, AUTHCODE_2.clientId, AUTHCODE_2.userId, AUTHCODE_2.expiresAt, function (error) {
|
||||
expect(error).to.be(null);
|
||||
|
||||
authcodedb.get(AUTHCODE_2.authCode, function (error, result) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
|
||||
expect(result).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('delExpired succeeds', function (done) {
|
||||
authcodedb.delExpired(function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result).to.eql(1);
|
||||
|
||||
authcodedb.get(AUTHCODE_2.authCode, function (error, result) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
|
||||
expect(result).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('delete succeeds', function (done) {
|
||||
authcodedb.del(AUTHCODE_0.authCode, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot delete previously delete record', function (done) {
|
||||
authcodedb.del(AUTHCODE_0.authCode, function (error) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('token', function () {
|
||||
var TOKEN_0 = {
|
||||
accessToken: tokendb.generateToken(),
|
||||
identifier: tokendb.PREFIX_USER + '0',
|
||||
clientId: 'clientid-0',
|
||||
expires: Date.now() + 60 * 60000,
|
||||
scope: '*'
|
||||
};
|
||||
var TOKEN_1 = {
|
||||
accessToken: tokendb.generateToken(),
|
||||
identifier: tokendb.PREFIX_USER + '1',
|
||||
clientId: 'clientid-1',
|
||||
expires: Number.MAX_SAFE_INTEGER,
|
||||
scope: '*'
|
||||
};
|
||||
var TOKEN_2 = {
|
||||
accessToken: tokendb.generateToken(),
|
||||
identifier: tokendb.PREFIX_USER + '2',
|
||||
clientId: 'clientid-2',
|
||||
expires: Date.now(),
|
||||
scope: '*'
|
||||
};
|
||||
|
||||
it('add fails due to missing arguments', function () {
|
||||
expect(function () { tokendb.add(TOKEN_0.accessToken, TOKEN_0.identifier, TOKEN_0.clientId, TOKEN_0.scope); }).to.throwError();
|
||||
expect(function () { tokendb.add(TOKEN_0.accessToken, TOKEN_0.identifier, TOKEN_0.clientId, function () {}); }).to.throwError();
|
||||
expect(function () { tokendb.add(TOKEN_0.accessToken, TOKEN_0.identifier, function () {}); }).to.throwError();
|
||||
expect(function () { tokendb.add(TOKEN_0.accessToken, function () {}); }).to.throwError();
|
||||
});
|
||||
|
||||
it('add succeeds', function (done) {
|
||||
tokendb.add(TOKEN_0.accessToken, TOKEN_0.identifier, TOKEN_0.clientId, TOKEN_0.expires, TOKEN_0.scope, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('add of same token fails', function (done) {
|
||||
tokendb.add(TOKEN_0.accessToken, TOKEN_0.identifier, TOKEN_0.clientId, TOKEN_0.expires, TOKEN_0.scope, function (error) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.ALREADY_EXISTS);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('get succeeds', function (done) {
|
||||
tokendb.get(TOKEN_0.accessToken, function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.be.an('object');
|
||||
expect(result).to.be.eql(TOKEN_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('get of nonexisting token fails', function (done) {
|
||||
tokendb.get(TOKEN_1.accessToken, function (error, result) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
|
||||
expect(result).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getByIdentifier succeeds', function (done) {
|
||||
tokendb.getByIdentifier(TOKEN_0.identifier, function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.equal(1);
|
||||
expect(result[0]).to.be.an('object');
|
||||
expect(result[0]).to.be.eql(TOKEN_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('delete succeeds', function (done) {
|
||||
tokendb.del(TOKEN_0.accessToken, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getByIdentifier succeeds after token deletion', function (done) {
|
||||
tokendb.getByIdentifier(TOKEN_0.identifier, function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.equal(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('delByIdentifier succeeds', function (done) {
|
||||
tokendb.add(TOKEN_1.accessToken, TOKEN_1.identifier, TOKEN_1.clientId, TOKEN_1.expires, TOKEN_1.scope, function (error) {
|
||||
expect(error).to.be(null);
|
||||
|
||||
tokendb.delByIdentifier(TOKEN_1.identifier, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot delete previously delete record', function (done) {
|
||||
tokendb.del(TOKEN_0.accessToken, function (error) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getByIdentifierAndClientId succeeds', function (done) {
|
||||
tokendb.add(TOKEN_0.accessToken, TOKEN_0.identifier, TOKEN_0.clientId, TOKEN_0.expires, TOKEN_0.scope, function (error) {
|
||||
expect(error).to.be(null);
|
||||
|
||||
tokendb.getByIdentifierAndClientId(TOKEN_0.identifier, TOKEN_0.clientId, function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.equal(1);
|
||||
expect(result[0]).to.eql(TOKEN_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('delExpired succeeds', function (done) {
|
||||
tokendb.add(TOKEN_2.accessToken, TOKEN_2.identifier, TOKEN_2.clientId, TOKEN_2.expires, TOKEN_2.scope, function (error) {
|
||||
expect(error).to.be(null);
|
||||
|
||||
tokendb.delExpired(function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result).to.eql(1);
|
||||
|
||||
tokendb.get(TOKEN_2.accessToken, function (error, result) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
|
||||
expect(result).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('delByIdentifierAndClientId succeeds', function (done) {
|
||||
tokendb.delByIdentifierAndClientId(TOKEN_0.identifier, TOKEN_0.clientId, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('get of previously deleted token fails', function (done) {
|
||||
tokendb.get(TOKEN_0.accessToken, function (error, result) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
|
||||
expect(result).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('app', function () {
|
||||
var APP_0 = {
|
||||
id: 'appid-0',
|
||||
appStoreId: 'appStoreId-0',
|
||||
dnsRecordId: null,
|
||||
installationState: appdb.ISTATE_PENDING_INSTALL,
|
||||
installationProgress: null,
|
||||
runState: null,
|
||||
location: 'some-location-0',
|
||||
manifest: { version: '0.1', dockerImage: 'docker/app0', healthCheckPath: '/', httpPort: 80, title: 'app0' },
|
||||
httpPort: null,
|
||||
containerId: null,
|
||||
portBindings: { port: 5678 },
|
||||
health: null,
|
||||
accessRestriction: '',
|
||||
lastBackupId: null,
|
||||
lastBackupConfig: null,
|
||||
oldConfig: null
|
||||
};
|
||||
var APP_1 = {
|
||||
id: 'appid-1',
|
||||
appStoreId: 'appStoreId-1',
|
||||
dnsRecordId: null,
|
||||
installationState: appdb.ISTATE_PENDING_INSTALL, // app health tests rely on this initial state
|
||||
installationProgress: null,
|
||||
runState: null,
|
||||
location: 'some-location-1',
|
||||
manifest: { version: '0.2', dockerImage: 'docker/app1', healthCheckPath: '/', httpPort: 80, title: 'app1' },
|
||||
httpPort: null,
|
||||
containerId: null,
|
||||
portBindings: { },
|
||||
health: null,
|
||||
accessRestriction: 'roleAdmin',
|
||||
lastBackupId: null,
|
||||
lastBackupConfig: null,
|
||||
oldConfig: null
|
||||
};
|
||||
|
||||
it('add fails due to missing arguments', function () {
|
||||
expect(function () { appdb.add(APP_0.id, APP_0.manifest, APP_0.installationState, function () {}); }).to.throwError();
|
||||
expect(function () { appdb.add(APP_0.id, function () {}); }).to.throwError();
|
||||
});
|
||||
|
||||
it('exists returns false', function (done) {
|
||||
appdb.exists(APP_0.id, function (error, exists) {
|
||||
expect(error).to.be(null);
|
||||
expect(exists).to.be(false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('add succeeds', function (done) {
|
||||
appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, APP_0.portBindings, APP_0.accessRestriction, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('exists succeeds', function (done) {
|
||||
appdb.exists(APP_0.id, function (error, exists) {
|
||||
expect(error).to.be(null);
|
||||
expect(exists).to.be(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getPortBindings succeeds', function (done) {
|
||||
appdb.getPortBindings(APP_0.id, function (error, bindings) {
|
||||
expect(error).to.be(null);
|
||||
expect(bindings).to.be.an(Object);
|
||||
expect(bindings).to.be.eql({ port: '5678' });
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('add of same app fails', function (done) {
|
||||
appdb.add(APP_0.id, APP_0.appStoreId, APP_0.manifest, APP_0.location, [ ], APP_0.accessRestriction, function (error) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.ALREADY_EXISTS);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('get succeeds', function (done) {
|
||||
appdb.get(APP_0.id, function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.be.an('object');
|
||||
expect(result).to.be.eql(APP_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('get of nonexisting code fails', function (done) {
|
||||
appdb.get(APP_1.id, function (error, result) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
|
||||
expect(result).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update succeeds', function (done) {
|
||||
APP_0.installationState = 'some-other-status';
|
||||
APP_0.location = 'some-other-location';
|
||||
APP_0.manifest.version = '0.2';
|
||||
APP_0.accessRestriction = true;
|
||||
APP_0.httpPort = 1337;
|
||||
|
||||
appdb.update(APP_0.id, { installationState: APP_0.installationState, location: APP_0.location, manifest: APP_0.manifest, accessRestriction: APP_0.accessRestriction, httpPort: APP_0.httpPort }, function (error) {
|
||||
expect(error).to.be(null);
|
||||
|
||||
appdb.get(APP_0.id, function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.be.an('object');
|
||||
expect(result).to.be.eql(APP_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('getByHttpPort succeeds', function (done) {
|
||||
appdb.getByHttpPort(APP_0.httpPort, function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.be.an('object');
|
||||
expect(result).to.be.eql(APP_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update of nonexisting app fails', function (done) {
|
||||
appdb.update(APP_1.id, { installationState: APP_1.installationState, location: APP_1.location }, function (error) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('add second app succeeds', function (done) {
|
||||
appdb.add(APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, [ ], APP_1.accessRestriction, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getAll succeeds', function (done) {
|
||||
appdb.getAll(function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.be(2);
|
||||
expect(result[0]).to.be.eql(APP_0);
|
||||
expect(result[1]).to.be.eql(APP_1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getAppStoreIds succeeds', function (done) {
|
||||
appdb.getAppStoreIds(function (error, results) {
|
||||
expect(error).to.be(null);
|
||||
expect(results).to.be.an(Array);
|
||||
expect(results.length).to.be(2);
|
||||
expect(results[0].appStoreId).to.equal(APP_0.appStoreId);
|
||||
expect(results[1].appStoreId).to.equal(APP_1.appStoreId);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('delete succeeds', function (done) {
|
||||
appdb.del(APP_0.id, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getPortBindings should be empty', function (done) {
|
||||
appdb.getPortBindings(APP_0.id, function (error, bindings) {
|
||||
expect(error).to.be(null);
|
||||
expect(bindings).to.be.an(Object);
|
||||
expect(bindings).to.be.eql({ });
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot delete previously delete record', function (done) {
|
||||
appdb.del(APP_0.id, function (error) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot set app as healthy because app is not installed', function (done) {
|
||||
appdb.setHealth(APP_1.id, appdb.HEALTH_HEALTHY, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot set app as healthy because app has pending run state', function (done) {
|
||||
appdb.update(APP_1.id, { runState: appdb.RSTATE_PENDING_STOP, installationState: appdb.ISTATE_INSTALLED }, function (error) {
|
||||
expect(error).to.be(null);
|
||||
|
||||
appdb.setHealth(APP_1.id, appdb.HEALTH_HEALTHY, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot set app as healthy because app has null run state', function (done) {
|
||||
appdb.update(APP_1.id, { runState: null, installationState: appdb.ISTATE_INSTALLED }, function (error) {
|
||||
expect(error).to.be(null);
|
||||
|
||||
appdb.setHealth(APP_1.id, appdb.HEALTH_HEALTHY, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('can set app as healthy when installed and no pending runState', function (done) {
|
||||
appdb.update(APP_1.id, { runState: appdb.RSTATE_RUNNING, installationState: appdb.ISTATE_INSTALLED }, function (error) {
|
||||
expect(error).to.be(null);
|
||||
|
||||
appdb.setHealth(APP_1.id, appdb.HEALTH_HEALTHY, function (error) {
|
||||
expect(error).to.be(null);
|
||||
appdb.get(APP_1.id, function (error, app) {
|
||||
expect(error).to.be(null);
|
||||
expect(app.health).to.be(appdb.HEALTH_HEALTHY);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot set health of unknown app', function (done) {
|
||||
appdb.setHealth('randomId', appdb.HEALTH_HEALTHY, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('return empty addon config array for invalid app', function (done) {
|
||||
appdb.getAddonConfigByAppId('randomid', function (error, results) {
|
||||
expect(error).to.be(null);
|
||||
expect(results).to.eql([ ]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('setAddonConfig succeeds', function (done) {
|
||||
appdb.setAddonConfig(APP_1.id, 'addonid1', [ 'ENV1=env', 'ENV2=env' ], function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('setAddonConfig succeeds', function (done) {
|
||||
appdb.setAddonConfig(APP_1.id, 'addonid2', [ 'ENV3=env' ], function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getAddonConfig succeeds', function (done) {
|
||||
appdb.getAddonConfig(APP_1.id, 'addonid1', function (error, results) {
|
||||
expect(error).to.be(null);
|
||||
expect(results).to.eql([ 'ENV1=env', 'ENV2=env' ]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getAddonConfigByAppId succeeds', function (done) {
|
||||
appdb.getAddonConfigByAppId(APP_1.id, function (error, results) {
|
||||
expect(error).to.be(null);
|
||||
expect(results).to.eql([ 'ENV1=env', 'ENV2=env', 'ENV3=env' ]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('unsetAddonConfig succeeds', function (done) {
|
||||
appdb.unsetAddonConfig(APP_1.id, 'addonid1', function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('unsetAddonConfig did remove configs', function (done) {
|
||||
appdb.getAddonConfigByAppId(APP_1.id, function (error, results) {
|
||||
expect(error).to.be(null);
|
||||
expect(results).to.eql([ 'ENV3=env' ]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('unsetAddonConfigByAppId succeeds', function (done) {
|
||||
appdb.unsetAddonConfigByAppId(APP_1.id, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('unsetAddonConfigByAppId did remove configs', function (done) {
|
||||
appdb.getAddonConfigByAppId(APP_1.id, function (error, results) {
|
||||
expect(error).to.be(null);
|
||||
expect(results).to.eql([ ]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('client', function () {
|
||||
var CLIENT_0 = {
|
||||
id: 'cid-0',
|
||||
appId: 'someappid_0',
|
||||
clientSecret: 'secret-0',
|
||||
redirectURI: 'http://foo.bar',
|
||||
scope: '*'
|
||||
|
||||
};
|
||||
var CLIENT_1 = {
|
||||
id: 'cid-1',
|
||||
appId: 'someappid_1',
|
||||
clientSecret: 'secret-',
|
||||
redirectURI: 'http://foo.bar',
|
||||
scope: '*'
|
||||
};
|
||||
var CLIENT_2 = {
|
||||
id: 'cid-2',
|
||||
appId: 'someappid_2',
|
||||
clientSecret: 'secret-2',
|
||||
redirectURI: 'http://foo.bar.baz',
|
||||
scope: 'profile,roleUser'
|
||||
};
|
||||
|
||||
it('add succeeds', function (done) {
|
||||
clientdb.add(CLIENT_0.id, CLIENT_0.appId, CLIENT_0.clientSecret, CLIENT_0.redirectURI, CLIENT_0.scope, function (error) {
|
||||
expect(error).to.be(null);
|
||||
|
||||
clientdb.add(CLIENT_1.id, CLIENT_1.appId, CLIENT_1.clientSecret, CLIENT_1.redirectURI, CLIENT_1.scope, function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('add same client id fails', function (done) {
|
||||
clientdb.add(CLIENT_0.id, CLIENT_0.appId, CLIENT_0.clientSecret, CLIENT_0.redirectURI, CLIENT_0.scope, function (error) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.equal(DatabaseError.ALREADY_EXISTS);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('get succeeds', function (done) {
|
||||
clientdb.get(CLIENT_0.id, function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.eql(CLIENT_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getByAppId succeeds', function (done) {
|
||||
clientdb.getByAppId(CLIENT_0.appId, function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.eql(CLIENT_0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getByAppId fails for unknown client id', function (done) {
|
||||
clientdb.getByAppId(CLIENT_0.appId + CLIENT_0.appId, function (error, result) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.equal(DatabaseError.NOT_FOUND);
|
||||
expect(result).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getAll succeeds', function (done) {
|
||||
clientdb.getAll(function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.equal(3); // one of them is webadmin
|
||||
expect(result[0]).to.eql(CLIENT_0);
|
||||
expect(result[1]).to.eql(CLIENT_1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update client fails due to unknown client id', function (done) {
|
||||
clientdb.update(CLIENT_2.id, CLIENT_2.appId, CLIENT_2.clientSecret, CLIENT_2.redirectURI, CLIENT_2.scope, function (error) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.equal(DatabaseError.NOT_FOUND);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('update client succeeds', function (done) {
|
||||
clientdb.update(CLIENT_1.id, CLIENT_2.appId, CLIENT_2.clientSecret, CLIENT_2.redirectURI, CLIENT_2.scope, function (error) {
|
||||
expect(error).to.be(null);
|
||||
|
||||
clientdb.get(CLIENT_1.id, function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result.appId).to.eql(CLIENT_2.appId);
|
||||
expect(result.clientSecret).to.eql(CLIENT_2.clientSecret);
|
||||
expect(result.redirectURI).to.eql(CLIENT_2.redirectURI);
|
||||
expect(result.scope).to.eql(CLIENT_2.scope);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('delByAppId succeeds', function (done) {
|
||||
clientdb.delByAppId(CLIENT_0.appId, function (error) {
|
||||
expect(error).to.be(null);
|
||||
|
||||
clientdb.getByAppId(CLIENT_0.appId, function (error, result) {
|
||||
expect(error).to.be.a(DatabaseError);
|
||||
expect(error.reason).to.equal(DatabaseError.NOT_FOUND);
|
||||
expect(result).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('settings', function () {
|
||||
it('can set value', function (done) {
|
||||
settingsdb.set('somekey', 'somevalue', function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('can get the set value', function (done) {
|
||||
settingsdb.get('somekey', function (error, value) {
|
||||
expect(error).to.be(null);
|
||||
expect(value).to.be('somevalue');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('can get all values', function (done) {
|
||||
settingsdb.getAll(function (error, result) {
|
||||
expect(error).to.be(null);
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result[0].name).to.be('somekey');
|
||||
expect(result[0].value).to.be('somevalue');
|
||||
expect(result.length).to.be(1); // the value set above
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('can update a value', function (done) {
|
||||
settingsdb.set('somekey', 'someothervalue', function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('can get updated value', function (done) {
|
||||
settingsdb.get('somekey', function (error, value) {
|
||||
expect(error).to.be(null);
|
||||
expect(value).to.be('someothervalue');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
273
src/test/server-test.js
Normal file
273
src/test/server-test.js
Normal file
@@ -0,0 +1,273 @@
|
||||
/* jslint node:true */
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
var progress = require('../progress.js'),
|
||||
config = require('../config.js'),
|
||||
database = require('../database.js'),
|
||||
expect = require('expect.js'),
|
||||
nock = require('nock'),
|
||||
request = require('superagent'),
|
||||
server = require('../server.js');
|
||||
|
||||
var SERVER_URL = 'http://localhost:' + config.get('port');
|
||||
|
||||
function cleanup(done) {
|
||||
done();
|
||||
}
|
||||
|
||||
describe('Server', function () {
|
||||
this.timeout(5000);
|
||||
|
||||
before(function () {
|
||||
config.set('version', '0.5.0');
|
||||
});
|
||||
|
||||
after(cleanup);
|
||||
|
||||
describe('startup', function () {
|
||||
it('start fails due to wrong arguments', function (done) {
|
||||
expect(function () { server.start(); }).to.throwException();
|
||||
expect(function () { server.start('foobar', function () {}); }).to.throwException();
|
||||
expect(function () { server.start(1337, function () {}); }).to.throwException();
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('succeeds', function (done) {
|
||||
server.start(function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('is reachable', function (done) {
|
||||
request.get(SERVER_URL + '/api/v1/cloudron/status', function (err, res) {
|
||||
expect(res.statusCode).to.equal(200);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail because already running', function (done) {
|
||||
expect(server.start).to.throwException(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
server.stop(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('runtime', function () {
|
||||
before(function (done) {
|
||||
server.start(done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
database._clear(function (error) {
|
||||
expect(!error).to.be.ok();
|
||||
server.stop(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('random bad requests', function (done) {
|
||||
request.get(SERVER_URL + '/random', function (err, res) {
|
||||
expect(err).to.not.be.ok();
|
||||
expect(res.statusCode).to.equal(404);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it('version', function (done) {
|
||||
request.get(SERVER_URL + '/api/v1/cloudron/status', function (err, res) {
|
||||
expect(err).to.not.be.ok();
|
||||
expect(res.statusCode).to.equal(200);
|
||||
expect(res.body.version).to.equal('0.5.0');
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it('status route is GET', function (done) {
|
||||
request.post(SERVER_URL + '/api/v1/cloudron/status')
|
||||
.end(function (err, res) {
|
||||
expect(res.statusCode).to.equal(404);
|
||||
|
||||
request.get(SERVER_URL + '/api/v1/cloudron/status')
|
||||
.end(function (err, res) {
|
||||
expect(res.statusCode).to.equal(200);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('config', function () {
|
||||
before(function (done) {
|
||||
server.start(done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
server.stop(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('config fails due missing token', function (done) {
|
||||
request.get(SERVER_URL + '/api/v1/cloudron/config', function (err, res) {
|
||||
expect(err).to.not.be.ok();
|
||||
expect(res.statusCode).to.equal(401);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it('config fails due wrong token', function (done) {
|
||||
request.get(SERVER_URL + '/api/v1/cloudron/config').query({ access_token: 'somewrongtoken' }).end(function (err, res) {
|
||||
expect(err).to.not.be.ok();
|
||||
expect(res.statusCode).to.equal(401);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('progress', function () {
|
||||
before(function (done) {
|
||||
server.start(done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
server.stop(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('succeeds with no progress', function (done) {
|
||||
request.get(SERVER_URL + '/api/v1/cloudron/progress', function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result.statusCode).to.equal(200);
|
||||
expect(result.body.update).to.be(null);
|
||||
expect(result.body.backup).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('succeeds with update progress', function (done) {
|
||||
progress.set(progress.UPDATE, 13, 'This is some status string');
|
||||
|
||||
request.get(SERVER_URL + '/api/v1/cloudron/progress', function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result.statusCode).to.equal(200);
|
||||
expect(result.body.update).to.be.an('object');
|
||||
expect(result.body.update.percent).to.be.a('number');
|
||||
expect(result.body.update.percent).to.equal(13);
|
||||
expect(result.body.update.message).to.be.a('string');
|
||||
expect(result.body.update.message).to.equal('This is some status string');
|
||||
|
||||
expect(result.body.backup).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('succeeds with no progress after clearing the update', function (done) {
|
||||
progress.clear(progress.UPDATE);
|
||||
|
||||
request.get(SERVER_URL + '/api/v1/cloudron/progress', function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result.statusCode).to.equal(200);
|
||||
expect(result.body.update).to.be(null);
|
||||
expect(result.body.backup).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('shutdown', function () {
|
||||
before(function (done) {
|
||||
server.start(done);
|
||||
});
|
||||
|
||||
it('fails due to wrong arguments', function (done) {
|
||||
expect(function () { server.stop(); }).to.throwException();
|
||||
expect(function () { server.stop('foobar'); }).to.throwException();
|
||||
expect(function () { server.stop(1337); }).to.throwException();
|
||||
expect(function () { server.stop({}); }).to.throwException();
|
||||
expect(function () { server.stop({ httpServer: {} }); }).to.throwException();
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('succeeds', function (done) {
|
||||
server.stop(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('is not reachable anymore', function (done) {
|
||||
request.get(SERVER_URL + '/api/v1/cloudron/status', function (error, result) {
|
||||
expect(error).to.not.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('cors', function () {
|
||||
before(function (done) {
|
||||
server.start(function (error) {
|
||||
done(error);
|
||||
});
|
||||
});
|
||||
|
||||
it('responds to OPTIONS', function (done) {
|
||||
request('OPTIONS', SERVER_URL + '/api/v1/cloudron/status')
|
||||
.set('Access-Control-Request-Method', 'GET')
|
||||
.set('Access-Control-Request-Headers', 'accept, origin, x-requested-with')
|
||||
.set('Origin', 'http://localhost')
|
||||
.end(function (res) {
|
||||
expect(res.headers['access-control-allow-methods']).to.be('GET, PUT, DELETE, POST, OPTIONS');
|
||||
expect(res.headers['access-control-allow-credentials']).to.be('true');
|
||||
expect(res.headers['access-control-allow-headers']).to.be('accept, origin, x-requested-with'); // mirrored from request
|
||||
expect(res.headers['access-control-allow-origin']).to.be('http://localhost'); // mirrors from request
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
server.stop(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('heartbeat', function () {
|
||||
var successfulHeartbeatGet;
|
||||
|
||||
before(function (done) {
|
||||
server.start(done);
|
||||
|
||||
var scope = nock(config.apiServerOrigin());
|
||||
successfulHeartbeatGet = scope.get('/api/v1/boxes/' + config.fqdn() + '/heartbeat');
|
||||
successfulHeartbeatGet.reply(200);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
server.stop(done);
|
||||
nock.cleanAll();
|
||||
});
|
||||
|
||||
it('sends heartbeat', function (done) {
|
||||
setTimeout(function () {
|
||||
expect(successfulHeartbeatGet.counter).to.equal(1);
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
66
src/test/settings-test.js
Normal file
66
src/test/settings-test.js
Normal file
@@ -0,0 +1,66 @@
|
||||
/* jslint node:true */
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
var database = require('../database.js'),
|
||||
expect = require('expect.js'),
|
||||
settings = require('../settings.js');
|
||||
|
||||
function setup(done) {
|
||||
// ensure data/config/mount paths
|
||||
database.initialize(function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
function cleanup(done) {
|
||||
database._clear(done);
|
||||
}
|
||||
|
||||
describe('Settings', function () {
|
||||
before(setup);
|
||||
after(cleanup);
|
||||
|
||||
it('can get default timezone', function (done) {
|
||||
settings.getTimeZone(function (error, tz) {
|
||||
expect(error).to.be(null);
|
||||
expect(tz.length).to.not.be(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('can get default autoupdate_pattern', function (done) {
|
||||
settings.getAutoupdatePattern(function (error, pattern) {
|
||||
expect(error).to.be(null);
|
||||
expect(pattern).to.be('00 00 1,3,5,23 * * *');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it ('can get default cloudron name', function (done) {
|
||||
settings.getCloudronName(function (error, name) {
|
||||
expect(error).to.be(null);
|
||||
expect(name).to.be('Cloudron');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('can get default cloudron avatar', function (done) {
|
||||
settings.getCloudronAvatar(function (error, gravatar) {
|
||||
expect(error).to.be(null);
|
||||
expect(gravatar).to.be.a(Buffer);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('can get all values', function (done) {
|
||||
settings.getAll(function (error, allSettings) {
|
||||
expect(error).to.be(null);
|
||||
expect(allSettings[settings.TIME_ZONE_KEY]).to.be.a('string');
|
||||
expect(allSettings[settings.AUTOUPDATE_PATTERN_KEY]).to.be.a('string');
|
||||
expect(allSettings[settings.CLOUDRON_NAME_KEY]).to.be.a('string');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
20
src/test/setupTest
Executable file
20
src/test/setupTest
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
readonly ADMIN_LOCATION=admin
|
||||
readonly source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. && pwd)"
|
||||
|
||||
! "${source_dir}/src/test/checkInstall" && exit 1
|
||||
|
||||
# create dir structure
|
||||
rm -rf $HOME/.cloudron_test
|
||||
mkdir -p $HOME/.cloudron_test
|
||||
cd $HOME/.cloudron_test
|
||||
mkdir -p data/appdata data/box/appicons data/mail data/nginx/cert data/nginx/applications data/collectd/collectd.conf.d data/addons configs
|
||||
|
||||
webadmin_scopes="root,profile,users,apps,settings,roleAdmin"
|
||||
webadmin_origin="https://${ADMIN_LOCATION}-localhost"
|
||||
mysql --user=root --password="" \
|
||||
-e "REPLACE INTO clients (id, appId, clientSecret, redirectURI, scope) VALUES (\"cid-webadmin\", \"webadmin\", \"secret-webadmin\", \"${webadmin_origin}\", \"${webadmin_scopes}\")" boxtest
|
||||
|
||||
51
src/test/shell-test.js
Normal file
51
src/test/shell-test.js
Normal file
@@ -0,0 +1,51 @@
|
||||
/* jslint node:true */
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global after:false */
|
||||
/* global before:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
var expect = require('expect.js'),
|
||||
path = require('path'),
|
||||
shell = require('../shell.js');
|
||||
|
||||
describe('shell', function () {
|
||||
it('can run valid program', function (done) {
|
||||
var cp = shell.exec('test', 'ls', [ '-l' ], function (error) {
|
||||
expect(cp).to.be.ok();
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on invalid program', function (done) {
|
||||
var cp = shell.exec('test', 'randomprogram', [ ], function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails on failing program', function (done) {
|
||||
var cp = shell.exec('test', '/usr/bin/false', [ ], function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot sudo invalid program', function (done) {
|
||||
var cp = shell.sudo('test', [ 'randomprogram' ], function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('can sudo valid program', function (done) {
|
||||
var RELOAD_NGINX_CMD = path.join(__dirname, '../src/scripts/reloadnginx.sh');
|
||||
var cp = shell.sudo('test', [ RELOAD_NGINX_CMD ], function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
401
src/test/user-test.js
Normal file
401
src/test/user-test.js
Normal file
@@ -0,0 +1,401 @@
|
||||
/* jslint node:true */
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
var database = require('../database.js'),
|
||||
expect = require('expect.js'),
|
||||
user = require('../user.js'),
|
||||
userdb = require('../userdb.js'),
|
||||
UserError = user.UserError;
|
||||
|
||||
var USERNAME = 'nobody';
|
||||
var USERNAME_NEW = 'nobodynew';
|
||||
var EMAIL = 'nobody@no.body';
|
||||
var EMAIL_NEW = 'nobodynew@no.body';
|
||||
var PASSWORD = 'foobar';
|
||||
var NEW_PASSWORD = 'somenewpassword';
|
||||
var IS_ADMIN = true;
|
||||
|
||||
function cleanupUsers(done) {
|
||||
userdb._clear(function () {
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
function createUser(done) {
|
||||
user.create(USERNAME, PASSWORD, EMAIL, IS_ADMIN, null /* invitor */, function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result).to.be.ok();
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
function setup(done) {
|
||||
// ensure data/config/mount paths
|
||||
database.initialize(function (error) {
|
||||
expect(error).to.be(null);
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
function cleanup(done) {
|
||||
database._clear(done);
|
||||
}
|
||||
|
||||
describe('User', function () {
|
||||
before(setup);
|
||||
after(cleanup);
|
||||
|
||||
describe('create', function() {
|
||||
before(cleanupUsers);
|
||||
after(cleanupUsers);
|
||||
|
||||
it('succeeds', function (done) {
|
||||
user.create(USERNAME, PASSWORD, EMAIL, IS_ADMIN, null /* invitor */, function (error, result) {
|
||||
expect(error).not.to.be.ok();
|
||||
expect(result).to.be.ok();
|
||||
expect(result.username).to.equal(USERNAME);
|
||||
expect(result.email).to.equal(EMAIL);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails because of invalid BAD_FIELD', function (done) {
|
||||
expect(function () {
|
||||
user.create(EMAIL, {}, function () {});
|
||||
}).to.throwException();
|
||||
expect(function () {
|
||||
user.create(12345, PASSWORD, EMAIL, function () {});
|
||||
}).to.throwException();
|
||||
expect(function () {
|
||||
user.create(USERNAME, PASSWORD, EMAIL, {});
|
||||
}).to.throwException();
|
||||
expect(function () {
|
||||
user.create(USERNAME, PASSWORD, EMAIL, {}, function () {});
|
||||
}).to.throwException();
|
||||
expect(function () {
|
||||
user.create(USERNAME, PASSWORD, EMAIL, {});
|
||||
}).to.throwException();
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('fails because user exists', function (done) {
|
||||
user.create(USERNAME, PASSWORD, EMAIL, IS_ADMIN, null /* invitor */, function (error, result) {
|
||||
expect(error).to.be.ok();
|
||||
expect(result).not.to.be.ok();
|
||||
expect(error.reason).to.equal(UserError.ALREADY_EXISTS);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails because password is empty', function (done) {
|
||||
user.create(USERNAME, '', EMAIL, IS_ADMIN, null /* invitor */, function (error, result) {
|
||||
expect(error).to.be.ok();
|
||||
expect(result).not.to.be.ok();
|
||||
expect(error.reason).to.equal(UserError.BAD_PASSWORD);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('verify', function () {
|
||||
before(createUser);
|
||||
after(cleanupUsers);
|
||||
|
||||
it('fails due to non existing username', function (done) {
|
||||
user.verify(USERNAME+USERNAME, PASSWORD, function (error, result) {
|
||||
expect(error).to.be.ok();
|
||||
expect(result).to.not.be.ok();
|
||||
expect(error.reason).to.equal(UserError.NOT_FOUND);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails due to empty password', function (done) {
|
||||
user.verify(USERNAME, '', function (error, result) {
|
||||
expect(error).to.be.ok();
|
||||
expect(result).to.not.be.ok();
|
||||
expect(error.reason).to.equal(UserError.WRONG_PASSWORD);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails due to wrong password', function (done) {
|
||||
user.verify(USERNAME, PASSWORD+PASSWORD, function (error, result) {
|
||||
expect(error).to.be.ok();
|
||||
expect(result).to.not.be.ok();
|
||||
expect(error.reason).to.equal(UserError.WRONG_PASSWORD);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('succeeds', function (done) {
|
||||
user.verify(USERNAME, PASSWORD, function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result).to.be.ok();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('verifyWithEmail', function () {
|
||||
before(createUser);
|
||||
after(cleanupUsers);
|
||||
|
||||
it('fails due to non existing user', function (done) {
|
||||
user.verifyWithEmail(EMAIL+EMAIL, PASSWORD, function (error, result) {
|
||||
expect(error).to.be.ok();
|
||||
expect(result).to.not.be.ok();
|
||||
expect(error.reason).to.equal(UserError.NOT_FOUND);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails due to empty password', function (done) {
|
||||
user.verifyWithEmail(EMAIL, '', function (error, result) {
|
||||
expect(error).to.be.ok();
|
||||
expect(result).to.not.be.ok();
|
||||
expect(error.reason).to.equal(UserError.WRONG_PASSWORD);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails due to wrong password', function (done) {
|
||||
user.verifyWithEmail(EMAIL, PASSWORD+PASSWORD, function (error, result) {
|
||||
expect(error).to.be.ok();
|
||||
expect(result).to.not.be.ok();
|
||||
expect(error.reason).to.equal(UserError.WRONG_PASSWORD);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('succeeds', function (done) {
|
||||
user.verifyWithEmail(EMAIL, PASSWORD, function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result).to.be.ok();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('retrieving', function () {
|
||||
before(createUser);
|
||||
after(cleanupUsers);
|
||||
|
||||
it('fails due to non existing user', function (done) {
|
||||
user.get('some non existing username', function (error, result) {
|
||||
expect(error).to.be.ok();
|
||||
expect(result).to.not.be.ok();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('succeeds', function (done) {
|
||||
user.get(USERNAME, function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result).to.be.ok();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', function () {
|
||||
before(createUser);
|
||||
after(cleanupUsers);
|
||||
|
||||
it('fails due to unknown userid', function (done) {
|
||||
user.update(USERNAME+USERNAME, USERNAME_NEW, EMAIL_NEW, function (error) {
|
||||
expect(error).to.be.a(UserError);
|
||||
expect(error.reason).to.equal(UserError.NOT_FOUND);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails due to invalid username', function (done) {
|
||||
user.update(USERNAME, '', EMAIL_NEW, function (error) {
|
||||
expect(error).to.be.a(UserError);
|
||||
expect(error.reason).to.equal(UserError.BAD_USERNAME);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails due to invalid email', function (done) {
|
||||
user.update(USERNAME, USERNAME_NEW, 'brokenemailaddress', function (error) {
|
||||
expect(error).to.be.a(UserError);
|
||||
expect(error.reason).to.equal(UserError.BAD_EMAIL);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('succeeds', function (done) {
|
||||
user.update(USERNAME, USERNAME_NEW, EMAIL_NEW, function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
|
||||
user.get(USERNAME, function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result).to.be.ok();
|
||||
expect(result.email).to.equal(EMAIL_NEW);
|
||||
expect(result.username).to.equal(USERNAME_NEW);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('admin change', function () {
|
||||
before(createUser);
|
||||
after(cleanupUsers);
|
||||
|
||||
it('fails to remove admin flag of only admin', function (done) {
|
||||
user.changeAdmin(USERNAME, false, function (error) {
|
||||
expect(error).to.be.an('object');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('make second user admin succeeds', function (done) {
|
||||
var user1 = {
|
||||
username: 'seconduser',
|
||||
password: 'foobar',
|
||||
email: 'some@thi.ng'
|
||||
};
|
||||
|
||||
user.create(user1.username, user1.password, user1.email, false, { username: USERNAME, email: EMAIL } /* invitor */, function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result).to.be.ok();
|
||||
|
||||
user.changeAdmin(user1.username, true, function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('succeeds to remove admin flag of first user', function (done) {
|
||||
user.changeAdmin(USERNAME, false, function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('password change', function () {
|
||||
before(createUser);
|
||||
after(cleanupUsers);
|
||||
|
||||
it('fails due to wrong arumgent count', function () {
|
||||
expect(function () { user.changePassword(); }).to.throwError();
|
||||
expect(function () { user.changePassword(USERNAME); }).to.throwError();
|
||||
expect(function () { user.changePassword(USERNAME, PASSWORD, NEW_PASSWORD); }).to.throwError();
|
||||
});
|
||||
|
||||
it('fails due to wrong arumgents', function () {
|
||||
expect(function () { user.changePassword(USERNAME, {}, NEW_PASSWORD, function () {}); }).to.throwError();
|
||||
expect(function () { user.changePassword(1337, PASSWORD, NEW_PASSWORD, function () {}); }).to.throwError();
|
||||
expect(function () { user.changePassword(USERNAME, PASSWORD, 1337, function () {}); }).to.throwError();
|
||||
expect(function () { user.changePassword(USERNAME, PASSWORD, NEW_PASSWORD, 'some string'); }).to.throwError();
|
||||
});
|
||||
|
||||
it('fails due to wrong password', function (done) {
|
||||
user.changePassword(USERNAME, 'wrongpassword', NEW_PASSWORD, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails due to empty new password', function (done) {
|
||||
user.changePassword(USERNAME, PASSWORD, '', function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails due to unknown user', function (done) {
|
||||
user.changePassword('somerandomuser', PASSWORD, NEW_PASSWORD, function (error) {
|
||||
expect(error).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('succeeds', function (done) {
|
||||
user.changePassword(USERNAME, PASSWORD, NEW_PASSWORD, function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('actually changed the password (unable to login with old pasword)', function (done) {
|
||||
user.verify(USERNAME, PASSWORD, function (error, result) {
|
||||
expect(error).to.be.ok();
|
||||
expect(result).to.not.be.ok();
|
||||
expect(error.reason).to.equal(UserError.WRONG_PASSWORD);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('actually changed the password (login with new password)', function (done) {
|
||||
user.verify(USERNAME, NEW_PASSWORD, function (error, result) {
|
||||
expect(error).to.not.be.ok();
|
||||
expect(result).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('resetPasswordByIdentifier', function () {
|
||||
before(createUser);
|
||||
after(cleanupUsers);
|
||||
|
||||
it('fails due to unkown email', function (done) {
|
||||
user.resetPasswordByIdentifier('unknown@mail.com', function (error) {
|
||||
expect(error).to.be.an(UserError);
|
||||
expect(error.reason).to.eql(UserError.NOT_FOUND);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fails due to unkown username', function (done) {
|
||||
user.resetPasswordByIdentifier('unknown', function (error) {
|
||||
expect(error).to.be.an(UserError);
|
||||
expect(error.reason).to.eql(UserError.NOT_FOUND);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('succeeds with email', function (done) {
|
||||
user.resetPasswordByIdentifier(EMAIL, function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('succeeds with username', function (done) {
|
||||
user.resetPasswordByIdentifier(USERNAME, function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user