migrate tests to node:test
This commit is contained in:
+7
-10
@@ -1,12 +1,9 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import acme2 from '../acme2.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Acme2', function () {
|
||||
const { setup, cleanup } = common;
|
||||
@@ -16,14 +13,14 @@ describe('Acme2', function () {
|
||||
|
||||
describe('getChallengeSubdomain', function () {
|
||||
it('non-wildcard', function () {
|
||||
expect(acme2._getChallengeSubdomain('example.com', 'example.com')).to.be('_acme-challenge');
|
||||
expect(acme2._getChallengeSubdomain('git.example.com', 'example.com')).to.be('_acme-challenge.git');
|
||||
assert.equal(acme2._getChallengeSubdomain('example.com', 'example.com'), '_acme-challenge');
|
||||
assert.equal(acme2._getChallengeSubdomain('git.example.com', 'example.com'), '_acme-challenge.git');
|
||||
});
|
||||
|
||||
it('wildcard', function () {
|
||||
expect(acme2._getChallengeSubdomain('*.example.com', 'example.com')).to.be('_acme-challenge');
|
||||
expect(acme2._getChallengeSubdomain('*.git.example.com', 'example.com')).to.be('_acme-challenge.git');
|
||||
expect(acme2._getChallengeSubdomain('*.example.com', 'customer.example.com')).to.be('_acme-challenge');
|
||||
assert.equal(acme2._getChallengeSubdomain('*.example.com', 'example.com'), '_acme-challenge');
|
||||
assert.equal(acme2._getChallengeSubdomain('*.git.example.com', 'example.com'), '_acme-challenge.git');
|
||||
assert.equal(acme2._getChallengeSubdomain('*.example.com', 'customer.example.com'), '_acme-challenge');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import addonConfigs from '../addonconfigs.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Addon config', function () {
|
||||
const { setup, cleanup, app } = common;
|
||||
@@ -16,7 +13,7 @@ describe('Addon config', function () {
|
||||
|
||||
it('returns empty addon config array for invalid app', async function () {
|
||||
const results = await addonConfigs.getByAppId('randomid');
|
||||
expect(results).to.eql([ ]);
|
||||
assert.deepEqual(results, [ ]);
|
||||
});
|
||||
|
||||
it('set succeeds', async function () {
|
||||
@@ -26,37 +23,37 @@ describe('Addon config', function () {
|
||||
|
||||
it('get succeeds', async function () {
|
||||
const results = await addonConfigs.get(app.id, 'addonid1');
|
||||
expect(results).to.eql([ { name: 'ENV1', value: 'env' }, { name: 'ENV2', value: 'env2' } ]);
|
||||
assert.deepEqual(results, [ { name: 'ENV1', value: 'env' }, { name: 'ENV2', value: 'env2' } ]);
|
||||
});
|
||||
|
||||
it('getByAppId succeeds', async function () {
|
||||
const results = await addonConfigs.getByAppId(app.id);
|
||||
expect(results).to.eql([ { name: 'ENV1', value: 'env' }, { name: 'ENV2', value: 'env2' }, { name: 'ENV3', value: 'env' } ]);
|
||||
assert.deepEqual(results, [ { name: 'ENV1', value: 'env' }, { name: 'ENV2', value: 'env2' }, { name: 'ENV3', value: 'env' } ]);
|
||||
});
|
||||
|
||||
it('getByName succeeds', async function () {
|
||||
const value = await addonConfigs.getByName(app.id, 'addonid1', 'ENV2');
|
||||
expect(value).to.be('env2');
|
||||
assert.equal(value, 'env2');
|
||||
});
|
||||
|
||||
it('getByName of unknown value succeeds', async function () {
|
||||
const value = await addonConfigs.getByName(app.id, 'addonid1', 'ENVRANDOM');
|
||||
expect(value).to.be(null);
|
||||
assert.equal(value, null);
|
||||
});
|
||||
|
||||
it('getAppIdByValue succeeds', async function () {
|
||||
const appId = await addonConfigs.getAppIdByValue('addonid1', 'ENV1', 'env');
|
||||
expect(appId).to.be(app.id);
|
||||
assert.equal(appId, app.id);
|
||||
});
|
||||
|
||||
it('getAppIdByValue pattern succeeds', async function () {
|
||||
const appId = await addonConfigs.getAppIdByValue('addonid1', '%ENV1', 'env');
|
||||
expect(appId).to.be(app.id);
|
||||
assert.equal(appId, app.id);
|
||||
});
|
||||
|
||||
it('getAppIdByValue pattern of unknown succeeds', async function () {
|
||||
const appId = await addonConfigs.getAppIdByValue('addonid1', '%ENV1', 'envx');
|
||||
expect(appId).to.be(null);
|
||||
assert.equal(appId, null);
|
||||
});
|
||||
|
||||
it('unset succeeds', async function () {
|
||||
@@ -65,7 +62,7 @@ describe('Addon config', function () {
|
||||
|
||||
it('unsetAddonConfig did remove configs', async function () {
|
||||
const results = await addonConfigs.getByAppId(app.id);
|
||||
expect(results).to.eql([ { name: 'ENV3', value: 'env' }]);
|
||||
assert.deepEqual(results, [ { name: 'ENV3', value: 'env' }]);
|
||||
});
|
||||
|
||||
it('unsetByAppId succeeds', async function () {
|
||||
@@ -74,6 +71,6 @@ describe('Addon config', function () {
|
||||
|
||||
it('unsetByAppId did remove configs', async function () {
|
||||
const results = await addonConfigs.getByAppId(app.id);
|
||||
expect(results).to.eql([ ]);
|
||||
assert.deepEqual(results, [ ]);
|
||||
});
|
||||
});
|
||||
|
||||
+29
-32
@@ -1,14 +1,11 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import applinks from '../applinks.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Applinks', function () {
|
||||
const { setup, cleanup } = common;
|
||||
@@ -55,76 +52,76 @@ describe('Applinks', function () {
|
||||
APPLINK_2.id = await applinks.add(deepCopy(APPLINK_2));
|
||||
|
||||
const result = await applinks.get(APPLINK_2.id);
|
||||
expect(result.upstreamUri).to.eql(APPLINK_2.upstreamUri); // should not have changed
|
||||
expect(result.icon.length).to.not.eql(0);
|
||||
assert.deepEqual(result.upstreamUri, APPLINK_2.upstreamUri); // should not have changed
|
||||
assert.notDeepEqual(result.icon.length, 0);
|
||||
});
|
||||
|
||||
it('can add fourth applink to test no favicon', async function () {
|
||||
APPLINK_3.id = await applinks.add(deepCopy(APPLINK_3));
|
||||
|
||||
const result = await applinks.get(APPLINK_3.id);
|
||||
expect(result.upstreamUri).to.eql('http://example.com');
|
||||
expect(result.icon).to.eql(null);
|
||||
assert.deepEqual(result.upstreamUri, 'http://example.com');
|
||||
assert.deepEqual(result.icon, null);
|
||||
});
|
||||
|
||||
it('can list all without accessRestriction', async function () {
|
||||
const result = await applinks.list();
|
||||
|
||||
expect(result.length).to.equal(4);
|
||||
expect(result[1].id).to.eql(APPLINK_0.id);
|
||||
expect(result[1].upstreamUri).to.eql(APPLINK_0.upstreamUri);
|
||||
expect(result[3].id).to.eql(APPLINK_1.id);
|
||||
expect(result[3].upstreamUri).to.eql(APPLINK_1.upstreamUri);
|
||||
expect(result[3].label).to.eql(APPLINK_1.label);
|
||||
expect(result[3].accessRestriction).to.eql(APPLINK_1.accessRestriction);
|
||||
expect(result[3].tags).to.eql(APPLINK_1.tags);
|
||||
expect(result[3].icon.toString('base64')).to.eql(APPLINK_1.icon);
|
||||
assert.equal(result.length, 4);
|
||||
assert.deepEqual(result[1].id, APPLINK_0.id);
|
||||
assert.deepEqual(result[1].upstreamUri, APPLINK_0.upstreamUri);
|
||||
assert.deepEqual(result[3].id, APPLINK_1.id);
|
||||
assert.deepEqual(result[3].upstreamUri, APPLINK_1.upstreamUri);
|
||||
assert.deepEqual(result[3].label, APPLINK_1.label);
|
||||
assert.deepEqual(result[3].accessRestriction, APPLINK_1.accessRestriction);
|
||||
assert.deepEqual(result[3].tags, APPLINK_1.tags);
|
||||
assert.deepEqual(result[3].icon.toString('base64'), APPLINK_1.icon);
|
||||
});
|
||||
|
||||
it('cannot get applink with wrong id', async function () {
|
||||
const result = await applinks.get('doesnotexist');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('can get applink', async function () {
|
||||
const result = await applinks.get(APPLINK_0.id);
|
||||
expect(result.upstreamUri).to.eql(APPLINK_0.upstreamUri);
|
||||
assert.deepEqual(result.upstreamUri, APPLINK_0.upstreamUri);
|
||||
});
|
||||
|
||||
it('can get second applink', async function () {
|
||||
const result = await applinks.get(APPLINK_1.id);
|
||||
|
||||
expect(result.id).to.eql(APPLINK_1.id);
|
||||
expect(result.upstreamUri).to.eql(APPLINK_1.upstreamUri);
|
||||
expect(result.label).to.eql(APPLINK_1.label);
|
||||
expect(result.accessRestriction).to.eql(APPLINK_1.accessRestriction);
|
||||
expect(result.tags).to.eql(APPLINK_1.tags);
|
||||
expect(result.icon.toString('base64')).to.eql(APPLINK_1.icon);
|
||||
assert.deepEqual(result.id, APPLINK_1.id);
|
||||
assert.deepEqual(result.upstreamUri, APPLINK_1.upstreamUri);
|
||||
assert.deepEqual(result.label, APPLINK_1.label);
|
||||
assert.deepEqual(result.accessRestriction, APPLINK_1.accessRestriction);
|
||||
assert.deepEqual(result.tags, APPLINK_1.tags);
|
||||
assert.deepEqual(result.icon.toString('base64'), APPLINK_1.icon);
|
||||
});
|
||||
|
||||
it('can update applink', async function () {
|
||||
await applinks.update(APPLINK_0, { upstreamUri: 'https://duckduckgo.com', icon: APPLINK_1.icon });
|
||||
|
||||
const result = await applinks.get(APPLINK_0.id);
|
||||
expect(result.upstreamUri).to.equal('https://duckduckgo.com');
|
||||
expect(result.icon.toString('base64')).to.eql(APPLINK_1.icon);
|
||||
assert.equal(result.upstreamUri, 'https://duckduckgo.com');
|
||||
assert.deepEqual(result.icon.toString('base64'), APPLINK_1.icon);
|
||||
});
|
||||
|
||||
it('can get applink icon', async function () {
|
||||
const result = await applinks.get(APPLINK_0.id);
|
||||
expect(result.icon.toString('base64')).to.eql(APPLINK_1.icon);
|
||||
assert.deepEqual(result.icon.toString('base64'), APPLINK_1.icon);
|
||||
});
|
||||
|
||||
it('cannot del applink with wrong id', async function () {
|
||||
const [error] = await safe(applinks.del({ id: 'doesnotexist' }));
|
||||
expect(error).to.be.a(BoxError);
|
||||
expect(error.reason).to.eql(BoxError.NOT_FOUND);
|
||||
assert.ok((error) instanceof (BoxError));
|
||||
assert.deepEqual(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('can del applink', async function () {
|
||||
await applinks.del(APPLINK_0);
|
||||
|
||||
const result = await applinks.get(APPLINK_0.id);
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import appPasswords from '../apppasswords.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
import users from '../users.js';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('App passwords', function () {
|
||||
const { setup, cleanup, admin } = common;
|
||||
@@ -21,59 +18,59 @@ describe('App passwords', function () {
|
||||
let id, password;
|
||||
it('cannot add bad app password', async function () {
|
||||
const [error] = await safe(appPasswords.add(admin.id, 'appid', 'x'.repeat(201), null));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can add app password', async function () {
|
||||
const result = await appPasswords.add(admin.id, 'appid', 'spark', null);
|
||||
expect(result.id).to.be.a('string');
|
||||
expect(result.password).to.be.a('string');
|
||||
assert.equal(typeof result.id, 'string');
|
||||
assert.equal(typeof result.password, 'string');
|
||||
id = result.id;
|
||||
password = result.password;
|
||||
});
|
||||
|
||||
it('can get app password', async function () {
|
||||
const result = await appPasswords.get(id);
|
||||
expect(result.hashedPassword).to.be.a('string');
|
||||
expect(result.name).to.be('spark');
|
||||
expect(result.identifier).to.be('appid');
|
||||
assert.equal(typeof result.hashedPassword, 'string');
|
||||
assert.equal(result.name, 'spark');
|
||||
assert.equal(result.identifier, 'appid');
|
||||
});
|
||||
|
||||
it('cannot get random app password', async function () {
|
||||
const result = await appPasswords.get('random');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('can get app passwords', async function () {
|
||||
const results = await appPasswords.list(admin.id);
|
||||
expect(results.length).to.be(1);
|
||||
expect(results[0].hashedPassword).to.be.a('string');
|
||||
expect(results[0].name).to.be('spark');
|
||||
expect(results[0].identifier).to.be('appid');
|
||||
assert.equal(results.length, 1);
|
||||
assert.equal(typeof results[0].hashedPassword, 'string');
|
||||
assert.equal(results[0].name, 'spark');
|
||||
assert.equal(results[0].identifier, 'appid');
|
||||
});
|
||||
|
||||
it('can verify app password', async function () {
|
||||
const result = await users.verifyWithId(admin.id, password, 'appid', {});
|
||||
expect(result).to.be.ok();
|
||||
expect(result.appPassword).to.be(true);
|
||||
assert.ok(result);
|
||||
assert.equal(result.appPassword, true);
|
||||
});
|
||||
|
||||
it('can verify non-app password', async function () {
|
||||
const result = await users.verifyWithId(admin.id, admin.password, 'appid', {});
|
||||
expect(result).to.be.ok();
|
||||
expect(result.appPassword).to.be(undefined);
|
||||
assert.ok(result);
|
||||
assert.equal(result.appPassword, undefined);
|
||||
});
|
||||
|
||||
it('cannot verify bad password', async function () {
|
||||
const [error, result] = await safe(users.verifyWithId(admin.id, 'bad', 'appid', {}));
|
||||
expect(result).to.not.be.ok();
|
||||
expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS);
|
||||
assert.ok(!(result));
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('cannot verify password for another app', async function () {
|
||||
const [error, result] = await safe(users.verifyWithId(admin.id, password, 'appid2', {}));
|
||||
expect(result).to.not.be.ok();
|
||||
expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS);
|
||||
assert.ok(!(result));
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('can del app password', async function () {
|
||||
@@ -82,42 +79,42 @@ describe('App passwords', function () {
|
||||
|
||||
it('cannot verify deleted app password', async function () {
|
||||
const [error] = await safe(users.verifyWithId(admin.id, password, 'appid', {}));
|
||||
expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('cannot del random app password', async function () {
|
||||
const [error] = await safe(appPasswords.del('random'));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
// expiry tests
|
||||
let expiredPassword;
|
||||
it('can add app password with expiry', async function () {
|
||||
const result = await appPasswords.add(admin.id, 'appid', 'expiring', new Date(Date.now() + 60000).toISOString());
|
||||
expect(result.id).to.be.a('string');
|
||||
expect(result.password).to.be.a('string');
|
||||
assert.equal(typeof result.id, 'string');
|
||||
assert.equal(typeof result.password, 'string');
|
||||
expiredPassword = result.password;
|
||||
});
|
||||
|
||||
it('can verify non-expired app password', async function () {
|
||||
const result = await users.verifyWithId(admin.id, expiredPassword, 'appid', {});
|
||||
expect(result).to.be.ok();
|
||||
expect(result.appPassword).to.be(true);
|
||||
assert.ok(result);
|
||||
assert.equal(result.appPassword, true);
|
||||
});
|
||||
|
||||
let pastId, pastPassword;
|
||||
it('can add app password with past expiry', async function () {
|
||||
const result = await appPasswords.add(admin.id, 'appid', 'expired', new Date(Date.now() - 60000).toISOString());
|
||||
expect(result.id).to.be.a('string');
|
||||
expect(result.password).to.be.a('string');
|
||||
assert.equal(typeof result.id, 'string');
|
||||
assert.equal(typeof result.password, 'string');
|
||||
pastId = result.id;
|
||||
pastPassword = result.password;
|
||||
});
|
||||
|
||||
it('cannot verify expired app password', async function () {
|
||||
const [error, result] = await safe(users.verifyWithId(admin.id, pastPassword, 'appid', {}));
|
||||
expect(result).to.not.be.ok();
|
||||
expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS);
|
||||
assert.ok(!(result));
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('can del expired app password', async function () {
|
||||
|
||||
+105
-108
@@ -1,19 +1,16 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import apps from '../apps.js';
|
||||
import AuditSource from '../auditsource.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import Location from '../location.js';
|
||||
import safe from 'safetydance';
|
||||
import users from '../users.js';
|
||||
|
||||
const { proxyApp } = common;
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Apps', function () {
|
||||
const { domainSetup, cleanup, app, admin, user , domain } = common;
|
||||
@@ -32,18 +29,18 @@ describe('Apps', function () {
|
||||
|
||||
it('throws on exact conflict', async function () {
|
||||
let [error] = await safe(apps._checkForPortBindingConflict([{ hostPort: 40000, type: 'tcp', count: 1 }], {}));
|
||||
expect(error.reason).to.equal(BoxError.CONFLICT);
|
||||
assert.equal(error.reason, BoxError.CONFLICT);
|
||||
|
||||
[error] = await safe(apps._checkForPortBindingConflict([{ hostPort: 50000, type: 'udp', count: 1 }], {}));
|
||||
expect(error.reason).to.equal(BoxError.CONFLICT);
|
||||
assert.equal(error.reason, BoxError.CONFLICT);
|
||||
});
|
||||
|
||||
it('throws on range conflict', async function () {
|
||||
let [error] = await safe(apps._checkForPortBindingConflict([{ hostPort: 40080, type: 'tcp', count: 40 }], {}));
|
||||
expect(error.reason).to.equal(BoxError.CONFLICT);
|
||||
assert.equal(error.reason, BoxError.CONFLICT);
|
||||
|
||||
[error] = await safe(apps._checkForPortBindingConflict([{ hostPort: 49995, type: 'udp', count: 20 }], {}));
|
||||
expect(error.reason).to.equal(BoxError.CONFLICT);
|
||||
assert.equal(error.reason, BoxError.CONFLICT);
|
||||
});
|
||||
|
||||
it('succeeds without conflict', async function () {
|
||||
@@ -57,105 +54,105 @@ describe('Apps', function () {
|
||||
describe('validateLocations', function () {
|
||||
it('does not allow reserved subdomain', async function () {
|
||||
const location = new Location('my', domain.domain, Location.TYPE_ALIAS);
|
||||
expect(await apps._validateLocations([location])).to.be.an(Error);
|
||||
assert.ok((await apps._validateLocations([location])) instanceof (Error));
|
||||
});
|
||||
|
||||
it('does not allow unknown domain', async function () {
|
||||
const location = new Location('my2', domain.domain + 'x', Location.TYPE_PRIMARY);
|
||||
expect(await apps._validateLocations([location])).to.be.an(Error);
|
||||
assert.ok((await apps._validateLocations([location])) instanceof (Error));
|
||||
});
|
||||
|
||||
it('allows valid locations', async function () {
|
||||
const location = new Location('my2', domain.domain, Location.TYPE_SECONDARY);
|
||||
expect(await apps._validateLocations([location])).to.be(null);
|
||||
assert.equal(await apps._validateLocations([location]), null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('validatePortBindings', function () {
|
||||
it('does not allow invalid host port', function () {
|
||||
expect(apps._validatePorts({ PORT: -1 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error);
|
||||
expect(apps._validatePorts({ PORT: 0 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error);
|
||||
expect(apps._validatePorts({ PORT: 'text' }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error);
|
||||
expect(apps._validatePorts({ PORT: 65536 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error);
|
||||
expect(apps._validatePorts({ PORT: 470 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error);
|
||||
assert.ok((apps._validatePorts({ PORT: -1 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error));
|
||||
assert.ok((apps._validatePorts({ PORT: 0 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error));
|
||||
assert.ok((apps._validatePorts({ PORT: 'text' }, { tcpPorts: { PORT: 5000 } })) instanceof (Error));
|
||||
assert.ok((apps._validatePorts({ PORT: 65536 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error));
|
||||
assert.ok((apps._validatePorts({ PORT: 470 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error));
|
||||
});
|
||||
|
||||
it('does not allow ports not as part of manifest', function () {
|
||||
expect(apps._validatePorts({ PORT: 1567 }, { tcpPorts: { } })).to.be.an(Error);
|
||||
expect(apps._validatePorts({ PORT: 1567 }, { tcpPorts: { port3: null } })).to.be.an(Error);
|
||||
assert.ok((apps._validatePorts({ PORT: 1567 }, { tcpPorts: { } })) instanceof (Error));
|
||||
assert.ok((apps._validatePorts({ PORT: 1567 }, { tcpPorts: { port3: null } })) instanceof (Error));
|
||||
});
|
||||
|
||||
it('does not allow reserved ports', function () {
|
||||
expect(apps._validatePorts({ PORT: 443 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error);
|
||||
expect(apps._validatePorts({ PORT: 50000 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error);
|
||||
expect(apps._validatePorts({ PORT: 50100 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error);
|
||||
expect(apps._validatePorts({ PORT: 50050 }, { tcpPorts: { PORT: 5000 } })).to.be.an(Error);
|
||||
assert.ok((apps._validatePorts({ PORT: 443 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error));
|
||||
assert.ok((apps._validatePorts({ PORT: 50000 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error));
|
||||
assert.ok((apps._validatePorts({ PORT: 50100 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error));
|
||||
assert.ok((apps._validatePorts({ PORT: 50050 }, { tcpPorts: { PORT: 5000 } })) instanceof (Error));
|
||||
});
|
||||
|
||||
it('allows valid bindings', function () {
|
||||
expect(apps._validatePorts({ PORT: 1024 }, { tcpPorts: { PORT: 5000 } })).to.be(null);
|
||||
assert.equal(apps._validatePorts({ PORT: 1024 }, { tcpPorts: { PORT: 5000 } }), null);
|
||||
|
||||
expect(apps._validatePorts({
|
||||
assert.equal(apps._validatePorts({
|
||||
PORT1: 4033,
|
||||
PORT2: 3242,
|
||||
PORT3: 1234
|
||||
}, { tcpPorts: { PORT1: {}, PORT2: {}, PORT3: {} } })).to.be(null);
|
||||
}, { tcpPorts: { PORT1: {}, PORT2: {}, PORT3: {} } }), null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateAccessRestriction', function () {
|
||||
it('allows null input', function () {
|
||||
expect(apps._validateAccessRestriction(null)).to.eql(null);
|
||||
assert.deepEqual(apps._validateAccessRestriction(null), null);
|
||||
});
|
||||
|
||||
it('does not allow wrong user type', function () {
|
||||
expect(apps._validateAccessRestriction({ users: {} })).to.be.an(Error);
|
||||
assert.ok((apps._validateAccessRestriction({ users: {} })) instanceof (Error));
|
||||
});
|
||||
|
||||
it('allows user input', function () {
|
||||
expect(apps._validateAccessRestriction({ users: [] })).to.eql(null);
|
||||
assert.deepEqual(apps._validateAccessRestriction({ users: [] }), null);
|
||||
});
|
||||
|
||||
it('allows single user input', function () {
|
||||
expect(apps._validateAccessRestriction({ users: [ 'someuserid' ] })).to.eql(null);
|
||||
assert.deepEqual(apps._validateAccessRestriction({ users: [ 'someuserid' ] }), null);
|
||||
});
|
||||
|
||||
it('allows multi user input', function () {
|
||||
expect(apps._validateAccessRestriction({ users: [ 'someuserid', 'someuserid1', 'someuserid2', 'someuserid3' ] })).to.eql(null);
|
||||
assert.deepEqual(apps._validateAccessRestriction({ users: [ 'someuserid', 'someuserid1', 'someuserid2', 'someuserid3' ] }), null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateUpstreamUri', function () {
|
||||
it('does not allow empty URI', function () {
|
||||
expect(apps._validateUpstreamUri('')).to.be.an(Error);
|
||||
assert.ok((apps._validateUpstreamUri('')) instanceof (Error));
|
||||
});
|
||||
|
||||
it('does not allow invalid URI scheme', function () {
|
||||
expect(apps._validateUpstreamUri('bla:blub')).to.be.an(Error);
|
||||
assert.ok((apps._validateUpstreamUri('bla:blub')) instanceof (Error));
|
||||
});
|
||||
|
||||
it('does not allow unsupported scheme', function () {
|
||||
expect(apps._validateUpstreamUri('ftp://foobar.com')).to.be.an(Error);
|
||||
assert.ok((apps._validateUpstreamUri('ftp://foobar.com')) instanceof (Error));
|
||||
});
|
||||
|
||||
it('does not allow trailing URI paths ', function () {
|
||||
expect(apps._validateUpstreamUri('https://foobar.com/extra/path')).to.be.an(Error);
|
||||
assert.ok((apps._validateUpstreamUri('https://foobar.com/extra/path')) instanceof (Error));
|
||||
});
|
||||
|
||||
it('allows IP', function () {
|
||||
expect(apps._validateUpstreamUri('http://1.2.3.4')).to.eql(null);
|
||||
assert.deepEqual(apps._validateUpstreamUri('http://1.2.3.4'), null);
|
||||
});
|
||||
|
||||
it('allows IP with port', function () {
|
||||
expect(apps._validateUpstreamUri('http://1.2.3.4:80')).to.eql(null);
|
||||
assert.deepEqual(apps._validateUpstreamUri('http://1.2.3.4:80'), null);
|
||||
});
|
||||
|
||||
it('allows domain', function () {
|
||||
expect(apps._validateUpstreamUri('https://www.cloudron.io')).to.eql(null);
|
||||
assert.deepEqual(apps._validateUpstreamUri('https://www.cloudron.io'), null);
|
||||
});
|
||||
|
||||
it('allows domain with port', function () {
|
||||
expect(apps._validateUpstreamUri('https://www.cloudron.io:443')).to.eql(null);
|
||||
assert.deepEqual(apps._validateUpstreamUri('https://www.cloudron.io:443'), null);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -164,35 +161,35 @@ describe('Apps', function () {
|
||||
const adminuser = { id: 'adminuser', groupIds: [ 'groupie' ], role: users.ROLE_ADMIN };
|
||||
|
||||
it('returns true for unrestricted access', function () {
|
||||
expect(apps.canAccess({ accessRestriction: null }, someuser)).to.be(true);
|
||||
assert.equal(apps.canAccess({ accessRestriction: null }, someuser), true);
|
||||
});
|
||||
|
||||
it('returns true for allowed user', function () {
|
||||
expect(apps.canAccess({ accessRestriction: { users: [ 'someuser' ] } }, someuser)).to.be(true);
|
||||
assert.equal(apps.canAccess({ accessRestriction: { users: [ 'someuser' ] } }, someuser), true);
|
||||
});
|
||||
|
||||
it('returns true for allowed user with multiple allowed', function () {
|
||||
expect(apps.canAccess({ accessRestriction: { users: [ 'foo', 'someuser', 'anotheruser' ] } }, someuser)).to.be(true);
|
||||
assert.equal(apps.canAccess({ accessRestriction: { users: [ 'foo', 'someuser', 'anotheruser' ] } }, someuser), true);
|
||||
});
|
||||
|
||||
it('returns false for not allowed user', function () {
|
||||
expect(apps.canAccess({ accessRestriction: { users: [ 'foo' ] } }, someuser)).to.be(false);
|
||||
assert.equal(apps.canAccess({ accessRestriction: { users: [ 'foo' ] } }, someuser), false);
|
||||
});
|
||||
|
||||
it('returns false for not allowed user with multiple allowed', function () {
|
||||
expect(apps.canAccess({ accessRestriction: { users: [ 'foo', 'anotheruser' ] } }, someuser)).to.be(false);
|
||||
assert.equal(apps.canAccess({ accessRestriction: { users: [ 'foo', 'anotheruser' ] } }, someuser), false);
|
||||
});
|
||||
|
||||
it('returns false for no group or user', function () {
|
||||
expect(apps.canAccess({ accessRestriction: { users: [ ], groups: [ ] } }, someuser)).to.be(false);
|
||||
assert.equal(apps.canAccess({ accessRestriction: { users: [ ], groups: [ ] } }, someuser), false);
|
||||
});
|
||||
|
||||
it('returns false for invalid group or user', function () {
|
||||
expect(apps.canAccess({ accessRestriction: { users: [ ], groups: [ 'nop' ] } }, someuser)).to.be(false);
|
||||
assert.equal(apps.canAccess({ accessRestriction: { users: [ ], groups: [ 'nop' ] } }, someuser), false);
|
||||
});
|
||||
|
||||
it('returns true for admin user', function () {
|
||||
expect(apps.canAccess({ accessRestriction: { users: [ ], groups: [ 'nop' ] } }, adminuser)).to.be(true);
|
||||
assert.equal(apps.canAccess({ accessRestriction: { users: [ ], groups: [ 'nop' ] } }, adminuser), true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -201,35 +198,35 @@ describe('Apps', function () {
|
||||
const adminuser = { id: 'adminuser', groupIds: [ 'groupie' ], role: users.ROLE_ADMIN };
|
||||
|
||||
it('returns false for unrestricted access', function () {
|
||||
expect(apps.isOperator({ operators: null }, someuser)).to.be(false);
|
||||
assert.equal(apps.isOperator({ operators: null }, someuser), false);
|
||||
});
|
||||
|
||||
it('returns true for allowed user', function () {
|
||||
expect(apps.isOperator({ operators: { users: [ 'someuser' ] } }, someuser)).to.be(true);
|
||||
assert.equal(apps.isOperator({ operators: { users: [ 'someuser' ] } }, someuser), true);
|
||||
});
|
||||
|
||||
it('returns true for allowed user with multiple allowed', function () {
|
||||
expect(apps.isOperator({ operators: { users: [ 'foo', 'someuser', 'anotheruser' ] } }, someuser)).to.be(true);
|
||||
assert.equal(apps.isOperator({ operators: { users: [ 'foo', 'someuser', 'anotheruser' ] } }, someuser), true);
|
||||
});
|
||||
|
||||
it('returns false for not allowed user', function () {
|
||||
expect(apps.isOperator({ operators: { users: [ 'foo' ] } }, someuser)).to.be(false);
|
||||
assert.equal(apps.isOperator({ operators: { users: [ 'foo' ] } }, someuser), false);
|
||||
});
|
||||
|
||||
it('returns false for not allowed user with multiple allowed', function () {
|
||||
expect(apps.isOperator({ operators: { users: [ 'foo', 'anotheruser' ] } }, someuser)).to.be(false);
|
||||
assert.equal(apps.isOperator({ operators: { users: [ 'foo', 'anotheruser' ] } }, someuser), false);
|
||||
});
|
||||
|
||||
it('returns false for no group or user', function () {
|
||||
expect(apps.isOperator({ operators: { users: [ ], groups: [ ] } }, someuser)).to.be(false);
|
||||
assert.equal(apps.isOperator({ operators: { users: [ ], groups: [ ] } }, someuser), false);
|
||||
});
|
||||
|
||||
it('returns false for invalid group or user', function () {
|
||||
expect(apps.isOperator({ operators: { users: [ ], groups: [ 'nop' ] } }, someuser)).to.be(false);
|
||||
assert.equal(apps.isOperator({ operators: { users: [ ], groups: [ 'nop' ] } }, someuser), false);
|
||||
});
|
||||
|
||||
it('returns true for admin user', function () {
|
||||
expect(apps.isOperator({ operators: { users: [ ], groups: [ 'nop' ] } }, adminuser)).to.be(true);
|
||||
assert.equal(apps.isOperator({ operators: { users: [ ], groups: [ 'nop' ] } }, adminuser), true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -238,25 +235,25 @@ describe('Apps', function () {
|
||||
const adminuser = { id: 'adminuser', groupIds: [ 'groupie' ], role: users.ROLE_ADMIN };
|
||||
|
||||
it('return user for normal user', function () {
|
||||
expect(apps.accessLevel({ accessRestriction: null, operators: null }, someuser)).to.be(apps.ACCESS_LEVEL_USER);
|
||||
expect(apps.accessLevel({ accessRestriction: null, operators: { users: [ ], groups: [ 'groupie' ] } }, someuser)).to.be(apps.ACCESS_LEVEL_USER);
|
||||
assert.equal(apps.accessLevel({ accessRestriction: null, operators: null }, someuser), apps.ACCESS_LEVEL_USER);
|
||||
assert.equal(apps.accessLevel({ accessRestriction: null, operators: { users: [ ], groups: [ 'groupie' ] } }, someuser), apps.ACCESS_LEVEL_USER);
|
||||
});
|
||||
|
||||
it('returns operator for operator user', function () {
|
||||
expect(apps.accessLevel({ accessRestriction: null, operators: { users: [ 'someuser' ], groups: [ 'groupie' ] } }, someuser)).to.be(apps.ACCESS_LEVEL_OPERATOR);
|
||||
expect(apps.accessLevel({ accessRestriction: null, operators: { users: [], groups: [ 'ops' ] } }, someuser)).to.be(apps.ACCESS_LEVEL_OPERATOR);
|
||||
assert.equal(apps.accessLevel({ accessRestriction: null, operators: { users: [ 'someuser' ], groups: [ 'groupie' ] } }, someuser), apps.ACCESS_LEVEL_OPERATOR);
|
||||
assert.equal(apps.accessLevel({ accessRestriction: null, operators: { users: [], groups: [ 'ops' ] } }, someuser), apps.ACCESS_LEVEL_OPERATOR);
|
||||
});
|
||||
|
||||
it('returns admin for admin user', function () {
|
||||
expect(apps.accessLevel({ accessRestriction: null, operators: null }, adminuser)).to.be(apps.ACCESS_LEVEL_ADMIN);
|
||||
expect(apps.accessLevel({ accessRestriction: null, operators: { users: [], groups: [] } }, adminuser)).to.be(apps.ACCESS_LEVEL_ADMIN);
|
||||
assert.equal(apps.accessLevel({ accessRestriction: null, operators: null }, adminuser), apps.ACCESS_LEVEL_ADMIN);
|
||||
assert.equal(apps.accessLevel({ accessRestriction: null, operators: { users: [], groups: [] } }, adminuser), apps.ACCESS_LEVEL_ADMIN);
|
||||
});
|
||||
});
|
||||
|
||||
describe('crud', function () {
|
||||
it('cannot get invalid app', async function () {
|
||||
const result = await apps.get('nope');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('can add app', async function () {
|
||||
@@ -265,35 +262,35 @@ describe('Apps', function () {
|
||||
|
||||
it('cannot add with same app id', async function () {
|
||||
const [error] = await safe(apps.add(app.id, app.appStoreId, '', app.manifest, app.subdomain, app.domain, app.portBindings, app));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('cannot add with same app id', async function () {
|
||||
const [error] = await safe(apps.add(app.id, app.appStoreId, '', app.manifest, app.subdomain, app.domain, app.portBindings, app));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('can get app', async function () {
|
||||
const result = await apps.get(app.id);
|
||||
expect(result.manifest).to.eql(app.manifest);
|
||||
expect(result.portBindings).to.eql({});
|
||||
expect(result.subdomain).to.eql(app.subdomain);
|
||||
assert.deepEqual(result.manifest, app.manifest);
|
||||
assert.deepEqual(result.portBindings, {});
|
||||
assert.deepEqual(result.subdomain, app.subdomain);
|
||||
});
|
||||
|
||||
it('can list apps', async function () {
|
||||
const result = await apps.list();
|
||||
expect(result.length).to.be(1);
|
||||
expect(result[0].manifest).to.eql(app.manifest);
|
||||
expect(result[0].portBindings).to.eql({});
|
||||
expect(result[0].subdomain).to.eql(app.subdomain);
|
||||
assert.equal(result.length, 1);
|
||||
assert.deepEqual(result[0].manifest, app.manifest);
|
||||
assert.deepEqual(result[0].portBindings, {});
|
||||
assert.deepEqual(result[0].subdomain, app.subdomain);
|
||||
});
|
||||
|
||||
it('can listByUser', async function () {
|
||||
let result = await apps.listByUser(admin);
|
||||
expect(result.length).to.be(1);
|
||||
assert.equal(result.length, 1);
|
||||
|
||||
result = await apps.listByUser(user);
|
||||
expect(result.length).to.be(1);
|
||||
assert.equal(result.length, 1);
|
||||
});
|
||||
|
||||
it('update succeeds', async function () {
|
||||
@@ -310,17 +307,17 @@ describe('Apps', function () {
|
||||
|
||||
await apps.update(app.id, data);
|
||||
const newApp = await apps.get(app.id);
|
||||
expect(newApp.installationState).to.be('some-other-status');
|
||||
expect(newApp.subdomain).to.be('some-other-subdomain');
|
||||
expect(newApp.manifest.version).to.be('0.2.0');
|
||||
expect(newApp.accessRestriction).to.be('');
|
||||
expect(newApp.memoryLimit).to.be(1337);
|
||||
expect(newApp.cpuQuota).to.be(79);
|
||||
assert.equal(newApp.installationState, 'some-other-status');
|
||||
assert.equal(newApp.subdomain, 'some-other-subdomain');
|
||||
assert.equal(newApp.manifest.version, '0.2.0');
|
||||
assert.equal(newApp.accessRestriction, '');
|
||||
assert.equal(newApp.memoryLimit, 1337);
|
||||
assert.equal(newApp.cpuQuota, 79);
|
||||
});
|
||||
|
||||
it('update of nonexisting app fails', async function () {
|
||||
const [error] = await safe(apps.update('random', { installationState: app.installationState, subdomain: app.subdomain }));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('delete succeeds', async function () {
|
||||
@@ -329,7 +326,7 @@ describe('Apps', function () {
|
||||
|
||||
it('cannot delete previously delete record', async function () {
|
||||
const [error] = await safe(apps.del(app.id));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -340,19 +337,19 @@ describe('Apps', function () {
|
||||
|
||||
it('can set app as healthy', async function () {
|
||||
const result = await apps.get(app.id);
|
||||
expect(result.health).to.be(null);
|
||||
assert.equal(result.health, null);
|
||||
|
||||
await apps.setHealth(app.id, apps.HEALTH_HEALTHY, new Date());
|
||||
});
|
||||
|
||||
it('did set app as healthy', async function () {
|
||||
const result = await apps.get(app.id);
|
||||
expect(result.health).to.be(apps.HEALTH_HEALTHY);
|
||||
assert.equal(result.health, apps.HEALTH_HEALTHY);
|
||||
});
|
||||
|
||||
it('cannot set health of unknown app', async function () {
|
||||
const [error] = await safe(apps.setHealth('randomId', apps.HEALTH_HEALTHY, new Date()));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -365,14 +362,14 @@ describe('Apps', function () {
|
||||
|
||||
it('cannot set invalid upstream uri', async function () {
|
||||
const [error] = await safe(apps.setUpstreamUri(proxyApp, 'foo:bar:80', AuditSource.PLATFORM));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can set upstream uri', async function () {
|
||||
await apps.setUpstreamUri(proxyApp, newUpstreamUri, AuditSource.PLATFORM);
|
||||
const result = await apps.get(proxyApp.id);
|
||||
|
||||
expect(result.upstreamUri).to.equal(newUpstreamUri);
|
||||
assert.equal(result.upstreamUri, newUpstreamUri);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -395,9 +392,9 @@ describe('Apps', function () {
|
||||
await apps.configureApps(await apps.list(), { scheduleNow: false }, AuditSource.PLATFORM);
|
||||
|
||||
const result = await apps.list();
|
||||
expect(result[0].installationState).to.be(apps.ISTATE_PENDING_CONFIGURE);
|
||||
expect(result[1].installationState).to.be(apps.ISTATE_ERROR);
|
||||
expect(result[2].installationState).to.be(apps.ISTATE_PENDING_CONFIGURE);
|
||||
assert.equal(result[0].installationState, apps.ISTATE_PENDING_CONFIGURE);
|
||||
assert.equal(result[1].installationState, apps.ISTATE_ERROR);
|
||||
assert.equal(result[2].installationState, apps.ISTATE_PENDING_CONFIGURE);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -420,33 +417,33 @@ describe('Apps', function () {
|
||||
await apps.restoreApps(await apps.list(), { scheduleNow: false }, AuditSource.PLATFORM);
|
||||
|
||||
const result = await apps.list();
|
||||
expect(result[0].installationState).to.be(apps.ISTATE_PENDING_INSTALL);
|
||||
expect(result[1].installationState).to.be(apps.ISTATE_ERROR);
|
||||
expect(result[2].installationState).to.be(apps.ISTATE_PENDING_INSTALL);
|
||||
assert.equal(result[0].installationState, apps.ISTATE_PENDING_INSTALL);
|
||||
assert.equal(result[1].installationState, apps.ISTATE_ERROR);
|
||||
assert.equal(result[2].installationState, apps.ISTATE_PENDING_INSTALL);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseCrontab', function () {
|
||||
it('succeeds for null crontob', function () {
|
||||
expect(apps._parseCrontab(null)).to.eql([]);
|
||||
assert.deepEqual(apps._parseCrontab(null), []);
|
||||
});
|
||||
|
||||
it('succeeds for empty crontob', function () {
|
||||
expect(apps._parseCrontab('')).to.eql([]);
|
||||
assert.deepEqual(apps._parseCrontab(''), []);
|
||||
});
|
||||
|
||||
it('throws for bad crontab', function () {
|
||||
safe(() => apps._parseCrontab('# some comment\n*/1 * * * ')); // incomplete pattern
|
||||
expect(safe.error.message).to.be('Invalid cron configuration at line 2');
|
||||
assert.equal(safe.error.message, 'Invalid cron configuration at line 2');
|
||||
|
||||
safe(() => apps._parseCrontab('* * * * 13 command')); // bad pattern
|
||||
expect(safe.error.message).to.be('Invalid cron pattern at line 1: Field value (13) is out of range');
|
||||
assert.equal(safe.error.message, 'Invalid cron pattern at line 1: Field value (13) is out of range');
|
||||
|
||||
safe(() => apps._parseCrontab('*/1 * * *\t* ')); // no command
|
||||
expect(safe.error.message).to.be('Invalid cron configuration at line 1');
|
||||
assert.equal(safe.error.message, 'Invalid cron configuration at line 1');
|
||||
|
||||
safe(() => apps._parseCrontab('@whatever /bin/false')); // invalid extension
|
||||
expect(safe.error.message).to.be('Unknown extension pattern at line 1');
|
||||
assert.equal(safe.error.message, 'Unknown extension pattern at line 1');
|
||||
});
|
||||
|
||||
it('succeeds for crontab', function () {
|
||||
@@ -455,24 +452,24 @@ describe('Apps', function () {
|
||||
' */1 * * *\t* echo "==> This is a custom cron task running every minute"\n\n' +
|
||||
'00 */1 * * * echo "==> This is a custom cron task running every hour" '); // trailing spaces are trimmed
|
||||
|
||||
expect(result.length).to.be(2);
|
||||
expect(result[0].schedule).to.be('*/1 * * * *');
|
||||
expect(result[0].command).to.be('echo "==> This is a custom cron task running every minute"');
|
||||
assert.equal(result.length, 2);
|
||||
assert.equal(result[0].schedule, '*/1 * * * *');
|
||||
assert.equal(result[0].command, 'echo "==> This is a custom cron task running every minute"');
|
||||
|
||||
expect(result[1].schedule).to.be('00 */1 * * *');
|
||||
expect(result[1].command).to.be('echo "==> This is a custom cron task running every hour"');
|
||||
assert.equal(result[1].schedule, '00 */1 * * *');
|
||||
assert.equal(result[1].command, 'echo "==> This is a custom cron task running every hour"');
|
||||
|
||||
});
|
||||
|
||||
it('succeeds for crontab (extensions)', function () {
|
||||
const result = apps._parseCrontab('@service /bin/service\n\n@weekly /bin/weekly');
|
||||
expect(result.length).to.be(2);
|
||||
assert.equal(result.length, 2);
|
||||
|
||||
expect(result[0].schedule).to.be('@service');
|
||||
expect(result[0].command).to.be('/bin/service');
|
||||
assert.equal(result[0].schedule, '@service');
|
||||
assert.equal(result[0].command, '/bin/service');
|
||||
|
||||
expect(result[1].schedule).to.be('0 0 * * 0');
|
||||
expect(result[1].command).to.be('/bin/weekly');
|
||||
assert.equal(result[1].schedule, '0 0 * * 0');
|
||||
assert.equal(result[1].command, '/bin/weekly');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+10
-13
@@ -1,15 +1,12 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import apptask from '../apptask.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import paths from '../paths.js';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('apptask', function () {
|
||||
const { setup, cleanup, app } = common;
|
||||
@@ -19,19 +16,19 @@ describe('apptask', function () {
|
||||
|
||||
it('create volume', async function () {
|
||||
await apptask._createAppDir(app);
|
||||
expect(fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id)).to.be(true);
|
||||
expect(fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id + '/data')).to.be(false);
|
||||
assert.equal(fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id), true);
|
||||
assert.equal(fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id + '/data'), false);
|
||||
});
|
||||
|
||||
it('delete volume - removeDirectory (false) ', async function () {
|
||||
await apptask._deleteAppDir(app, { removeDirectory: false });
|
||||
expect(fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id)).to.be(true);
|
||||
expect(fs.readdirSync(paths.APPS_DATA_DIR + '/' + app.id).length).to.be(0); // empty
|
||||
assert.equal(fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id), true);
|
||||
assert.equal(fs.readdirSync(paths.APPS_DATA_DIR + '/' + app.id).length, 0); // empty
|
||||
});
|
||||
|
||||
it('delete volume - removeDirectory (true) ', async function () {
|
||||
await apptask._deleteAppDir(app, { removeDirectory: true });
|
||||
expect(!fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id)).to.be(true);
|
||||
assert.equal(!fs.existsSync(paths.APPS_DATA_DIR + '/' + app.id), true);
|
||||
});
|
||||
|
||||
it('barfs on empty manifest', async function () {
|
||||
@@ -39,7 +36,7 @@ describe('apptask', function () {
|
||||
badApp.manifest = { };
|
||||
|
||||
const [error] = await safe(apptask._verifyManifest(badApp.manifest));
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
});
|
||||
|
||||
it('fails on bad manifest', async function () {
|
||||
@@ -48,7 +45,7 @@ describe('apptask', function () {
|
||||
delete badApp.manifest.httpPort;
|
||||
|
||||
const [error] = await safe(apptask._verifyManifest(badApp.manifest));
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
});
|
||||
|
||||
it('barfs on incompatible manifest', async function () {
|
||||
@@ -57,7 +54,7 @@ describe('apptask', function () {
|
||||
badApp.manifest.maxBoxVersion = '0.0.0'; // max box version is too small
|
||||
|
||||
const [error] = await safe(apptask._verifyManifest(badApp.manifest));
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
});
|
||||
|
||||
it('verifies manifest', async function () {
|
||||
|
||||
+12
-15
@@ -1,15 +1,12 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import archives from '../archives.js';
|
||||
import backups from '../backups.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Archives', function () {
|
||||
const { setup, cleanup, auditSource, getDefaultBackupSite } = common;
|
||||
@@ -41,7 +38,7 @@ describe('Archives', function () {
|
||||
|
||||
it('cannot add bad backup to archives', async function () {
|
||||
const [error] = await safe(archives.add('badId', {}, auditSource));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('can add good backup to archives', async function () {
|
||||
@@ -50,35 +47,35 @@ describe('Archives', function () {
|
||||
|
||||
it('cannot get invalid archive', async function () {
|
||||
const result = await archives.get('bad');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('can get archive', async function () {
|
||||
const result = await archives.get(archiveId);
|
||||
expect(result.appConfig).to.eql(appBackup.appConfig);
|
||||
assert.deepEqual(result.appConfig, appBackup.appConfig);
|
||||
});
|
||||
|
||||
it('can list archives', async function () {
|
||||
const result = await archives.list(1, 100);
|
||||
expect(result.length).to.be(1);
|
||||
expect(result[0].id).to.be(archiveId);
|
||||
expect(result[0].appConfig).to.eql(appBackup.appConfig);
|
||||
assert.equal(result.length, 1);
|
||||
assert.equal(result[0].id, archiveId);
|
||||
assert.deepEqual(result[0].appConfig, appBackup.appConfig);
|
||||
});
|
||||
|
||||
it('can list backupIds', async function () {
|
||||
const result = await archives.listBackupIds();
|
||||
expect(result.length).to.be(1);
|
||||
expect(result[0]).to.be(appBackup.id);
|
||||
assert.equal(result.length, 1);
|
||||
assert.equal(result[0], appBackup.id);
|
||||
});
|
||||
|
||||
it('cannot delete bad archive', async function () {
|
||||
const [error] = await safe(archives.del({ id: 'badId' }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('can del valid archive', async function () {
|
||||
await archives.del({ id: archiveId }, auditSource);
|
||||
const result = await archives.list(1, 10);
|
||||
expect(result.length).to.be(0);
|
||||
assert.equal(result.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import archives from '../archives.js';
|
||||
@@ -5,15 +6,11 @@ import backupCleaner from '../backupcleaner.js';
|
||||
import backups from '../backups.js';
|
||||
import backupSites from '../backupsites.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import moment from 'moment';
|
||||
import tasks from '../tasks.js';
|
||||
import timers from 'timers/promises';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('backup cleaner', function () {
|
||||
const { setup, cleanup, app, getDefaultBackupSite, auditSource } = common;
|
||||
@@ -39,25 +36,25 @@ describe('backup cleaner', function () {
|
||||
it('keeps latest', function () {
|
||||
const backup = Object.assign({}, backupTemplate, { creationTime: moment().subtract(5, 's').toDate(), state: backups.BACKUP_STATE_NORMAL });
|
||||
backupCleaner._applyBackupRetention([backup], { keepWithinSecs: 1, keepLatest: true }, []);
|
||||
expect(backup.keepReason).to.be('latest');
|
||||
assert.equal(backup.keepReason, 'latest');
|
||||
});
|
||||
|
||||
it('does not keep latest', function () {
|
||||
const backup = { creationTime: moment().subtract(5, 's').toDate(), state: backups.BACKUP_STATE_NORMAL };
|
||||
backupCleaner._applyBackupRetention([backup], { keepWithinSecs: 1, keepLatest: false }, []);
|
||||
expect(backup.keepReason).to.be(undefined);
|
||||
assert.equal(backup.keepReason, undefined);
|
||||
});
|
||||
|
||||
it('always keeps forever policy', function () {
|
||||
const backup = { creationTime: new Date() };
|
||||
backupCleaner._applyBackupRetention([backup], { keepWithinSecs: -1, keepLatest: true }, []);
|
||||
expect(backup.keepReason).to.be('keepWithinSecs');
|
||||
assert.equal(backup.keepReason, 'keepWithinSecs');
|
||||
});
|
||||
|
||||
it('preserveSecs takes precedence', function () {
|
||||
const backup = { creationTime: new Date(), preserveSecs: 3000 };
|
||||
backupCleaner._applyBackupRetention([backup], { keepWithinSecs: 1, keepLatest: true }, []);
|
||||
expect(backup.keepReason).to.be('preserveSecs');
|
||||
assert.equal(backup.keepReason, 'preserveSecs');
|
||||
});
|
||||
|
||||
it('1 daily', function () {
|
||||
@@ -69,11 +66,11 @@ describe('backup cleaner', function () {
|
||||
{ id: '4', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(5, 'd').toDate() }
|
||||
];
|
||||
backupCleaner._applyBackupRetention(b, { keepDaily: 1, keepLatest: true }, []);
|
||||
expect(b[0].keepReason).to.be('keepDaily');
|
||||
expect(b[1].keepReason).to.be(undefined);
|
||||
expect(b[2].keepReason).to.be(undefined);
|
||||
expect(b[3].keepReason).to.be(undefined);
|
||||
expect(b[3].keepReason).to.be(undefined);
|
||||
assert.equal(b[0].keepReason, 'keepDaily');
|
||||
assert.equal(b[1].keepReason, undefined);
|
||||
assert.equal(b[2].keepReason, undefined);
|
||||
assert.equal(b[3].keepReason, undefined);
|
||||
assert.equal(b[3].keepReason, undefined);
|
||||
});
|
||||
|
||||
// if you are debugging this test, it's because of some timezone issue with all the hour substraction!
|
||||
@@ -88,13 +85,13 @@ describe('backup cleaner', function () {
|
||||
{ id: '6', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(5, 'd').toDate() }
|
||||
];
|
||||
backupCleaner._applyBackupRetention(b, { keepDaily: 2, keepWeekly: 1, keepLatest: false }, []);
|
||||
expect(b[0].keepReason).to.be('keepDaily'); // today
|
||||
expect(b[1].keepReason).to.be('keepWeekly'); // today
|
||||
expect(b[2].keepReason).to.be(undefined);
|
||||
expect(b[3].keepReason).to.be('keepDaily'); // yesterday
|
||||
expect(b[4].discardReason).to.be('error'); // errored
|
||||
expect(b[5].discardReason).to.be('creating-too-long'); // creating for too long
|
||||
expect(b[6].keepReason).to.be(undefined); // outside retention policy
|
||||
assert.equal(b[0].keepReason, 'keepDaily'); // today
|
||||
assert.equal(b[1].keepReason, 'keepWeekly'); // today
|
||||
assert.equal(b[2].keepReason, undefined);
|
||||
assert.equal(b[3].keepReason, 'keepDaily'); // yesterday
|
||||
assert.equal(b[4].discardReason, 'error'); // errored
|
||||
assert.equal(b[5].discardReason, 'creating-too-long'); // creating for too long
|
||||
assert.equal(b[6].keepReason, undefined); // outside retention policy
|
||||
});
|
||||
|
||||
it('2 daily, 3 monthly, 1 yearly', function () {
|
||||
@@ -111,16 +108,16 @@ describe('backup cleaner', function () {
|
||||
{ id: '9', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(97, 'd').toDate() },
|
||||
];
|
||||
backupCleaner._applyBackupRetention(b, { keepDaily: 2, keepMonthly: 3, keepYearly: 1, keepLatest: true }, []);
|
||||
expect(b[0].keepReason).to.be('creating');
|
||||
expect(b[1].discardReason).to.be('error'); // errored
|
||||
expect(b[2].keepReason).to.be('keepDaily');
|
||||
expect(b[3].keepReason).to.be('keepMonthly');
|
||||
expect(b[4].keepReason).to.be('keepYearly');
|
||||
expect(b[5].keepReason).to.be('keepDaily'); // yesterday
|
||||
expect(b[6].discardReason).to.be('creating-too-long'); // errored
|
||||
expect(b[7].keepReason).to.be('keepMonthly');
|
||||
expect(b[8].keepReason).to.be('keepMonthly');
|
||||
expect(b[9].keepReason).to.be(undefined);
|
||||
assert.equal(b[0].keepReason, 'creating');
|
||||
assert.equal(b[1].discardReason, 'error'); // errored
|
||||
assert.equal(b[2].keepReason, 'keepDaily');
|
||||
assert.equal(b[3].keepReason, 'keepMonthly');
|
||||
assert.equal(b[4].keepReason, 'keepYearly');
|
||||
assert.equal(b[5].keepReason, 'keepDaily'); // yesterday
|
||||
assert.equal(b[6].discardReason, 'creating-too-long'); // errored
|
||||
assert.equal(b[7].keepReason, 'keepMonthly');
|
||||
assert.equal(b[8].keepReason, 'keepMonthly');
|
||||
assert.equal(b[9].keepReason, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -288,23 +285,23 @@ describe('backup cleaner', function () {
|
||||
await cleanupBackups(site);
|
||||
|
||||
const results = await backups.listByTypePaged(backups.BACKUP_TYPE_BOX, site.id, 1, 1000);
|
||||
expect(results.length).to.equal(1);
|
||||
expect(results[0].id).to.equal(BACKUP_1_BOX.id);
|
||||
assert.equal(results.length, 1);
|
||||
assert.equal(results[0].id, BACKUP_1_BOX.id);
|
||||
|
||||
// check that app backups are gone as well. only backup_1 will remain
|
||||
const result = await backups.get(BACKUP_0_APP_0.id);
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('does not remove expired backups if only one left', async function () {
|
||||
await cleanupBackups(site);
|
||||
|
||||
const results = await backups.listByTypePaged(backups.BACKUP_TYPE_BOX, site.id, 1, 1000);
|
||||
expect(results[0].id).to.equal(BACKUP_1_BOX.id);
|
||||
assert.equal(results[0].id, BACKUP_1_BOX.id);
|
||||
|
||||
// check that app backups are also still there. backup_1 is still there
|
||||
const result = await backups.get(BACKUP_1_APP_0.id);
|
||||
expect(result.id).to.equal(BACKUP_1_APP_0.id);
|
||||
assert.equal(result.id, BACKUP_1_APP_0.id);
|
||||
});
|
||||
|
||||
it('succeeds for app backups not referenced by a box backup', async function () {
|
||||
@@ -318,12 +315,12 @@ describe('backup cleaner', function () {
|
||||
await cleanupBackups(site);
|
||||
|
||||
let result = await backups.listByTypePaged(backups.BACKUP_TYPE_APP, site.id, 1, 1000);
|
||||
expect(result.length).to.equal(4);
|
||||
assert.equal(result.length, 4);
|
||||
result = result.sort((r1, r2) => r1.remotePath.localeCompare(r2.remotePath));
|
||||
expect(result[0].id).to.be(BACKUP_0_APP_0.id); // because app is installed, latest backup is preserved
|
||||
expect(result[1].id).to.be(BACKUP_1_APP_0.id); // referenced by box
|
||||
expect(result[2].id).to.be(BACKUP_1_APP_1.id); // referenced by box
|
||||
expect(result[3].id).to.be(BACKUP_2_APP_2.id); // referenced by archive
|
||||
assert.equal(result[0].id, BACKUP_0_APP_0.id); // because app is installed, latest backup is preserved
|
||||
assert.equal(result[1].id, BACKUP_1_APP_0.id); // referenced by box
|
||||
assert.equal(result[2].id, BACKUP_1_APP_1.id); // referenced by box
|
||||
assert.equal(result[3].id, BACKUP_2_APP_2.id); // referenced by archive
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import common from './common.js';
|
||||
import DataLayout from '../datalayout.js';
|
||||
import tgz from '../backupformat/tgz.js';
|
||||
const EnsureFileSizeStream = tgz._EnsureFileSizeStream;
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
@@ -12,10 +13,6 @@ import rsync from '../backupformat/rsync.js';
|
||||
import safe from 'safetydance';
|
||||
import stream from 'node:stream/promises';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('backuptask', function () {
|
||||
const { setup, cleanup, createTree } = common;
|
||||
@@ -38,9 +35,9 @@ describe('backuptask', function () {
|
||||
const ins = fs.createReadStream(`/tmp/${name}`);
|
||||
const outs = fs.createWriteStream('/tmp/out.txt');
|
||||
const [error] = await safe(stream.pipeline(ins, efs, outs));
|
||||
expect(error).to.be(null);
|
||||
assert.equal(error, null);
|
||||
const out = fs.readFileSync('/tmp/out.txt');
|
||||
expect(out).to.eql(data);
|
||||
assert.deepEqual(out, data);
|
||||
});
|
||||
|
||||
it('overflow', async function () {
|
||||
@@ -48,9 +45,9 @@ describe('backuptask', function () {
|
||||
const ins = fs.createReadStream(`/tmp/${name}`);
|
||||
const outs = fs.createWriteStream('/tmp/out.txt');
|
||||
const [error] = await safe(stream.pipeline(ins, efs, outs));
|
||||
expect(error).to.be(null);
|
||||
assert.equal(error, null);
|
||||
const out = fs.readFileSync('/tmp/out.txt');
|
||||
expect(out).to.eql(data.subarray(0, 20));
|
||||
assert.deepEqual(out, data.subarray(0, 20));
|
||||
});
|
||||
|
||||
it('underflow', async function () {
|
||||
@@ -58,9 +55,9 @@ describe('backuptask', function () {
|
||||
const ins = fs.createReadStream(`/tmp/${name}`);
|
||||
const outs = fs.createWriteStream('/tmp/out.txt');
|
||||
const [error] = await safe(stream.pipeline(ins, efs, outs));
|
||||
expect(error).to.be(null);
|
||||
assert.equal(error, null);
|
||||
const out = fs.readFileSync('/tmp/out.txt');
|
||||
expect(out).to.eql(Buffer.concat([data, Buffer.alloc(8)]));
|
||||
assert.deepEqual(out, Buffer.concat([data, Buffer.alloc(8)]));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -82,24 +79,24 @@ describe('backuptask', function () {
|
||||
await rsync._saveFsMetadata(dataLayout, `${dataLayout.localRoot()}/fsmetadata.json`);
|
||||
|
||||
const emptyDirs = JSON.parse(fs.readFileSync(path.join(tmpdir, 'fsmetadata.json'), 'utf8')).emptyDirs;
|
||||
expect(emptyDirs).to.eql(['./data/subdir/emptydir']);
|
||||
assert.deepEqual(emptyDirs, ['./data/subdir/emptydir']);
|
||||
|
||||
const execFiles = JSON.parse(fs.readFileSync(path.join(tmpdir, 'fsmetadata.json'), 'utf8')).execFiles;
|
||||
expect(execFiles).to.eql(['./dir2/file']);
|
||||
assert.deepEqual(execFiles, ['./dir2/file']);
|
||||
});
|
||||
|
||||
it('restores special files', async function () {
|
||||
fs.rmSync(path.join(tmpdir, 'data'), { recursive: true, force: true });
|
||||
|
||||
expect(fs.existsSync(path.join(tmpdir, 'data/subdir/emptydir'))).to.be(false); // just make sure rimraf worked
|
||||
assert.equal(fs.existsSync(path.join(tmpdir, 'data/subdir/emptydir')), false); // just make sure rimraf worked
|
||||
|
||||
const dataLayout = new DataLayout(tmpdir, []);
|
||||
|
||||
await rsync._restoreFsMetadata(dataLayout, `${dataLayout.localRoot()}/fsmetadata.json`);
|
||||
|
||||
expect(fs.existsSync(path.join(tmpdir, 'data/subdir/emptydir'))).to.be(true);
|
||||
assert.equal(fs.existsSync(path.join(tmpdir, 'data/subdir/emptydir')), true);
|
||||
const mode = fs.statSync(path.join(tmpdir, 'dir2/file')).mode;
|
||||
expect(mode & ~fs.constants.S_IFREG).to.be(parseInt('0755', 8));
|
||||
assert.equal(mode & ~fs.constants.S_IFREG, parseInt('0755', 8));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import backupIntegrity from '../backupintegrity.js';
|
||||
@@ -6,17 +7,13 @@ import backupSites from '../backupsites.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import child_process from 'node:child_process';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import tasks from '../tasks.js';
|
||||
import timers from 'timers/promises';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('backupintegrity', function () {
|
||||
const { setup, cleanup, getDefaultBackupSite, auditSource } = common;
|
||||
@@ -64,11 +61,11 @@ describe('backupintegrity', function () {
|
||||
it('throws for missing backup id', async function () {
|
||||
try {
|
||||
await backupIntegrity.check('nonexistent-id', () => {});
|
||||
expect().fail('expected BoxError');
|
||||
assert.ok().fail('expected BoxError');
|
||||
} catch (err) {
|
||||
expect(err).to.be.a(BoxError);
|
||||
expect(err.reason).to.be(BoxError.BAD_FIELD);
|
||||
expect(err.message).to.contain('Backup not found');
|
||||
assert.ok((err) instanceof (BoxError));
|
||||
assert.equal(err.reason, BoxError.BAD_FIELD);
|
||||
assert.ok(err.message.includes('Backup not found'));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -84,9 +81,9 @@ describe('backupintegrity', function () {
|
||||
await backupIntegrity.check(backup.id, (p) => { progressCalls.push(p); });
|
||||
|
||||
const updated = await backups.get(backup.id);
|
||||
expect(updated.integrityCheckStatus).to.be('passed');
|
||||
expect(updated.integrityCheckResult.messages).to.eql([]);
|
||||
expect(updated.integrityCheckResult.stats).to.be.an('object');
|
||||
assert.equal(updated.integrityCheckStatus, 'passed');
|
||||
assert.deepEqual(updated.integrityCheckResult.messages, []);
|
||||
assert.equal(typeof updated.integrityCheckResult.stats, 'object');
|
||||
});
|
||||
|
||||
it('cleanup', function () {
|
||||
|
||||
+14
-17
@@ -1,15 +1,12 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import backups from '../backups.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('backups', function () {
|
||||
const { setup, cleanup, getDefaultBackupSite } = common;
|
||||
@@ -77,38 +74,38 @@ describe('backups', function () {
|
||||
|
||||
it('fails with duplicate path', async function () {
|
||||
const [error] = await safe(backups.add(boxBackup));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('get succeeds', async function () {
|
||||
const result = await backups.get(boxBackup.id);
|
||||
delete result.creationTime;
|
||||
expect(result).to.eql(boxBackup);
|
||||
assert.deepEqual(result, boxBackup);
|
||||
});
|
||||
|
||||
it('get of unknown id fails', async function () {
|
||||
const result = await backups.get('somerandom');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('listByTypePaged succeeds', async function () {
|
||||
const results = await backups.listByTypePaged(backups.BACKUP_TYPE_BOX, defaultBackupSite.id, 1, 5);
|
||||
expect(results.length).to.be(1);
|
||||
assert.equal(results.length, 1);
|
||||
delete results[0].creationTime;
|
||||
expect(results[0]).to.eql(boxBackup);
|
||||
assert.deepEqual(results[0], boxBackup);
|
||||
});
|
||||
|
||||
it('update succeeds', async function () {
|
||||
await backups.update(boxBackup, { label: 'DuMonde', preserveSecs: 30 });
|
||||
const result = await backups.get(boxBackup.id);
|
||||
expect(result.label).to.eql('DuMonde');
|
||||
expect(result.preserveSecs).to.eql(30);
|
||||
assert.deepEqual(result.label, 'DuMonde');
|
||||
assert.deepEqual(result.preserveSecs, 30);
|
||||
});
|
||||
|
||||
it('delete succeeds', async function () {
|
||||
await backups.del(boxBackup.id);
|
||||
const result = await backups.get(boxBackup.id);
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('add app backup succeeds', async function () {
|
||||
@@ -118,20 +115,20 @@ describe('backups', function () {
|
||||
it('get app backup succeeds', async function () {
|
||||
const result = await backups.get(appBackup.id);
|
||||
delete result.creationTime;
|
||||
expect(result).to.eql(appBackup);
|
||||
assert.deepEqual(result, appBackup);
|
||||
});
|
||||
|
||||
it('listByIdentifierAndStatePaged succeeds', async function () {
|
||||
const results = await backups.listByIdentifierAndStatePaged(appBackup.identifier, backups.BACKUP_STATE_CREATING, 1, 5);
|
||||
expect(results.length).to.be(1);
|
||||
assert.equal(results.length, 1);
|
||||
delete results[0].creationTime;
|
||||
expect(results[0]).to.eql(appBackup);
|
||||
assert.deepEqual(results[0], appBackup);
|
||||
});
|
||||
|
||||
it('delete app backup succeeds', async function () {
|
||||
await backups.del(appBackup.id);
|
||||
const result = await backups.get(appBackup.id);
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import archives from '../archives.js';
|
||||
@@ -6,13 +7,9 @@ import backupSites from '../backupsites.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import constants from '../constants.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('backups', function () {
|
||||
const { setup, cleanup, auditSource, getDefaultBackupSite } = common;
|
||||
@@ -60,28 +57,28 @@ describe('backups', function () {
|
||||
|
||||
it('can add another site', async function () {
|
||||
const id = await backupSites.add(backupSite, auditSource);
|
||||
expect(id).to.be.ok();
|
||||
assert.ok(id);
|
||||
backupSite.id = id;
|
||||
});
|
||||
|
||||
it('can list backup sites', async function () {
|
||||
const result = await backupSites.list();
|
||||
expect(result.length).to.be(2);
|
||||
assert.equal(result.length, 2);
|
||||
});
|
||||
|
||||
it('can get backup site', async function () {
|
||||
const result = await backupSites.get(defaultBackupSite.id);
|
||||
expect(result.provider).to.be('filesystem');
|
||||
expect(result.config.backupDir).to.be.ok(); // the test sets this to some tmp location
|
||||
expect(result.format).to.be('tgz');
|
||||
expect(result.encryption).to.be(null);
|
||||
expect(result.contents).to.be(null);
|
||||
expect(result.enableForUpdates).to.be(true);
|
||||
assert.equal(result.provider, 'filesystem');
|
||||
assert.ok(result.config.backupDir); // the test sets this to some tmp location
|
||||
assert.equal(result.format, 'tgz');
|
||||
assert.equal(result.encryption, null);
|
||||
assert.equal(result.contents, null);
|
||||
assert.equal(result.enableForUpdates, true);
|
||||
});
|
||||
|
||||
it('cannot get random backup site', async function () {
|
||||
const result = await backupSites.get('random');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('can set backup config', async function () {
|
||||
@@ -89,39 +86,39 @@ describe('backups', function () {
|
||||
await backupSites.setConfig(defaultBackupSite, newConfig, auditSource);
|
||||
|
||||
const result = await backupSites.get(defaultBackupSite.id);
|
||||
expect(result.config.backupDir).to.be('/tmp/backups');
|
||||
assert.equal(result.config.backupDir, '/tmp/backups');
|
||||
});
|
||||
|
||||
it('cannot set invalid schedule', async function () {
|
||||
const [error] = await safe(backupSites.setSchedule(defaultBackupSite, '', auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can set valid schedule', async function () {
|
||||
for (const pattern of [ '00 * * * * *', constants.CRON_PATTERN_NEVER ]) {
|
||||
await backupSites.setSchedule(defaultBackupSite, pattern, auditSource);
|
||||
const result = await backupSites.get(defaultBackupSite.id);
|
||||
expect(result.schedule).to.be(pattern);
|
||||
assert.equal(result.schedule, pattern);
|
||||
}
|
||||
});
|
||||
|
||||
it('cannot set invalid retention', async function () {
|
||||
const [error] = await safe(backupSites.setRetention(defaultBackupSite, { keepWhenever: 4 }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can set valid retention', async function () {
|
||||
for (const retention of [ { keepWithinSecs: 1 }, { keepYearly: 3 }, { keepMonthly: 14 } ]) {
|
||||
await backupSites.setRetention(defaultBackupSite, retention, auditSource);
|
||||
const result = await backupSites.get(defaultBackupSite.id);
|
||||
expect(result.retention).to.eql(retention);
|
||||
assert.deepEqual(result.retention, retention);
|
||||
}
|
||||
});
|
||||
|
||||
it('cannot disable for update', async function () {
|
||||
await backupSites.setEnabledForUpdates(defaultBackupSite, false, auditSource);
|
||||
const result = await backupSites.get(defaultBackupSite.id);
|
||||
expect(result.enableForUpdates).to.eql(false);
|
||||
assert.deepEqual(result.enableForUpdates, false);
|
||||
});
|
||||
|
||||
it('can delete all the backup sites', async function () {
|
||||
@@ -129,8 +126,8 @@ describe('backups', function () {
|
||||
backupSite.integrityKeyPair = {}; // keep removePrivateFields happy
|
||||
await backupSites.del(backupSite, auditSource);
|
||||
|
||||
expect(await backups.listByTypePaged(backups.BACKUP_TYPE_BOX, defaultBackupSite.id, 1, 10)).to.eql([]);
|
||||
expect(await archives.list(1, 10)).to.eql([]);
|
||||
expect(await backupSites.list()).to.eql([]);
|
||||
assert.deepEqual(await backups.listByTypePaged(backups.BACKUP_TYPE_BOX, defaultBackupSite.id, 1, 10), []);
|
||||
assert.deepEqual(await archives.list(1, 10), []);
|
||||
assert.deepEqual(await backupSites.list(), []);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import backups from '../backups.js';
|
||||
import backupSites from '../backupsites.js';
|
||||
import child_process from 'node:child_process';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import tasks from '../tasks.js';
|
||||
import timers from 'timers/promises';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('backuptask', function () {
|
||||
const { setup, cleanup, getDefaultBackupSite, auditSource } = common;
|
||||
@@ -69,8 +66,8 @@ describe('backuptask', function () {
|
||||
}
|
||||
|
||||
const result = await createBackup(defaultBackupSite);
|
||||
expect(fs.statSync(path.join(backupConfig.backupDir, 'snapshot/box.tar.gz')).nlink).to.be(2); // hard linked to a rotated backup
|
||||
expect(fs.statSync(path.join(backupConfig.backupDir, result.remotePath)).nlink).to.be(2);
|
||||
assert.equal(fs.statSync(path.join(backupConfig.backupDir, 'snapshot/box.tar.gz')).nlink, 2); // hard linked to a rotated backup
|
||||
assert.equal(fs.statSync(path.join(backupConfig.backupDir, result.remotePath)).nlink, 2);
|
||||
|
||||
backupInfo1 = result;
|
||||
});
|
||||
@@ -83,9 +80,9 @@ describe('backuptask', function () {
|
||||
}
|
||||
|
||||
const result = await createBackup(defaultBackupSite);
|
||||
expect(fs.statSync(path.join(backupConfig.backupDir, 'snapshot/box.tar.gz')).nlink).to.be(2); // hard linked to a rotated backup
|
||||
expect(fs.statSync(path.join(backupConfig.backupDir, result.remotePath)).nlink).to.be(2); // hard linked to new backup
|
||||
expect(fs.statSync(path.join(backupConfig.backupDir, backupInfo1.remotePath)).nlink).to.be(1); // not hard linked anymore
|
||||
assert.equal(fs.statSync(path.join(backupConfig.backupDir, 'snapshot/box.tar.gz')).nlink, 2); // hard linked to a rotated backup
|
||||
assert.equal(fs.statSync(path.join(backupConfig.backupDir, result.remotePath)).nlink, 2); // hard linked to new backup
|
||||
assert.equal(fs.statSync(path.join(backupConfig.backupDir, backupInfo1.remotePath)).nlink, 1); // not hard linked anymore
|
||||
});
|
||||
|
||||
it('cleanup', function () {
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import blobs from '../blobs.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('blobs', function () {
|
||||
const { setup, cleanup } = common;
|
||||
@@ -19,17 +16,17 @@ describe('blobs', function () {
|
||||
});
|
||||
it('can get the set value', async function () {
|
||||
const value = await blobs.get('someid');
|
||||
expect(value).to.eql(Buffer.from('somevalue'));
|
||||
assert.deepEqual(value, Buffer.from('somevalue'));
|
||||
});
|
||||
it('can update a value', async function () {
|
||||
await blobs.set('someid', Buffer.from('someothervalue'));
|
||||
});
|
||||
it('can get updated value', async function () {
|
||||
const value = await blobs.get('someid');
|
||||
expect(value).to.eql(Buffer.from('someothervalue'));
|
||||
assert.deepEqual(value, Buffer.from('someothervalue'));
|
||||
});
|
||||
it('cannot get randome value', async function () {
|
||||
const value = await blobs.get('unknownid');
|
||||
expect(value).to.be(null);
|
||||
assert.equal(value, null);
|
||||
});
|
||||
});
|
||||
|
||||
+10
-13
@@ -1,14 +1,11 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import branding from '../branding.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Branding', function () {
|
||||
const { setup, cleanup, auditSource } = common;
|
||||
@@ -18,42 +15,42 @@ describe('Branding', function () {
|
||||
|
||||
it ('can get default cloudron name', async function () {
|
||||
const name = await branding.getCloudronName();
|
||||
expect(name).to.be('Cloudron');
|
||||
assert.equal(name, 'Cloudron');
|
||||
});
|
||||
|
||||
it('can set name', async function () {
|
||||
await branding.setCloudronName('Dolomites', auditSource);
|
||||
const name = await branding.getCloudronName();
|
||||
expect(name).to.be('Dolomites');
|
||||
assert.equal(name, 'Dolomites');
|
||||
});
|
||||
|
||||
it('can set emoji in name', async function () {
|
||||
await branding.setCloudronName('🎊 Cloudron 🎉', auditSource);
|
||||
const name = await branding.getCloudronName();
|
||||
expect(name).to.be('🎊 Cloudron 🎉');
|
||||
assert.equal(name, '🎊 Cloudron 🎉');
|
||||
});
|
||||
|
||||
it('cannot set large name', async function () {
|
||||
const [error] = await safe(branding.setCloudronName('x'.repeat(65), auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can get default cloudron avatar', async function () {
|
||||
const avatar = await branding.getCloudronAvatar();
|
||||
expect(avatar).to.be.a(Buffer);
|
||||
assert.ok((avatar) instanceof (Buffer));
|
||||
});
|
||||
|
||||
it('can render default footer', async function () {
|
||||
expect(await branding.renderFooter()).to.contain('(https://cloudron.io)');
|
||||
assert.ok((await branding.renderFooter()).includes('(https://cloudron.io)'));
|
||||
});
|
||||
|
||||
it('can render footer', async function () {
|
||||
await branding.setFooter('BigFoot Inc', auditSource);
|
||||
expect(await branding.renderFooter()).to.be('BigFoot Inc');
|
||||
assert.equal(await branding.renderFooter(), 'BigFoot Inc');
|
||||
});
|
||||
|
||||
it('can render footer with YEAR', async function () {
|
||||
await branding.setFooter('BigFoot Inc %YEAR%', auditSource);
|
||||
expect(await branding.renderFooter()).to.be('BigFoot Inc 2026');
|
||||
assert.equal(await branding.renderFooter(), 'BigFoot Inc 2026');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import cloudron from '../cloudron.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Cloudron', function () {
|
||||
const { setup, cleanup } = common;
|
||||
@@ -19,36 +16,36 @@ describe('Cloudron', function () {
|
||||
describe('timezone', function () {
|
||||
it('can get default timezone', async function () {
|
||||
const tz = await cloudron.getTimeZone();
|
||||
expect(tz).to.be('UTC');
|
||||
assert.equal(tz, 'UTC');
|
||||
});
|
||||
|
||||
it('cannot set invalid timezone', async function () {
|
||||
const [error] = await safe(cloudron.setTimeZone('OMG'));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can set valid timezone', async function () {
|
||||
await cloudron.setTimeZone('Africa/Johannesburg');
|
||||
const tz = await cloudron.getTimeZone();
|
||||
expect(tz).to.be('Africa/Johannesburg');
|
||||
assert.equal(tz, 'Africa/Johannesburg');
|
||||
});
|
||||
});
|
||||
|
||||
describe('language', function () {
|
||||
it('can get default language', async function () {
|
||||
const lang = await cloudron.getLanguage();
|
||||
expect(lang).to.be('en');
|
||||
assert.equal(lang, 'en');
|
||||
});
|
||||
|
||||
it('cannot set invalid language', async function () {
|
||||
const [error] = await safe(cloudron.setLanguage('ta'));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot set valid language', async function () {
|
||||
await cloudron.setLanguage('de');
|
||||
const lang = await cloudron.getLanguage();
|
||||
expect(lang).to.be('de');
|
||||
assert.equal(lang, 'de');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import cron from '../cron.js';
|
||||
import dashboard from '../dashboard.js';
|
||||
import database from '../database.js';
|
||||
import domains from '../domains.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import locks from '../locks.js';
|
||||
import mailer from '../mailer.js';
|
||||
@@ -238,7 +238,7 @@ function clearMailQueue() {
|
||||
|
||||
async function checkMails(number) {
|
||||
await timers.setTimeout(1000);
|
||||
expect(mailer._mailQueue.length).to.equal(number);
|
||||
assert.equal(mailer._mailQueue.length, number);
|
||||
const emails = [...mailer._mailQueue]; // copy before clearing
|
||||
clearMailQueue();
|
||||
|
||||
|
||||
+10
-10
@@ -1,8 +1,8 @@
|
||||
/* global it, describe, before, after */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import database from '../database.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
|
||||
describe('database', function () {
|
||||
@@ -26,7 +26,7 @@ describe('database', function () {
|
||||
|
||||
it('basic query', async function () {
|
||||
const result = await database.query('SELECT COUNT(*) as count FROM apps');
|
||||
expect(result[0].count).to.be(0);
|
||||
assert.equal(result[0].count, 0);
|
||||
});
|
||||
|
||||
it('bad queries', async function () {
|
||||
@@ -37,8 +37,8 @@ describe('database', function () {
|
||||
|
||||
for (const query of queries) {
|
||||
const [error] = await safe(database.query(query));
|
||||
expect(error.reason).to.be(BoxError.DATABASE_ERROR);
|
||||
expect(error.sqlMessage).to.be.a('string');
|
||||
assert.equal(error.reason, BoxError.DATABASE_ERROR);
|
||||
assert.equal(typeof error.sqlMessage, 'string');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -52,8 +52,8 @@ describe('database', function () {
|
||||
{ query: 'SELECT COUNT(*) as count FROM apps', args: [] },
|
||||
{ query: 'SELECT COUNT(*) as count FROM settings', args: [] },
|
||||
]);
|
||||
expect(results[0][0].count).to.be(0);
|
||||
expect(results[1][0].count).to.be(0);
|
||||
assert.equal(results[0][0].count, 0);
|
||||
assert.equal(results[1][0].count, 0);
|
||||
});
|
||||
|
||||
it('bad transaction', async function () {
|
||||
@@ -62,8 +62,8 @@ describe('database', function () {
|
||||
{ query: 'stuff', args: [] },
|
||||
]));
|
||||
|
||||
expect(error.reason).to.be(BoxError.DATABASE_ERROR);
|
||||
expect(error.sqlMessage).to.be.a('string');
|
||||
assert.equal(error.reason, BoxError.DATABASE_ERROR);
|
||||
assert.equal(typeof error.sqlMessage, 'string');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -75,7 +75,7 @@ describe('database', function () {
|
||||
|
||||
it('cannot import from non-existent file', async function () {
|
||||
const [error] = await safe(database.importFromFile('/does/not/exist'));
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
});
|
||||
|
||||
it('can export to file', async function () {
|
||||
|
||||
+29
-30
@@ -1,9 +1,8 @@
|
||||
/* global it:false */
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
import DataLayout from '../datalayout.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
/* global describe:false */
|
||||
|
||||
describe('DataLayout', function () {
|
||||
describe('no dirMap', function () {
|
||||
@@ -11,28 +10,28 @@ describe('DataLayout', function () {
|
||||
const dataLayout = new DataLayout(BOX_DATA_DIR, []);
|
||||
|
||||
it('localRoot', function () {
|
||||
expect(dataLayout.localRoot()).to.be(BOX_DATA_DIR);
|
||||
assert.equal(dataLayout.localRoot(), BOX_DATA_DIR);
|
||||
});
|
||||
|
||||
it('getBasename', function () {
|
||||
expect(dataLayout.getBasename()).to.be('box');
|
||||
assert.equal(dataLayout.getBasename(), 'box');
|
||||
});
|
||||
|
||||
it('localPaths', function () {
|
||||
expect(dataLayout.localPaths()).to.eql([ BOX_DATA_DIR ]);
|
||||
assert.deepEqual(dataLayout.localPaths(), [ BOX_DATA_DIR ]);
|
||||
});
|
||||
|
||||
it('toLocalPath', function () {
|
||||
expect(dataLayout.toLocalPath('./s1')).to.be(`${BOX_DATA_DIR}/s1`);
|
||||
expect(dataLayout.toLocalPath('./s1/')).to.be(`${BOX_DATA_DIR}/s1/`);
|
||||
expect(dataLayout.toLocalPath('./s1/s2')).to.be(`${BOX_DATA_DIR}/s1/s2`);
|
||||
assert.equal(dataLayout.toLocalPath('./s1'), `${BOX_DATA_DIR}/s1`);
|
||||
assert.equal(dataLayout.toLocalPath('./s1/'), `${BOX_DATA_DIR}/s1/`);
|
||||
assert.equal(dataLayout.toLocalPath('./s1/s2'), `${BOX_DATA_DIR}/s1/s2`);
|
||||
});
|
||||
|
||||
it('toRemotePath', function () {
|
||||
expect(dataLayout.toRemotePath(`${BOX_DATA_DIR}`)).to.be('./');
|
||||
expect(dataLayout.toRemotePath(`${BOX_DATA_DIR}/s1`)).to.be('./s1');
|
||||
expect(dataLayout.toRemotePath(`${BOX_DATA_DIR}/s1/`)).to.be('./s1/');
|
||||
expect(dataLayout.toRemotePath(`${BOX_DATA_DIR}/s1/s2`)).to.be('./s1/s2');
|
||||
assert.equal(dataLayout.toRemotePath(`${BOX_DATA_DIR}`), './');
|
||||
assert.equal(dataLayout.toRemotePath(`${BOX_DATA_DIR}/s1`), './s1');
|
||||
assert.equal(dataLayout.toRemotePath(`${BOX_DATA_DIR}/s1/`), './s1/');
|
||||
assert.equal(dataLayout.toRemotePath(`${BOX_DATA_DIR}/s1/s2`), './s1/s2');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -42,41 +41,41 @@ describe('DataLayout', function () {
|
||||
const dataLayout = new DataLayout(APP_DATA_DIR, [ { localDir: EXT_DIR, remoteDir: 'data' }]);
|
||||
|
||||
it('localRoot', function () {
|
||||
expect(dataLayout.localRoot()).to.be(APP_DATA_DIR);
|
||||
assert.equal(dataLayout.localRoot(), APP_DATA_DIR);
|
||||
});
|
||||
|
||||
it('getBasename', function () {
|
||||
expect(dataLayout.getBasename()).to.be('appid');
|
||||
assert.equal(dataLayout.getBasename(), 'appid');
|
||||
});
|
||||
|
||||
it('localPaths', function () {
|
||||
expect(dataLayout.localPaths()).to.eql([ APP_DATA_DIR, '/srv/hsb' ]);
|
||||
assert.deepEqual(dataLayout.localPaths(), [ APP_DATA_DIR, '/srv/hsb' ]);
|
||||
});
|
||||
|
||||
it('toLocalPath - root', function () {
|
||||
expect(dataLayout.toLocalPath('./s1')).to.be(`${APP_DATA_DIR}/s1`);
|
||||
expect(dataLayout.toLocalPath('./s1/')).to.be(`${APP_DATA_DIR}/s1/`);
|
||||
expect(dataLayout.toLocalPath('./s1/s2')).to.be(`${APP_DATA_DIR}/s1/s2`);
|
||||
assert.equal(dataLayout.toLocalPath('./s1'), `${APP_DATA_DIR}/s1`);
|
||||
assert.equal(dataLayout.toLocalPath('./s1/'), `${APP_DATA_DIR}/s1/`);
|
||||
assert.equal(dataLayout.toLocalPath('./s1/s2'), `${APP_DATA_DIR}/s1/s2`);
|
||||
});
|
||||
|
||||
it('toLocalPath - extdir', function () {
|
||||
expect(dataLayout.toLocalPath('./data/s1')).to.be(`${EXT_DIR}/s1`);
|
||||
expect(dataLayout.toLocalPath('./data/s1/')).to.be(`${EXT_DIR}/s1/`);
|
||||
expect(dataLayout.toLocalPath('./data/s1/s2')).to.be(`${EXT_DIR}/s1/s2`);
|
||||
assert.equal(dataLayout.toLocalPath('./data/s1'), `${EXT_DIR}/s1`);
|
||||
assert.equal(dataLayout.toLocalPath('./data/s1/'), `${EXT_DIR}/s1/`);
|
||||
assert.equal(dataLayout.toLocalPath('./data/s1/s2'), `${EXT_DIR}/s1/s2`);
|
||||
});
|
||||
|
||||
it('toRemotePath - root', function () {
|
||||
expect(dataLayout.toRemotePath(`${APP_DATA_DIR}`)).to.be('./');
|
||||
expect(dataLayout.toRemotePath(`${APP_DATA_DIR}/s1`)).to.be('./s1');
|
||||
expect(dataLayout.toRemotePath(`${APP_DATA_DIR}/s1/`)).to.be('./s1/');
|
||||
expect(dataLayout.toRemotePath(`${APP_DATA_DIR}/s1/s2`)).to.be('./s1/s2');
|
||||
assert.equal(dataLayout.toRemotePath(`${APP_DATA_DIR}`), './');
|
||||
assert.equal(dataLayout.toRemotePath(`${APP_DATA_DIR}/s1`), './s1');
|
||||
assert.equal(dataLayout.toRemotePath(`${APP_DATA_DIR}/s1/`), './s1/');
|
||||
assert.equal(dataLayout.toRemotePath(`${APP_DATA_DIR}/s1/s2`), './s1/s2');
|
||||
});
|
||||
|
||||
it('toRemotePath - extdir', function () {
|
||||
expect(dataLayout.toRemotePath(`${EXT_DIR}`)).to.be('./data/');
|
||||
expect(dataLayout.toRemotePath(`${EXT_DIR}/s1`)).to.be('./data/s1');
|
||||
expect(dataLayout.toRemotePath(`${EXT_DIR}/s1/`)).to.be('./data/s1/');
|
||||
expect(dataLayout.toRemotePath(`${EXT_DIR}/s1/s2`)).to.be('./data/s1/s2');
|
||||
assert.equal(dataLayout.toRemotePath(`${EXT_DIR}`), './data/');
|
||||
assert.equal(dataLayout.toRemotePath(`${EXT_DIR}/s1`), './data/s1');
|
||||
assert.equal(dataLayout.toRemotePath(`${EXT_DIR}/s1/`), './data/s1/');
|
||||
assert.equal(dataLayout.toRemotePath(`${EXT_DIR}/s1/s2`), './data/s1/s2');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+6
-9
@@ -1,14 +1,11 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import child_process from 'node:child_process';
|
||||
import common from './common.js';
|
||||
import df from '../df.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('df', function () {
|
||||
const { setup, cleanup } = common;
|
||||
@@ -21,8 +18,8 @@ describe('df', function () {
|
||||
if (child_process.execSync('uname -a').toString().indexOf('-arch') !== -1) return;
|
||||
|
||||
const disks = await df.filesystems();
|
||||
expect(disks).to.be.ok();
|
||||
expect(disks.some(d => d.mountpoint === '/')).to.be.ok();
|
||||
assert.ok(disks);
|
||||
assert.ok(disks.some(d => d.mountpoint === '/'));
|
||||
});
|
||||
|
||||
it('can get file', async function () {
|
||||
@@ -30,7 +27,7 @@ describe('df', function () {
|
||||
if (child_process.execSync('uname -a').toString().indexOf('-arch') !== -1) return;
|
||||
|
||||
const disks = await df.file(import.meta.dirname);
|
||||
expect(disks).to.be.ok();
|
||||
expect(disks.mountpoint).to.be('/home');
|
||||
assert.ok(disks);
|
||||
assert.equal(disks.mountpoint, '/home');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import async from 'async';
|
||||
import common from './common.js';
|
||||
import constants from '../constants.js';
|
||||
import directoryServer from '../directoryserver.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import groups from '../groups.js';
|
||||
import ldap from 'ldapjs';
|
||||
import safe from 'safetydance';
|
||||
import speakeasy from 'speakeasy';
|
||||
import users from '../users.js';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
async function ldapBind(dn, password) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -78,8 +75,8 @@ describe('Directory Server (LDAP)', function () {
|
||||
secret: 'ldapsecret'
|
||||
};
|
||||
|
||||
before(function (done) {
|
||||
async.series([
|
||||
before(async function () {
|
||||
await async.series([
|
||||
setup,
|
||||
directoryServer.start.bind(null),
|
||||
directoryServer.setConfig.bind(null, { enabled: true, secret: auth.secret, allowlist: '127.0.0.1' }, auditSource),
|
||||
@@ -91,14 +88,14 @@ describe('Directory Server (LDAP)', function () {
|
||||
group2 = await groups.add({ name: 'ldap-test-2' }, auditSource);
|
||||
await groups.setMembers(group2, [ admin.id ], {}, auditSource);
|
||||
}
|
||||
], done);
|
||||
]);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
async.series([
|
||||
after(async function () {
|
||||
await async.series([
|
||||
directoryServer.stop,
|
||||
cleanup
|
||||
], done);
|
||||
]);
|
||||
});
|
||||
|
||||
describe('user bind', function () {
|
||||
@@ -106,12 +103,12 @@ describe('Directory Server (LDAP)', function () {
|
||||
|
||||
it('cn= fails for nonexisting user', async function () {
|
||||
const [error] = await safe(ldapBind('cn=doesnotexist,ou=users,dc=cloudron', 'password'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('cn= fails with wrong password', async function () {
|
||||
const [error] = await safe(ldapBind(`cn=${admin.id},ou=users,dc=cloudron`, 'wrongpassword'));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
});
|
||||
|
||||
it('cn= succeeds with id', async function () {
|
||||
@@ -128,7 +125,7 @@ describe('Directory Server (LDAP)', function () {
|
||||
|
||||
it('mail= fails with bad email', async function () {
|
||||
const [error] = await safe(ldapBind('mail=random,ou=users,dc=cloudron', admin.password));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('mail= succeeds with email', async function () {
|
||||
@@ -147,8 +144,8 @@ describe('Directory Server (LDAP)', function () {
|
||||
|
||||
it('totp check not requested - fails with bad password', async function () {
|
||||
const [error] = await safe(ldapBind(`cn=${admin.id},ou=users,dc=cloudron`, admin.password + 'random'));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
expect(error.lde_message).to.be('Wrong password');
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
assert.equal(error.lde_message, 'Wrong password');
|
||||
});
|
||||
|
||||
it('totp check not requested - succeeds with good password', async function () {
|
||||
@@ -157,8 +154,8 @@ describe('Directory Server (LDAP)', function () {
|
||||
|
||||
it('totp check requested - fails with empty 2fa if user has 2fa', async function () {
|
||||
const [error] = await safe(ldapBind(`cn=${admin.id}+totptoken=,ou=users,dc=cloudron`, admin.password));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
expect(error.lde_message).to.be('A totpToken must be provided');
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
assert.equal(error.lde_message, 'A totpToken must be provided');
|
||||
});
|
||||
|
||||
it('totp check requested - succeeds with empty 2fa if user has no 2fa', async function () {
|
||||
@@ -167,8 +164,8 @@ describe('Directory Server (LDAP)', function () {
|
||||
|
||||
it('totp check requested - fails with invalid 2fa', async function () {
|
||||
const [error] = await safe(ldapBind(`cn=${admin.id}+totptoken=schlecht,ou=users,dc=cloudron`, admin.password));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
expect(error.lde_message).to.be('Invalid totpToken');
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
assert.equal(error.lde_message, 'Invalid totpToken');
|
||||
});
|
||||
|
||||
it('totp check requested - succeeds with invalid 2fa if user has no 2fa', async function () {
|
||||
@@ -178,13 +175,13 @@ describe('Directory Server (LDAP)', function () {
|
||||
it('totp check requested - fails with bad password if user has 2fa', async function () {
|
||||
const totpToken = speakeasy.totp({ secret: twofa.secret, encoding: 'base32' });
|
||||
const [error] = await safe(ldapBind(`cn=${admin.email}+totpToken=${totpToken},ou=users,dc=cloudron`, admin.password + 'random'));
|
||||
expect(error.lde_message).to.be('Wrong password');
|
||||
assert.equal(error.lde_message, 'Wrong password');
|
||||
});
|
||||
|
||||
it('totp check requested - fails with bad password if user has no 2fa', async function () {
|
||||
const totpToken = speakeasy.totp({ secret: twofa.secret, encoding: 'base32' });
|
||||
const [error] = await safe(ldapBind(`cn=${admin.email}+totpToken=${totpToken},ou=users,dc=cloudron`, admin.password + 'random'));
|
||||
expect(error.lde_message).to.be('Wrong password');
|
||||
assert.equal(error.lde_message, 'Wrong password');
|
||||
});
|
||||
|
||||
it('totp check requested - succeeds with valid 2fa', async function () {
|
||||
@@ -196,158 +193,158 @@ describe('Directory Server (LDAP)', function () {
|
||||
describe('search users', function () {
|
||||
it('fails without auth', async function () {
|
||||
const [error] = await safe(ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' }));
|
||||
expect(error).to.be.a(ldap.InsufficientAccessRightsError);
|
||||
assert.ok((error) instanceof (ldap.InsufficientAccessRightsError));
|
||||
});
|
||||
|
||||
it('fails with wrong auth DN', async function () {
|
||||
const [error] = await safe(ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' }, { dn: 'cn=doesnotexist,ou=system,dc=cloudron', secret: 'ldapsecret' }));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
});
|
||||
|
||||
it('fails with wrong auth secret', async function () {
|
||||
const [error] = await safe(ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' }, { dn: 'cn=admin,ou=system,dc=cloudron', secret: 'wrongldapsecret' }));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
});
|
||||
|
||||
it('fails for non existing tree', async function () {
|
||||
const [error] = await safe(ldapSearch('o=example', { filter: '(&(l=Seattle)(email=*@' + domain.domain + '))' }, auth));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('succeeds with basic filter', async function () {
|
||||
const entries = await ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' }, auth);
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
entries.sort(function (a, b) { return a.username > b.username; });
|
||||
expect(entries[0].username).to.equal(admin.username.toLowerCase());
|
||||
expect(entries[0].mail).to.equal(admin.email.toLowerCase());
|
||||
expect(entries[1].username).to.equal(user.username.toLowerCase());
|
||||
expect(entries[1].mail).to.equal(user.email.toLowerCase());
|
||||
assert.equal(entries[0].username, admin.username.toLowerCase());
|
||||
assert.equal(entries[0].mail, admin.email.toLowerCase());
|
||||
assert.equal(entries[1].username, user.username.toLowerCase());
|
||||
assert.equal(entries[1].mail, user.email.toLowerCase());
|
||||
});
|
||||
|
||||
it('succeeds with pagination', async function () {
|
||||
const entries = await ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person', paged: true }, auth);
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
entries.sort(function (a, b) { return a.username > b.username; });
|
||||
expect(entries[0].username).to.equal(admin.username.toLowerCase());
|
||||
expect(entries[0].mail).to.equal(admin.email.toLowerCase());
|
||||
expect(entries[1].username).to.equal(user.username.toLowerCase());
|
||||
expect(entries[1].mail).to.equal(user.email.toLowerCase());
|
||||
assert.equal(entries[0].username, admin.username.toLowerCase());
|
||||
assert.equal(entries[0].mail, admin.email.toLowerCase());
|
||||
assert.equal(entries[1].username, user.username.toLowerCase());
|
||||
assert.equal(entries[1].mail, user.email.toLowerCase());
|
||||
});
|
||||
|
||||
it('succeeds with username wildcard filter', async function () {
|
||||
const entries = await ldapSearch('ou=users,dc=cloudron', { filter: '&(objectcategory=person)(username=*)' }, auth);
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
entries.sort(function (a, b) { return a.username > b.username; });
|
||||
expect(entries[0].username).to.equal(admin.username.toLowerCase());
|
||||
expect(entries[1].username).to.equal(user.username.toLowerCase());
|
||||
assert.equal(entries[0].username, admin.username.toLowerCase());
|
||||
assert.equal(entries[1].username, user.username.toLowerCase());
|
||||
});
|
||||
|
||||
it('succeeds with username filter', async function () {
|
||||
const entries = await ldapSearch('ou=users,dc=cloudron', { filter: '&(objectcategory=person)(username=' + admin.username + ')' }, auth);
|
||||
expect(entries.length).to.equal(1);
|
||||
expect(entries[0].username).to.equal(admin.username.toLowerCase());
|
||||
expect(entries[0].memberof.length).to.equal(2);
|
||||
assert.equal(entries.length, 1);
|
||||
assert.equal(entries[0].username, admin.username.toLowerCase());
|
||||
assert.equal(entries[0].memberof.length, 2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('group search', function () {
|
||||
it('fails without auth', async function () {
|
||||
const [error] = await safe(ldapSearch('ou=groups,dc=cloudron', { filter: 'objectcategory=group' }));
|
||||
expect(error).to.be.a(ldap.InsufficientAccessRightsError);
|
||||
assert.ok((error) instanceof (ldap.InsufficientAccessRightsError));
|
||||
});
|
||||
|
||||
it('fails with wrong auth DN', async function () {
|
||||
const [error] = await safe(ldapSearch('ou=groups,dc=cloudron', { filter: 'objectcategory=group' }, { dn: 'cn=doesnotexist,ou=system,dc=cloudron', secret: 'ldapsecret' }));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
});
|
||||
|
||||
it('fails with wrong auth secret', async function () {
|
||||
const [error] = await safe(ldapSearch('ou=groups,dc=cloudron', { filter: 'objectcategory=group' }, { dn: 'cn=admin,ou=system,dc=cloudron', secret: 'wrongldapsecret' }));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
});
|
||||
|
||||
it('succeeds with basic filter', async function () {
|
||||
mockApp.accessRestriction = null;
|
||||
|
||||
const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: 'objectclass=group' }, auth);
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
|
||||
// ensure order for testability
|
||||
entries.sort(function (a, b) { return a.cn < b.cn; });
|
||||
|
||||
expect(entries[0].cn).to.equal('ldap-test-1');
|
||||
expect(entries[0].memberuid.length).to.equal(2);
|
||||
expect(entries[0].memberuid).to.contain(admin.id);
|
||||
expect(entries[0].memberuid).to.contain(user.id);
|
||||
expect(entries[0].member).to.contain(`cn=${user.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].uniquemember).to.contain(`cn=${user.id},ou=users,dc=cloudron`);
|
||||
assert.equal(entries[0].cn, 'ldap-test-1');
|
||||
assert.equal(entries[0].memberuid.length, 2);
|
||||
assert.ok(entries[0].memberuid.includes(admin.id));
|
||||
assert.ok(entries[0].memberuid.includes(user.id));
|
||||
assert.ok(entries[0].member.includes(`cn=${user.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].uniquemember.includes(`cn=${user.id},ou=users,dc=cloudron`));
|
||||
|
||||
expect(entries[1].cn).to.equal('ldap-test-2');
|
||||
expect(entries[1].memberuid).to.equal(admin.id);
|
||||
expect(entries[0].member).to.contain(`cn=${admin.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].uniquemember).to.contain(`cn=${admin.id},ou=users,dc=cloudron`);
|
||||
assert.equal(entries[1].cn, 'ldap-test-2');
|
||||
assert.equal(entries[1].memberuid, admin.id);
|
||||
assert.ok(entries[0].member.includes(`cn=${admin.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].uniquemember.includes(`cn=${admin.id},ou=users,dc=cloudron`));
|
||||
});
|
||||
|
||||
it ('succeeds with cn wildcard filter', async function () {
|
||||
const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: '&(objectclass=group)(cn=*)' }, auth);
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
|
||||
// ensure order for testability
|
||||
entries.sort(function (a, b) { return a.cn < b.cn; });
|
||||
|
||||
expect(entries[0].cn).to.equal('ldap-test-1');
|
||||
expect(entries[0].memberuid.length).to.equal(2);
|
||||
expect(entries[0].memberuid).to.contain(admin.id);
|
||||
expect(entries[0].memberuid).to.contain(user.id);
|
||||
expect(entries[0].member).to.contain(`cn=${user.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].member).to.contain(`cn=${admin.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].uniquemember).to.contain(`cn=${user.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].uniquemember).to.contain(`cn=${admin.id},ou=users,dc=cloudron`);
|
||||
assert.equal(entries[0].cn, 'ldap-test-1');
|
||||
assert.equal(entries[0].memberuid.length, 2);
|
||||
assert.ok(entries[0].memberuid.includes(admin.id));
|
||||
assert.ok(entries[0].memberuid.includes(user.id));
|
||||
assert.ok(entries[0].member.includes(`cn=${user.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].member.includes(`cn=${admin.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].uniquemember.includes(`cn=${user.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].uniquemember.includes(`cn=${admin.id},ou=users,dc=cloudron`));
|
||||
|
||||
expect(entries[1].cn).to.equal('ldap-test-2');
|
||||
expect(entries[1].memberuid).to.equal(admin.id);
|
||||
expect(entries[0].member).to.contain(`cn=${admin.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].uniquemember).to.contain(`cn=${admin.id},ou=users,dc=cloudron`);
|
||||
assert.equal(entries[1].cn, 'ldap-test-2');
|
||||
assert.equal(entries[1].memberuid, admin.id);
|
||||
assert.ok(entries[0].member.includes(`cn=${admin.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].uniquemember.includes(`cn=${admin.id},ou=users,dc=cloudron`));
|
||||
});
|
||||
|
||||
it('succeeds with memberuid filter', async function () {
|
||||
const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: '&(objectclass=group)(memberuid=' + user.id + ')' }, auth);
|
||||
expect(entries.length).to.equal(1);
|
||||
assert.equal(entries.length, 1);
|
||||
|
||||
// ensure order for testability
|
||||
entries.sort(function (a, b) { return a.cn < b.cn; });
|
||||
|
||||
expect(entries[0].cn).to.equal('ldap-test-1');
|
||||
expect(entries[0].memberuid.length).to.equal(2);
|
||||
expect(entries[0].memberuid).to.contain(admin.id);
|
||||
expect(entries[0].memberuid).to.contain(user.id);
|
||||
expect(entries[0].member).to.contain(`cn=${user.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].member).to.contain(`cn=${admin.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].uniquemember).to.contain(`cn=${user.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].uniquemember).to.contain(`cn=${admin.id},ou=users,dc=cloudron`);
|
||||
assert.equal(entries[0].cn, 'ldap-test-1');
|
||||
assert.equal(entries[0].memberuid.length, 2);
|
||||
assert.ok(entries[0].memberuid.includes(admin.id));
|
||||
assert.ok(entries[0].memberuid.includes(user.id));
|
||||
assert.ok(entries[0].member.includes(`cn=${user.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].member.includes(`cn=${admin.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].uniquemember.includes(`cn=${user.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].uniquemember.includes(`cn=${admin.id},ou=users,dc=cloudron`));
|
||||
});
|
||||
|
||||
it ('succeeds with pagination', async function () {
|
||||
mockApp.accessRestriction = null;
|
||||
const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: 'objectclass=group', paged: true }, auth);
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
|
||||
// ensure order for testability
|
||||
entries.sort(function (a, b) { return a.cn < b.cn; });
|
||||
|
||||
expect(entries[0].cn).to.equal('ldap-test-1');
|
||||
expect(entries[0].memberuid.length).to.equal(2);
|
||||
expect(entries[0].memberuid).to.contain(admin.id);
|
||||
expect(entries[0].memberuid).to.contain(user.id);
|
||||
expect(entries[0].member).to.contain(`cn=${user.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].member).to.contain(`cn=${admin.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].uniquemember).to.contain(`cn=${user.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].uniquemember).to.contain(`cn=${admin.id},ou=users,dc=cloudron`);
|
||||
assert.equal(entries[0].cn, 'ldap-test-1');
|
||||
assert.equal(entries[0].memberuid.length, 2);
|
||||
assert.ok(entries[0].memberuid.includes(admin.id));
|
||||
assert.ok(entries[0].memberuid.includes(user.id));
|
||||
assert.ok(entries[0].member.includes(`cn=${user.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].member.includes(`cn=${admin.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].uniquemember.includes(`cn=${user.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].uniquemember.includes(`cn=${admin.id},ou=users,dc=cloudron`));
|
||||
|
||||
expect(entries[1].cn).to.equal('ldap-test-2');
|
||||
expect(entries[1].memberuid).to.equal(admin.id);
|
||||
expect(entries[0].member).to.contain(`cn=${admin.id},ou=users,dc=cloudron`);
|
||||
expect(entries[0].uniquemember).to.contain(`cn=${admin.id},ou=users,dc=cloudron`);
|
||||
assert.equal(entries[1].cn, 'ldap-test-2');
|
||||
assert.equal(entries[1].memberuid, admin.id);
|
||||
assert.ok(entries[0].member.includes(`cn=${admin.id},ou=users,dc=cloudron`));
|
||||
assert.ok(entries[0].uniquemember.includes(`cn=${admin.id},ou=users,dc=cloudron`));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import { describe, it, before, after, beforeEach } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import common from './common.js';
|
||||
import dns from '../dns.js';
|
||||
import domains from '../domains.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import { DNS as GCDNS } from '@google-cloud/dns';
|
||||
import nock from 'nock';
|
||||
import _ from '../underscore.js';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global beforeEach:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('dns provider', function () {
|
||||
const { setup, cleanup, auditSource, domain } = common;
|
||||
@@ -36,7 +32,7 @@ describe('dns provider', function () {
|
||||
|
||||
it('get succeeds', async function () {
|
||||
const result = await dns.getDnsRecords('test', domainCopy.domain, 'A');
|
||||
expect(result.length).to.eql(0);
|
||||
assert.deepEqual(result.length, 0);
|
||||
});
|
||||
|
||||
it('del succeeds', async function () {
|
||||
@@ -78,8 +74,8 @@ describe('dns provider', function () {
|
||||
.reply(201, { domain_record: DOMAIN_RECORD_0 });
|
||||
|
||||
await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
expect(req2.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
assert.ok(req2.isDone());
|
||||
});
|
||||
|
||||
it('upsert existing record succeeds', async function () {
|
||||
@@ -123,8 +119,8 @@ describe('dns provider', function () {
|
||||
.reply(200, { domain_record: DOMAIN_RECORD_1_NEW });
|
||||
|
||||
await dns.upsertDnsRecords('test', domainCopy.domain, 'A', [DOMAIN_RECORD_1_NEW.data]);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
expect(req2.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
assert.ok(req2.isDone());
|
||||
});
|
||||
|
||||
it('upsert multiple record succeeds', async function () {
|
||||
@@ -204,10 +200,10 @@ describe('dns provider', function () {
|
||||
.reply(201, { domain_record: DOMAIN_RECORD_2_NEW });
|
||||
|
||||
await dns.upsertDnsRecords('', domainCopy.domain, 'TXT', [DOMAIN_RECORD_2_NEW.data, DOMAIN_RECORD_1_NEW.data, DOMAIN_RECORD_3_NEW.data]);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
expect(req2.isDone()).to.be.ok();
|
||||
expect(req3.isDone()).to.be.ok();
|
||||
expect(req4.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
assert.ok(req2.isDone());
|
||||
assert.ok(req3.isDone());
|
||||
assert.ok(req4.isDone());
|
||||
});
|
||||
|
||||
it('get succeeds', async function () {
|
||||
@@ -238,10 +234,10 @@ describe('dns provider', function () {
|
||||
.reply(200, { domain_records: [DOMAIN_RECORD_0, DOMAIN_RECORD_1] });
|
||||
|
||||
const result = await dns.getDnsRecords('test', domainCopy.domain, 'A');
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.eql(1);
|
||||
expect(result[0]).to.eql(DOMAIN_RECORD_1.data);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.deepEqual(result.length, 1);
|
||||
assert.deepEqual(result[0], DOMAIN_RECORD_1.data);
|
||||
assert.ok(req1.isDone());
|
||||
});
|
||||
|
||||
it('del succeeds', async function () {
|
||||
@@ -275,8 +271,8 @@ describe('dns provider', function () {
|
||||
.reply(204, {});
|
||||
|
||||
await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
expect(req2.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
assert.ok(req2.isDone());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -307,7 +303,7 @@ describe('dns provider', function () {
|
||||
.reply(200, {});
|
||||
|
||||
await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
});
|
||||
|
||||
it('get succeeds', async function () {
|
||||
@@ -323,10 +319,10 @@ describe('dns provider', function () {
|
||||
.reply(200, DOMAIN_RECORD_0);
|
||||
|
||||
const result = await dns.getDnsRecords('test', domainCopy.domain, 'A');
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.eql(1);
|
||||
expect(result[0]).to.eql(DOMAIN_RECORD_0[0].data);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.deepEqual(result.length, 1);
|
||||
assert.deepEqual(result[0], DOMAIN_RECORD_0[0].data);
|
||||
assert.ok(req1.isDone());
|
||||
});
|
||||
|
||||
it('del succeeds', async function () {
|
||||
@@ -346,8 +342,8 @@ describe('dns provider', function () {
|
||||
.reply(204, {});
|
||||
|
||||
await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
expect(req2.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
assert.ok(req2.isDone());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -378,7 +374,7 @@ describe('dns provider', function () {
|
||||
.reply(201, { message: 'Zone Record Created' });
|
||||
|
||||
await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
});
|
||||
|
||||
it('get succeeds', async function () {
|
||||
@@ -396,10 +392,10 @@ describe('dns provider', function () {
|
||||
.reply(200, DOMAIN_RECORD_0);
|
||||
|
||||
const result = await dns.getDnsRecords('test', domainCopy.domain, 'A');
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.eql(1);
|
||||
expect(result[0]).to.eql(DOMAIN_RECORD_0.rrset_values[0]);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.deepEqual(result.length, 1);
|
||||
assert.deepEqual(result[0], DOMAIN_RECORD_0.rrset_values[0]);
|
||||
assert.ok(req1.isDone());
|
||||
});
|
||||
|
||||
it('del succeeds', async function () {
|
||||
@@ -410,7 +406,7 @@ describe('dns provider', function () {
|
||||
.reply(204, {});
|
||||
|
||||
await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(req2.isDone()).to.be.ok();
|
||||
assert.ok(req2.isDone());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -447,8 +443,8 @@ describe('dns provider', function () {
|
||||
.reply(200, {});
|
||||
|
||||
await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
expect(req2.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
assert.ok(req2.isDone());
|
||||
});
|
||||
|
||||
it('get succeeds', async function () {
|
||||
@@ -466,10 +462,10 @@ describe('dns provider', function () {
|
||||
.reply(200, { records: [DOMAIN_RECORD_0] });
|
||||
|
||||
const result = await dns.getDnsRecords('test', domainCopy.domain, 'A');
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.eql(1);
|
||||
expect(result[0]).to.eql(DOMAIN_RECORD_0.answer);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.deepEqual(result.length, 1);
|
||||
assert.deepEqual(result[0], DOMAIN_RECORD_0.answer);
|
||||
assert.ok(req1.isDone());
|
||||
});
|
||||
|
||||
it('del succeeds', async function () {
|
||||
@@ -492,8 +488,8 @@ describe('dns provider', function () {
|
||||
.reply(200, {});
|
||||
|
||||
await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
expect(req2.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
assert.ok(req2.isDone());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -593,8 +589,8 @@ describe('dns provider', function () {
|
||||
.reply(200, SET_HOSTS_RETURN);
|
||||
|
||||
await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
expect(req2.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
assert.ok(req2.isDone());
|
||||
});
|
||||
|
||||
it('upsert multiple non-existing records succeeds', async function () {
|
||||
@@ -668,8 +664,8 @@ describe('dns provider', function () {
|
||||
.reply(200, SET_HOSTS_RETURN);
|
||||
|
||||
await dns.upsertDnsRecords('test', domainCopy.domain, 'TXT', ['1.2.3.4', '2.3.4.5', '3.4.5.6']);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
expect(req2.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
assert.ok(req2.isDone());
|
||||
});
|
||||
|
||||
it('upsert existing record succeeds', async function () {
|
||||
@@ -728,8 +724,8 @@ describe('dns provider', function () {
|
||||
.reply(200, SET_HOSTS_RETURN);
|
||||
|
||||
await dns.upsertDnsRecords('www', domainCopy.domain, 'CNAME', ['1.2.3.4']);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
expect(req2.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
assert.ok(req2.isDone());
|
||||
});
|
||||
|
||||
it('get succeeds', async function () {
|
||||
@@ -763,10 +759,10 @@ describe('dns provider', function () {
|
||||
.reply(200, GET_HOSTS_RETURN);
|
||||
|
||||
const result = await dns.getDnsRecords('test', domainCopy.domain, 'A');
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.eql(2);
|
||||
expect(result).to.eql(['1.2.3.4', '2.3.4.5']);
|
||||
assert.ok(req1.isDone());
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.deepEqual(result.length, 2);
|
||||
assert.deepEqual(result, ['1.2.3.4', '2.3.4.5']);
|
||||
});
|
||||
|
||||
it('del succeeds', async function () {
|
||||
@@ -820,8 +816,8 @@ describe('dns provider', function () {
|
||||
.reply(200, SET_HOSTS_RETURN);
|
||||
|
||||
await dns.removeDnsRecords('www', domainCopy.domain, 'CNAME', ['1.2.3.4']);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
expect(req2.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
assert.ok(req2.isDone());
|
||||
});
|
||||
|
||||
it('del succeeds with non-existing domain', async function () {
|
||||
@@ -854,7 +850,7 @@ describe('dns provider', function () {
|
||||
.reply(200, GET_HOSTS_RETURN);
|
||||
|
||||
await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(req1.isDone()).to.be.ok();
|
||||
assert.ok(req1.isDone());
|
||||
});
|
||||
|
||||
});
|
||||
@@ -899,7 +895,7 @@ describe('dns provider', function () {
|
||||
|
||||
function mockery(queue) {
|
||||
return async function (options) {
|
||||
expect(options).to.be.an(Object);
|
||||
assert.ok((options) && typeof (options) === 'object' && !Array.isArray(options));
|
||||
|
||||
const elem = queue.shift();
|
||||
if (!Array.isArray(elem)) throw (new Error('Mock answer required'));
|
||||
@@ -909,11 +905,11 @@ describe('dns provider', function () {
|
||||
}
|
||||
|
||||
function Route53Mock(cfg) {
|
||||
expect(cfg.credentials).to.eql({ // retryDelayOptions is a function
|
||||
assert.deepEqual(cfg.credentials, { // retryDelayOptions is a function
|
||||
accessKeyId: domainCopy.config.accessKeyId,
|
||||
secretAccessKey: domainCopy.config.secretAccessKey,
|
||||
});
|
||||
expect(cfg.region).to.be('us-east-1');
|
||||
assert.equal(cfg.region, 'us-east-1');
|
||||
}
|
||||
Route53Mock.prototype.getHostedZone = mockery(awsAnswerQueue);
|
||||
Route53Mock.prototype.getChange = mockery(awsAnswerQueue);
|
||||
@@ -941,7 +937,7 @@ describe('dns provider', function () {
|
||||
}]);
|
||||
|
||||
await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(awsAnswerQueue.length).to.eql(0);
|
||||
assert.deepEqual(awsAnswerQueue.length, 0);
|
||||
});
|
||||
|
||||
it('upsert existing record succeeds', async function () {
|
||||
@@ -955,7 +951,7 @@ describe('dns provider', function () {
|
||||
}]);
|
||||
|
||||
await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(awsAnswerQueue.length).to.eql(0);
|
||||
assert.deepEqual(awsAnswerQueue.length, 0);
|
||||
});
|
||||
|
||||
it('upsert multiple record succeeds', async function () {
|
||||
@@ -969,7 +965,7 @@ describe('dns provider', function () {
|
||||
}]);
|
||||
|
||||
await dns.upsertDnsRecords('', domainCopy.domain, 'TXT', ['first', 'second', 'third']);
|
||||
expect(awsAnswerQueue.length).to.eql(0);
|
||||
assert.deepEqual(awsAnswerQueue.length, 0);
|
||||
});
|
||||
|
||||
it('get succeeds', async function () {
|
||||
@@ -985,10 +981,10 @@ describe('dns provider', function () {
|
||||
}]);
|
||||
|
||||
const result = await dns.getDnsRecords('test', domainCopy.domain, 'A');
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.eql(1);
|
||||
expect(result[0]).to.eql('1.2.3.4');
|
||||
expect(awsAnswerQueue.length).to.eql(0);
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.deepEqual(result.length, 1);
|
||||
assert.deepEqual(result[0], '1.2.3.4');
|
||||
assert.deepEqual(awsAnswerQueue.length, 0);
|
||||
});
|
||||
|
||||
it('del succeeds', async function () {
|
||||
@@ -1002,7 +998,7 @@ describe('dns provider', function () {
|
||||
}]);
|
||||
|
||||
await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(awsAnswerQueue.length).to.eql(0);
|
||||
assert.deepEqual(awsAnswerQueue.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1059,7 +1055,7 @@ describe('dns provider', function () {
|
||||
zoneQueue.push([null, { id: '1' }]);
|
||||
|
||||
await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(zoneQueue.length).to.eql(0);
|
||||
assert.deepEqual(zoneQueue.length, 0);
|
||||
});
|
||||
|
||||
it('upsert existing record succeeds', async function () {
|
||||
@@ -1068,7 +1064,7 @@ describe('dns provider', function () {
|
||||
zoneQueue.push([null, { id: '2' }]);
|
||||
|
||||
await dns.upsertDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(zoneQueue.length).to.eql(0);
|
||||
assert.deepEqual(zoneQueue.length, 0);
|
||||
});
|
||||
|
||||
it('upsert multiple record succeeds', async function () {
|
||||
@@ -1077,7 +1073,7 @@ describe('dns provider', function () {
|
||||
zoneQueue.push([null, { id: '3' }]);
|
||||
|
||||
await dns.upsertDnsRecords('', domainCopy.domain, 'TXT', ['first', 'second', 'third']);
|
||||
expect(zoneQueue.length).to.eql(0);
|
||||
assert.deepEqual(zoneQueue.length, 0);
|
||||
});
|
||||
|
||||
it('get succeeds', async function () {
|
||||
@@ -1085,10 +1081,10 @@ describe('dns provider', function () {
|
||||
zoneQueue.push([null, [new GCDNS().zone('test').record('A', { 'name': 'test', data: ['1.2.3.4', '5.6.7.8'], ttl: 1 })]]);
|
||||
|
||||
const result = await dns.getDnsRecords('test', domainCopy.domain, 'A');
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.eql(2);
|
||||
expect(result).to.eql(['1.2.3.4', '5.6.7.8']);
|
||||
expect(zoneQueue.length).to.eql(0);
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.deepEqual(result.length, 2);
|
||||
assert.deepEqual(result, ['1.2.3.4', '5.6.7.8']);
|
||||
assert.deepEqual(zoneQueue.length, 0);
|
||||
});
|
||||
|
||||
it('del succeeds', async function () {
|
||||
@@ -1097,7 +1093,7 @@ describe('dns provider', function () {
|
||||
zoneQueue.push([null, { id: '5' }]);
|
||||
|
||||
await dns.removeDnsRecords('test', domainCopy.domain, 'A', ['1.2.3.4']);
|
||||
expect(zoneQueue.length).to.eql(0);
|
||||
assert.deepEqual(zoneQueue.length, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+32
-35
@@ -1,12 +1,9 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import common from './common.js';
|
||||
import dns from '../dns.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('DNS', function () {
|
||||
const { setup, cleanup, app, domain:domainObject } = common;
|
||||
@@ -19,34 +16,34 @@ describe('DNS', function () {
|
||||
describe('validateHostname', function () {
|
||||
it('cannot have >63 length subdomains', function () {
|
||||
const s = Array(64).fill('s').join('');
|
||||
expect(dns.validateHostname(s, domain)).to.be.an(Error);
|
||||
expect(dns.validateHostname(`dev.${s}`, domain)).to.be.an(Error);
|
||||
assert.ok((dns.validateHostname(s, domain)) instanceof (Error));
|
||||
assert.ok((dns.validateHostname(`dev.${s}`, domain)) instanceof (Error));
|
||||
});
|
||||
|
||||
it('allows only alphanumerics and hypen', function () {
|
||||
expect(dns.validateHostname('#2r', domain)).to.be.an(Error);
|
||||
expect(dns.validateHostname('a%b', domain)).to.be.an(Error);
|
||||
expect(dns.validateHostname('ab_', domain)).to.be.an(Error);
|
||||
expect(dns.validateHostname('ab.', domain)).to.be.an(Error);
|
||||
expect(dns.validateHostname('ab..c', domain)).to.be.an(Error);
|
||||
expect(dns.validateHostname('.ab', domain)).to.be.an(Error);
|
||||
expect(dns.validateHostname('-ab', domain)).to.be.an(Error);
|
||||
expect(dns.validateHostname('ab-', domain)).to.be.an(Error);
|
||||
assert.ok((dns.validateHostname('#2r', domain)) instanceof (Error));
|
||||
assert.ok((dns.validateHostname('a%b', domain)) instanceof (Error));
|
||||
assert.ok((dns.validateHostname('ab_', domain)) instanceof (Error));
|
||||
assert.ok((dns.validateHostname('ab.', domain)) instanceof (Error));
|
||||
assert.ok((dns.validateHostname('ab..c', domain)) instanceof (Error));
|
||||
assert.ok((dns.validateHostname('.ab', domain)) instanceof (Error));
|
||||
assert.ok((dns.validateHostname('-ab', domain)) instanceof (Error));
|
||||
assert.ok((dns.validateHostname('ab-', domain)) instanceof (Error));
|
||||
});
|
||||
|
||||
it('total length cannot exceed 255', function () {
|
||||
let s = '';
|
||||
for (let i = 0; i < (255 - 'example.com'.length); i++) s += 's';
|
||||
|
||||
expect(dns.validateHostname(s, domain)).to.be.an(Error);
|
||||
assert.ok((dns.validateHostname(s, domain)) instanceof (Error));
|
||||
});
|
||||
|
||||
it('allow valid domains', function () {
|
||||
expect(dns.validateHostname('a', domain)).to.be(null);
|
||||
expect(dns.validateHostname('a0-x', domain)).to.be(null);
|
||||
expect(dns.validateHostname('a0.x', domain)).to.be(null);
|
||||
expect(dns.validateHostname('a0.x.y', domain)).to.be(null);
|
||||
expect(dns.validateHostname('01', domain)).to.be(null);
|
||||
assert.equal(dns.validateHostname('a', domain), null);
|
||||
assert.equal(dns.validateHostname('a0-x', domain), null);
|
||||
assert.equal(dns.validateHostname('a0.x', domain), null);
|
||||
assert.equal(dns.validateHostname('a0.x.y', domain), null);
|
||||
assert.equal(dns.validateHostname('01', domain), null);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -58,15 +55,15 @@ describe('DNS', function () {
|
||||
config: {}
|
||||
};
|
||||
|
||||
expect(dns.getName(d, '', 'A')).to.be('');
|
||||
expect(dns.getName(d, 'www', 'A')).to.be('www');
|
||||
expect(dns.getName(d, 'www.dev', 'A')).to.be('www.dev');
|
||||
assert.equal(dns.getName(d, '', 'A'), '');
|
||||
assert.equal(dns.getName(d, 'www', 'A'), 'www');
|
||||
assert.equal(dns.getName(d, 'www.dev', 'A'), 'www.dev');
|
||||
|
||||
expect(dns.getName(d, '', 'MX')).to.be('');
|
||||
assert.equal(dns.getName(d, '', 'MX'), '');
|
||||
|
||||
expect(dns.getName(d, '', 'TXT')).to.be('');
|
||||
expect(dns.getName(d, 'www', 'TXT')).to.be('www');
|
||||
expect(dns.getName(d, 'www.dev', 'TXT')).to.be('www.dev');
|
||||
assert.equal(dns.getName(d, '', 'TXT'), '');
|
||||
assert.equal(dns.getName(d, 'www', 'TXT'), 'www');
|
||||
assert.equal(dns.getName(d, 'www.dev', 'TXT'), 'www.dev');
|
||||
});
|
||||
|
||||
it('works when zoneName!=domain', function () {
|
||||
@@ -76,15 +73,15 @@ describe('DNS', function () {
|
||||
config: {}
|
||||
};
|
||||
|
||||
expect(dns.getName(d, '', 'A')).to.be('dev');
|
||||
expect(dns.getName(d, 'www', 'A')).to.be('www.dev');
|
||||
expect(dns.getName(d, 'www.dev', 'A')).to.be('www.dev.dev');
|
||||
assert.equal(dns.getName(d, '', 'A'), 'dev');
|
||||
assert.equal(dns.getName(d, 'www', 'A'), 'www.dev');
|
||||
assert.equal(dns.getName(d, 'www.dev', 'A'), 'www.dev.dev');
|
||||
|
||||
expect(dns.getName(d, '', 'MX')).to.be('dev');
|
||||
assert.equal(dns.getName(d, '', 'MX'), 'dev');
|
||||
|
||||
expect(dns.getName(d, '', 'TXT')).to.be('dev');
|
||||
expect(dns.getName(d, 'www', 'TXT')).to.be('www.dev');
|
||||
expect(dns.getName(d, 'www.dev', 'TXT')).to.be('www.dev.dev');
|
||||
assert.equal(dns.getName(d, '', 'TXT'), 'dev');
|
||||
assert.equal(dns.getName(d, 'www', 'TXT'), 'www.dev');
|
||||
assert.equal(dns.getName(d, 'www.dev', 'TXT'), 'www.dev.dev');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+9
-12
@@ -1,14 +1,11 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import common from './common.js';
|
||||
import docker from '../docker.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import nock from 'nock';
|
||||
|
||||
/* global it:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
/* global describe:false */
|
||||
|
||||
describe('docker', function () {
|
||||
const { setup, cleanup } = common;
|
||||
@@ -22,15 +19,15 @@ describe('docker', function () {
|
||||
|
||||
it('can df', async function () {
|
||||
const output = await docker.df({});
|
||||
expect(output).to.be.ok();
|
||||
assert.ok(output);
|
||||
});
|
||||
|
||||
it('parseImageRef', async function () {
|
||||
expect(docker.parseImageRef('cloudron/base')).to.eql({ fullRepositoryName: 'cloudron/base', registry: null, tag: null, digest: null });
|
||||
expect(docker.parseImageRef('cloudron/base:4.2.0')).to.eql({ fullRepositoryName: 'cloudron/base', registry: null, tag: '4.2.0', digest: null });
|
||||
expect(docker.parseImageRef('cloudron/base@sha256:xx')).to.eql({ fullRepositoryName: 'cloudron/base', registry: null, tag: null, digest: 'xx' });
|
||||
expect(docker.parseImageRef('cloudron/base:4.2.0@sha256:xx')).to.eql({ fullRepositoryName: 'cloudron/base', registry: null, tag: '4.2.0', digest: 'xx' });
|
||||
expect(docker.parseImageRef('registry.com/cloudron/base:4.2.0@sha256:xx')).to.eql({ fullRepositoryName: 'registry.com/cloudron/base', registry: 'registry.com', tag: '4.2.0', digest: 'xx' });
|
||||
expect(docker.parseImageRef('registry.com/base:4.2.0@sha256:xx')).to.eql({ fullRepositoryName: 'registry.com/base', registry: 'registry.com', tag: '4.2.0', digest: 'xx' }); // optional namespace
|
||||
assert.deepEqual(docker.parseImageRef('cloudron/base'), { fullRepositoryName: 'cloudron/base', registry: null, tag: null, digest: null });
|
||||
assert.deepEqual(docker.parseImageRef('cloudron/base:4.2.0'), { fullRepositoryName: 'cloudron/base', registry: null, tag: '4.2.0', digest: null });
|
||||
assert.deepEqual(docker.parseImageRef('cloudron/base@sha256:xx'), { fullRepositoryName: 'cloudron/base', registry: null, tag: null, digest: 'xx' });
|
||||
assert.deepEqual(docker.parseImageRef('cloudron/base:4.2.0@sha256:xx'), { fullRepositoryName: 'cloudron/base', registry: null, tag: '4.2.0', digest: 'xx' });
|
||||
assert.deepEqual(docker.parseImageRef('registry.com/cloudron/base:4.2.0@sha256:xx'), { fullRepositoryName: 'registry.com/cloudron/base', registry: 'registry.com', tag: '4.2.0', digest: 'xx' });
|
||||
assert.deepEqual(docker.parseImageRef('registry.com/base:4.2.0@sha256:xx'), { fullRepositoryName: 'registry.com/base', registry: 'registry.com', tag: '4.2.0', digest: 'xx' }); // optional namespace
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import child_process from 'node:child_process';
|
||||
import common from './common.js';
|
||||
import constants from '../constants.js';
|
||||
import dockerProxy from '../dockerproxy.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import nock from 'nock';
|
||||
import syslogServer from '../../syslog.js';
|
||||
|
||||
/* global it:false */
|
||||
/* global xit:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
const DOCKER = `docker -H tcp://172.18.0.1:${constants.DOCKER_PROXY_PORT} `;
|
||||
|
||||
@@ -55,39 +51,33 @@ describe('Dockerproxy', function () {
|
||||
|
||||
it('can get info', async function () {
|
||||
const stdout = await exec(DOCKER + ' info');
|
||||
expect(stdout).to.contain('Containers:');
|
||||
// expect(stderr).to.be.empty(); // on some machines, i get 'No swap limit support'
|
||||
assert.ok(stdout.includes('Containers:'));
|
||||
// assert.equal((stderr).length, 0); // on some machines, i get 'No swap limit support'
|
||||
});
|
||||
|
||||
it('can create container', async function () {
|
||||
const cmd = `${DOCKER} run ${BASE_IMAGE} "/bin/bash" "-c" "echo 'hello'"`;
|
||||
const stdout = await exec(cmd);
|
||||
expect(stdout).to.contain('hello');
|
||||
assert.ok(stdout.includes('hello'));
|
||||
});
|
||||
|
||||
it('proxy overwrites the container network option', async function () {
|
||||
const cmd = `${DOCKER} run --network ifnotrewritethiswouldfail ${BASE_IMAGE} "/bin/bash" "-c" "echo 'hello'"`;
|
||||
const stdout = await exec(cmd);
|
||||
expect(stdout).to.contain('hello');
|
||||
assert.ok(stdout.includes('hello'));
|
||||
});
|
||||
|
||||
xit('cannot see logs through docker logs, since syslog is configured', function (done) {
|
||||
exec(`${DOCKER} logs ${containerId}`, function (error, stdout, stderr) {
|
||||
expect(error.message).to.contain('configured logging driver does not support reading');
|
||||
expect(stderr).to.contain('configured logging driver does not support reading');
|
||||
expect(stdout).to.be.empty();
|
||||
|
||||
done();
|
||||
});
|
||||
it.skip('cannot see logs through docker logs, since syslog is configured', async function () {
|
||||
// kept skipped: docker logs output differs by host and logging driver
|
||||
});
|
||||
|
||||
it('can use PUT to upload archive into a container', async function () {
|
||||
const stdout = await exec(`${DOCKER} cp ${import.meta.dirname}/proxytestarchive.tar ${containerId}:/tmp/`);
|
||||
expect(stdout).to.be.empty();
|
||||
assert.equal((stdout).length, 0);
|
||||
});
|
||||
|
||||
it('can exec into a container', async function () {
|
||||
const stdout = await exec(`${DOCKER} exec ${containerId} ls`);
|
||||
expect(stdout).to.equal('bin\nboot\ndev\netc\nhome\nlib\nlib32\nlib64\nlibx32\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsrv\nsys\ntmp\nusr\nvar\n');
|
||||
assert.equal(stdout, 'bin\nboot\ndev\netc\nhome\nlib\nlib32\nlib64\nlibx32\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsrv\nsys\ntmp\nusr\nvar\n');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import dockerRegistries from '../dockerregistries.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Docker Registries', function () {
|
||||
const { setup, cleanup, auditSource } = common;
|
||||
@@ -21,45 +18,45 @@ describe('Docker Registries', function () {
|
||||
|
||||
it('cannot get random', async function () {
|
||||
const registry = await dockerRegistries.get('srandom');
|
||||
expect(registry).to.be(null);
|
||||
assert.equal(registry, null);
|
||||
});
|
||||
|
||||
it('can add', async function () {
|
||||
id = await dockerRegistries.add({ provider: 'devops', serverAddress: 'registry.devops.test', password: 'hushhush' }, auditSource);
|
||||
expect(id).to.be.a('string');
|
||||
assert.equal(typeof id, 'string');
|
||||
});
|
||||
|
||||
it('can get', async function () {
|
||||
const registry = await dockerRegistries.get(id);
|
||||
expect(registry.provider).to.be('devops');
|
||||
expect(registry.serverAddress).to.be('registry.devops.test');
|
||||
expect(registry.password).to.be('hushhush');
|
||||
assert.equal(registry.provider, 'devops');
|
||||
assert.equal(registry.serverAddress, 'registry.devops.test');
|
||||
assert.equal(registry.password, 'hushhush');
|
||||
});
|
||||
|
||||
it('can list', async function () {
|
||||
const registries = await dockerRegistries.list();
|
||||
expect(registries.length).to.be(1);
|
||||
expect(registries[0].provider).to.be('devops');
|
||||
expect(registries[0].serverAddress).to.be('registry.devops.test');
|
||||
expect(registries[0].password).to.be('hushhush');
|
||||
assert.equal(registries.length, 1);
|
||||
assert.equal(registries[0].provider, 'devops');
|
||||
assert.equal(registries[0].serverAddress, 'registry.devops.test');
|
||||
assert.equal(registries[0].password, 'hushhush');
|
||||
});
|
||||
|
||||
it('can update', async function () {
|
||||
await dockerRegistries.update(await dockerRegistries.get(id), { provider: 'cicd', serverAddress: 'registry.cicd' }, auditSource);
|
||||
const registry = await dockerRegistries.get(id);
|
||||
expect(registry.provider).to.be('cicd');
|
||||
expect(registry.serverAddress).to.be('registry.cicd');
|
||||
expect(registry.password).to.be('hushhush'); // injected from the older one
|
||||
assert.equal(registry.provider, 'cicd');
|
||||
assert.equal(registry.serverAddress, 'registry.cicd');
|
||||
assert.equal(registry.password, 'hushhush'); // injected from the older one
|
||||
});
|
||||
|
||||
it('can del', async function () {
|
||||
await dockerRegistries.del(await dockerRegistries.get(id), auditSource);
|
||||
const registries = await dockerRegistries.list();
|
||||
expect(registries.length).to.be(0);
|
||||
assert.equal(registries.length, 0);
|
||||
});
|
||||
|
||||
it('cannot del random', async function () {
|
||||
const [error] = await safe(dockerRegistries.del({ id: 'fake' }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
});
|
||||
|
||||
+33
-36
@@ -1,16 +1,13 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import apps from '../apps.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import domains from '../domains.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Domains', function () {
|
||||
const { setup, cleanup, domain, app, auditSource } = common;
|
||||
@@ -36,19 +33,19 @@ describe('Domains', function () {
|
||||
|
||||
it('cannot add same domain twice', async function () {
|
||||
const [error] = await safe(domains.add(DOMAIN_0.domain, DOMAIN_0, auditSource));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('can get domain', async function () {
|
||||
const result = await domains.get(DOMAIN_0.domain);
|
||||
expect(result.domain).to.equal(DOMAIN_0.domain);
|
||||
expect(result.zoneName).to.equal(DOMAIN_0.zoneName);
|
||||
expect(result.config).to.eql(DOMAIN_0.config);
|
||||
assert.equal(result.domain, DOMAIN_0.domain);
|
||||
assert.equal(result.zoneName, DOMAIN_0.zoneName);
|
||||
assert.deepEqual(result.config, DOMAIN_0.config);
|
||||
});
|
||||
|
||||
it('cannot get non-existent domain', async function () {
|
||||
const result = await domains.get('random');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('can set domain config', async function () {
|
||||
@@ -59,11 +56,11 @@ describe('Domains', function () {
|
||||
await domains.setConfig(DOMAIN_0.domain, newDomain, auditSource);
|
||||
|
||||
const result = await domains.get(DOMAIN_0.domain);
|
||||
expect(result.domain).to.equal(DOMAIN_0.domain);
|
||||
expect(result.zoneName).to.equal(DOMAIN_0.zoneName);
|
||||
expect(result.provider).to.equal(DOMAIN_0.provider);
|
||||
expect(result.config).to.eql(newConfig);
|
||||
expect(result.tlsConfig).to.eql(newTlsConfig);
|
||||
assert.equal(result.domain, DOMAIN_0.domain);
|
||||
assert.equal(result.zoneName, DOMAIN_0.zoneName);
|
||||
assert.equal(result.provider, DOMAIN_0.provider);
|
||||
assert.deepEqual(result.config, newConfig);
|
||||
assert.deepEqual(result.tlsConfig, newTlsConfig);
|
||||
|
||||
DOMAIN_0.config = newConfig;
|
||||
DOMAIN_0.tlsConfig = newTlsConfig;
|
||||
@@ -72,42 +69,42 @@ describe('Domains', function () {
|
||||
it('can set domain wellknown', async function () {
|
||||
await domains.setWellKnown(DOMAIN_0.domain, { service: 'some.service' }, auditSource);
|
||||
let result = await domains.get(DOMAIN_0.domain);
|
||||
expect(result.wellKnown).to.eql({ service: 'some.service' });
|
||||
assert.deepEqual(result.wellKnown, { service: 'some.service' });
|
||||
|
||||
await domains.setWellKnown(DOMAIN_0.domain, null, auditSource);
|
||||
result = await domains.get(DOMAIN_0.domain);
|
||||
expect(result.wellKnown).to.eql(null);
|
||||
assert.deepEqual(result.wellKnown, null);
|
||||
});
|
||||
|
||||
it('can get all domains', async function () {
|
||||
const result = await domains.list();
|
||||
expect(result.length).to.equal(2);
|
||||
assert.equal(result.length, 2);
|
||||
|
||||
// sorted by domain
|
||||
expect(result[0].domain).to.equal(domain.domain);
|
||||
expect(result[0].zoneName).to.equal(domain.zoneName);
|
||||
expect(result[0].provider).to.equal(domain.provider);
|
||||
expect(result[0].config).to.eql(domain.config);
|
||||
expect(result[0].tlsConfig).to.eql(domain.tlsConfig);
|
||||
assert.equal(result[0].domain, domain.domain);
|
||||
assert.equal(result[0].zoneName, domain.zoneName);
|
||||
assert.equal(result[0].provider, domain.provider);
|
||||
assert.deepEqual(result[0].config, domain.config);
|
||||
assert.deepEqual(result[0].tlsConfig, domain.tlsConfig);
|
||||
|
||||
expect(result[1].domain).to.equal(DOMAIN_0.domain);
|
||||
expect(result[1].zoneName).to.equal(DOMAIN_0.zoneName);
|
||||
expect(result[1].provider).to.equal(DOMAIN_0.provider);
|
||||
expect(result[1].config).to.eql(DOMAIN_0.config);
|
||||
expect(result[1].tlsConfig).to.eql(DOMAIN_0.tlsConfig);
|
||||
assert.equal(result[1].domain, DOMAIN_0.domain);
|
||||
assert.equal(result[1].zoneName, DOMAIN_0.zoneName);
|
||||
assert.equal(result[1].provider, DOMAIN_0.provider);
|
||||
assert.deepEqual(result[1].config, DOMAIN_0.config);
|
||||
assert.deepEqual(result[1].tlsConfig, DOMAIN_0.tlsConfig);
|
||||
});
|
||||
|
||||
it('cannot delete non-existing domain', async function () {
|
||||
const [error] = await safe(domains.del('not.exists', auditSource));
|
||||
expect(error).to.be.a(BoxError);
|
||||
expect(error.reason).to.equal(BoxError.NOT_FOUND);
|
||||
assert.ok((error) instanceof (BoxError));
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('cannot delete dashboard domain', async function () {
|
||||
const [error] = await safe(domains.del(domain.domain, auditSource));
|
||||
expect(error).to.be.a(BoxError);
|
||||
expect(error.reason).to.equal(BoxError.CONFLICT);
|
||||
expect(error.message).to.equal('Cannot remove admin domain');
|
||||
assert.ok((error) instanceof (BoxError));
|
||||
assert.equal(error.reason, BoxError.CONFLICT);
|
||||
assert.equal(error.message, 'Cannot remove admin domain');
|
||||
});
|
||||
|
||||
it('cannot delete referenced domain', async function () {
|
||||
@@ -116,8 +113,8 @@ describe('Domains', function () {
|
||||
await apps.add(appCopy.id, appCopy.appStoreId, '', appCopy.manifest, appCopy.subdomain, appCopy.domain, appCopy.portBindings, appCopy);
|
||||
|
||||
const [error] = await safe(domains.del(DOMAIN_0.domain, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.CONFLICT);
|
||||
expect(error.message).to.contain('Domain is in use in an app\'s location');
|
||||
assert.equal(error.reason, BoxError.CONFLICT);
|
||||
assert.ok(error.message.includes('Domain is in use in an app\'s location'));
|
||||
|
||||
await apps.del(appCopy.id);
|
||||
});
|
||||
@@ -126,6 +123,6 @@ describe('Domains', function () {
|
||||
await domains.del(DOMAIN_0.domain, auditSource);
|
||||
|
||||
const result = await domains.get(DOMAIN_0.domain);
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
});
|
||||
|
||||
+40
-43
@@ -1,16 +1,13 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import common from './common.js';
|
||||
import database from '../database.js';
|
||||
import eventlog from '../eventlog.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import notifications from '../notifications.js';
|
||||
import timers from 'timers/promises';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Eventlog', function () {
|
||||
const { setup, cleanup } = common;
|
||||
@@ -26,55 +23,55 @@ describe('Eventlog', function () {
|
||||
|
||||
it('add succeeds', async function () {
|
||||
const id = await eventlog.add('some.event', { ip: '1.2.3.4' }, { appId: 'thatapp' });
|
||||
expect(id).to.be.a('string');
|
||||
assert.equal(typeof id, 'string');
|
||||
|
||||
eventId = id;
|
||||
});
|
||||
|
||||
it('get succeeds', async function () {
|
||||
const result = await eventlog.get(eventId);
|
||||
expect(result.id).to.be(eventId);
|
||||
expect(result.action).to.be('some.event');
|
||||
expect(result.creationTime).to.be.a(Date);
|
||||
assert.equal(result.id, eventId);
|
||||
assert.equal(result.action, 'some.event');
|
||||
assert.ok((result.creationTime) instanceof (Date));
|
||||
|
||||
expect(result.source).to.be.eql({ ip: '1.2.3.4' });
|
||||
expect(result.data).to.be.eql({ appId: 'thatapp' });
|
||||
assert.deepEqual(result.source, { ip: '1.2.3.4' });
|
||||
assert.deepEqual(result.data, { appId: 'thatapp' });
|
||||
});
|
||||
|
||||
it('get of unknown id fails', async function () {
|
||||
const result = await eventlog.get('notfoundid');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('listPaged succeeds', async function () {
|
||||
const results = await eventlog.listPaged({ actions: [], search: null }, 1, 1);
|
||||
expect(results).to.be.an(Array);
|
||||
expect(results.length).to.be(1);
|
||||
assert.ok(Array.isArray(results));
|
||||
assert.equal(results.length, 1);
|
||||
|
||||
expect(results[0].id).to.be(eventId);
|
||||
expect(results[0].action).to.be('some.event');
|
||||
expect(results[0].source).to.be.eql({ ip: '1.2.3.4' });
|
||||
expect(results[0].data).to.be.eql({ appId: 'thatapp' });
|
||||
assert.equal(results[0].id, eventId);
|
||||
assert.equal(results[0].action, 'some.event');
|
||||
assert.deepEqual(results[0].source, { ip: '1.2.3.4' });
|
||||
assert.deepEqual(results[0].data, { appId: 'thatapp' });
|
||||
});
|
||||
|
||||
it('listPaged succeeds with source search', async function () {
|
||||
const results = await eventlog.listPaged({ actions: [], search: '1.2.3.4' }, 1, 1);
|
||||
expect(results).to.be.an(Array);
|
||||
expect(results.length).to.be(1);
|
||||
expect(results[0].id).to.be(eventId);
|
||||
expect(results[0].action).to.be('some.event');
|
||||
expect(results[0].source).to.be.eql({ ip: '1.2.3.4' });
|
||||
expect(results[0].data).to.be.eql({ appId: 'thatapp' });
|
||||
assert.ok(Array.isArray(results));
|
||||
assert.equal(results.length, 1);
|
||||
assert.equal(results[0].id, eventId);
|
||||
assert.equal(results[0].action, 'some.event');
|
||||
assert.deepEqual(results[0].source, { ip: '1.2.3.4' });
|
||||
assert.deepEqual(results[0].data, { appId: 'thatapp' });
|
||||
});
|
||||
|
||||
it('listPaged succeeds with data search', async function () {
|
||||
const results = await eventlog.listPaged({ actions: [], search: 'thatapp' }, 1, 1);
|
||||
expect(results).to.be.an(Array);
|
||||
expect(results.length).to.be(1);
|
||||
expect(results[0].id).to.be(eventId);
|
||||
expect(results[0].action).to.be('some.event');
|
||||
expect(results[0].source).to.be.eql({ ip: '1.2.3.4' });
|
||||
expect(results[0].data).to.be.eql({ appId: 'thatapp' });
|
||||
assert.ok(Array.isArray(results));
|
||||
assert.equal(results.length, 1);
|
||||
assert.equal(results[0].id, eventId);
|
||||
assert.equal(results[0].action, 'some.event');
|
||||
assert.deepEqual(results[0].source, { ip: '1.2.3.4' });
|
||||
assert.deepEqual(results[0].data, { appId: 'thatapp' });
|
||||
});
|
||||
|
||||
it('listPaged succeeds with from/to time filter', async function () {
|
||||
@@ -84,9 +81,9 @@ describe('Eventlog', function () {
|
||||
const to = new Date(creationTime.getTime() + 60000); // 1 min after
|
||||
|
||||
const results = await eventlog.listPaged({ actions: [], search: null, from, to }, 1, 10);
|
||||
expect(results).to.be.an(Array);
|
||||
expect(results.length).to.be.above(0);
|
||||
expect(results.some((r) => r.id === eventId)).to.be(true);
|
||||
assert.ok(Array.isArray(results));
|
||||
assert.ok((results.length) > (0));
|
||||
assert.equal(results.some((r) => r.id === eventId), true);
|
||||
});
|
||||
|
||||
it('listPaged returns empty with from after event', async function () {
|
||||
@@ -94,13 +91,13 @@ describe('Eventlog', function () {
|
||||
const from = new Date(event.creationTime.getTime() + 86400000); // 1 day after
|
||||
|
||||
const results = await eventlog.listPaged({ actions: [], search: null, from }, 1, 10);
|
||||
expect(results.some((r) => r.id === eventId)).to.be(false);
|
||||
assert.equal(results.some((r) => r.id === eventId), false);
|
||||
});
|
||||
|
||||
let loginEventId;
|
||||
it('upsert with no existing entry succeeds', async function () {
|
||||
const result = await eventlog.upsertLoginEvent('user.login', { ip: '1.2.3.4' }, { appId: 'thatapp' });
|
||||
expect(result).to.be.a('string');
|
||||
assert.equal(typeof result, 'string');
|
||||
loginEventId = result;
|
||||
});
|
||||
|
||||
@@ -110,11 +107,11 @@ describe('Eventlog', function () {
|
||||
|
||||
await timers.setTimeout(2000);
|
||||
result = await eventlog.upsertLoginEvent('user.login', { ip: '1.2.3.4' }, { appId: 'thatapp' });
|
||||
expect(result).to.equal(loginEventId);
|
||||
assert.equal(result, loginEventId);
|
||||
|
||||
result = await eventlog.get(loginEventId);
|
||||
// should have changed
|
||||
expect(oldCreationTime).to.not.equal(result.creationTime);
|
||||
assert.notEqual(oldCreationTime, result.creationTime);
|
||||
});
|
||||
|
||||
it('upsert with existing old entry succeeds', async function () {
|
||||
@@ -124,7 +121,7 @@ describe('Eventlog', function () {
|
||||
await database.query('INSERT INTO eventlog (id, action, sourceJson, dataJson, creationTime) VALUES (?, ?, ?, ?, ?)', [ 'anotherid', 'user.login2', JSON.stringify({ ip: '1.2.3.4' }), JSON.stringify({ appId: 'thatapp' }), yesterday ]);
|
||||
|
||||
const result = await eventlog.upsertLoginEvent('user.login2', { ip: '1.2.3.4' }, { appId: 'thatapp' });
|
||||
expect(result).to.not.equal('anotherid');
|
||||
assert.notEqual(result, 'anotherid');
|
||||
});
|
||||
|
||||
it('cleans up', async function () {
|
||||
@@ -142,13 +139,13 @@ describe('Eventlog', function () {
|
||||
|
||||
await eventlog.cleanup({ creationTime: new Date(Date.now() - 1000) }); // 1 second ago
|
||||
let results = await eventlog.listPaged({ actions: [], search: null }, 1, 100);
|
||||
expect(results.length).to.be(1);
|
||||
assert.equal(results.length, 1);
|
||||
|
||||
expect(results[0].id).to.be(id);
|
||||
expect(results[0].action).to.be(eventlog.ACTION_USER_LOGIN);
|
||||
expect(results[0].creationTime).to.be.a(Date);
|
||||
assert.equal(results[0].id, id);
|
||||
assert.equal(results[0].action, eventlog.ACTION_USER_LOGIN);
|
||||
assert.ok((results[0].creationTime) instanceof (Date));
|
||||
|
||||
results = await notifications.list({}, 1, 10);
|
||||
expect(results.length).to.be(0);
|
||||
assert.equal(results.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import async from 'async';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import externalLdap from '../externalldap.js';
|
||||
import groups from '../groups.js';
|
||||
import ldap from 'ldapjs';
|
||||
import safe from 'safetydance';
|
||||
import users from '../users.js';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
const LDAP_SHARED_PASSWORD = 'validpassword';
|
||||
const LDAP_SHARED_TOTP_TOKEN = '1234';
|
||||
@@ -221,18 +218,18 @@ describe('External LDAP', function () {
|
||||
const { setup, cleanup, admin, auditSource } = common;
|
||||
const ldapServer = new LdapServer(LDAP_CONFIG.provider);
|
||||
|
||||
before(function (done) {
|
||||
async.series([
|
||||
before(async function () {
|
||||
await async.series([
|
||||
ldapServer.start.bind(ldapServer),
|
||||
setup
|
||||
], done);
|
||||
]);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
async.series([
|
||||
after(async function () {
|
||||
await async.series([
|
||||
ldapServer.stop.bind(ldapServer),
|
||||
cleanup
|
||||
], done);
|
||||
]);
|
||||
});
|
||||
|
||||
describe('settings', function () {
|
||||
@@ -241,7 +238,7 @@ describe('External LDAP', function () {
|
||||
delete conf.url;
|
||||
|
||||
const [error] = await safe(externalLdap.setConfig(conf, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('enabling fails with empty url', async function () {
|
||||
@@ -249,7 +246,7 @@ describe('External LDAP', function () {
|
||||
conf.url = '';
|
||||
|
||||
const [error] = await safe(externalLdap.setConfig(conf, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('enabling fails with missing baseDn', async function () {
|
||||
@@ -257,7 +254,7 @@ describe('External LDAP', function () {
|
||||
delete conf.baseDn;
|
||||
|
||||
const [error] = await safe(externalLdap.setConfig(conf, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('enabling fails with empty baseDn', async function () {
|
||||
@@ -265,7 +262,7 @@ describe('External LDAP', function () {
|
||||
conf.baseDn = '';
|
||||
|
||||
const [error] = await safe(externalLdap.setConfig(conf, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('enabling fails with missing filter', async function () {
|
||||
@@ -273,7 +270,7 @@ describe('External LDAP', function () {
|
||||
delete conf.filter;
|
||||
|
||||
const [error] = await safe(externalLdap.setConfig(conf, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('enabling fails with empty filter', async function () {
|
||||
@@ -281,7 +278,7 @@ describe('External LDAP', function () {
|
||||
conf.filter = '';
|
||||
|
||||
const [error] = await safe(externalLdap.setConfig(conf, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('enabling succeeds', async function () {
|
||||
@@ -299,7 +296,7 @@ describe('External LDAP', function () {
|
||||
delete conf.groupBaseDn;
|
||||
|
||||
const [error] = await safe(externalLdap.setConfig(conf, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('enabling with groups fails with empty groupBaseDn', async function () {
|
||||
@@ -308,7 +305,7 @@ describe('External LDAP', function () {
|
||||
conf.groupBaseDn = '';
|
||||
|
||||
const [error] = await safe(externalLdap.setConfig(conf, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('enabling with groups fails with missing groupFilter', async function () {
|
||||
@@ -317,7 +314,7 @@ describe('External LDAP', function () {
|
||||
delete conf.groupFilter;
|
||||
|
||||
const [error] = await safe(externalLdap.setConfig(conf, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('enabling with groups fails with empty groupFilter', async function () {
|
||||
@@ -326,7 +323,7 @@ describe('External LDAP', function () {
|
||||
conf.groupFilter = '';
|
||||
|
||||
const [error] = await safe(externalLdap.setConfig(conf, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('enabling with groups fails with missing groupnameField', async function () {
|
||||
@@ -335,7 +332,7 @@ describe('External LDAP', function () {
|
||||
delete conf.groupnameField;
|
||||
|
||||
const [error] = await safe(externalLdap.setConfig(conf, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('enabling with groups fails with empty groupnameField', async function () {
|
||||
@@ -344,7 +341,7 @@ describe('External LDAP', function () {
|
||||
conf.groupnameField = '';
|
||||
|
||||
const [error] = await safe(externalLdap.setConfig(conf, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('enabling with groups succeeds', async function () {
|
||||
@@ -367,17 +364,17 @@ describe('External LDAP', function () {
|
||||
|
||||
it('fails for unknown user', async function () {
|
||||
const [error] = await safe(externalLdap.verifyPassword('badusername', 'badpassword', {}));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('fails for bad password', async function () {
|
||||
const [error] = await safe(externalLdap.verifyPassword('maximus', 'badpassword', {}));
|
||||
expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('succeeds for valid password', async function () {
|
||||
const u = await externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, {});
|
||||
expect(u.username).to.be('maximus');
|
||||
assert.equal(u.username, 'maximus');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -396,12 +393,12 @@ describe('External LDAP', function () {
|
||||
|
||||
it('succeeds when skip totp', async function () {
|
||||
const u = await externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, { skipTotpCheck: true });
|
||||
expect(u.username).to.be('maximus');
|
||||
assert.equal(u.username, 'maximus');
|
||||
});
|
||||
|
||||
it('succeeds when not skipping totp since totpToken is ignored for non-cloudron provider', async function () {
|
||||
const u = await externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, { skipTotpCheck: false, totpToken: 'random' });
|
||||
expect(u.username).to.be('maximus');
|
||||
assert.equal(u.username, 'maximus');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -420,22 +417,22 @@ describe('External LDAP', function () {
|
||||
|
||||
it('succeeds when skip totp (e.g. some cloudron app)', async function () {
|
||||
const u = await externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, { skipTotpCheck: true });
|
||||
expect(u.username).to.be('maximus');
|
||||
assert.equal(u.username, 'maximus');
|
||||
});
|
||||
|
||||
it('fails when not skipping totp (e.g. cloudron dashboard)', async function () {
|
||||
const [error] = await safe(externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, { skipTotpCheck: false, totpToken: 'badtotp' }));
|
||||
expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('fails when totp required and empty totp (e.g cloudron dashboard)', async function () {
|
||||
const [error] = await safe(externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, { skipTotpCheck: false, totpToken: '' }));
|
||||
expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('succeeds when totp required and good totp', async function () {
|
||||
const u = await externalLdap.verifyPassword('maximus', LDAP_SHARED_PASSWORD, { skipTotpCheck: false, totpToken: LDAP_SHARED_TOTP_TOKEN });
|
||||
expect(u.username).to.be('maximus');
|
||||
assert.equal(u.username, 'maximus');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -454,7 +451,7 @@ describe('External LDAP', function () {
|
||||
|
||||
it('fails if disabled', async function () {
|
||||
const [error] = await safe(externalLdap.sync(function progress() {}));
|
||||
expect(error.reason).to.equal(BoxError.BAD_STATE);
|
||||
assert.equal(error.reason, BoxError.BAD_STATE);
|
||||
});
|
||||
|
||||
it('enable', async function () {
|
||||
@@ -470,9 +467,9 @@ describe('External LDAP', function () {
|
||||
|
||||
await externalLdap.sync(function progress() {});
|
||||
const result = await users.list();
|
||||
expect(result.find(function (u) {
|
||||
assert.ok(result.find(function (u) {
|
||||
return u.username === 'firstuser' && u.email === 'first@user.com' && u.displayName === 'First User' && u.source === 'ldap';
|
||||
})).to.be.ok();
|
||||
}));
|
||||
});
|
||||
|
||||
it('succeeds for updated users', async function () {
|
||||
@@ -481,9 +478,9 @@ describe('External LDAP', function () {
|
||||
|
||||
await externalLdap.sync(function progress() {});
|
||||
const result = await users.list();
|
||||
expect(result.find(function (u) {
|
||||
assert.ok(result.find(function (u) {
|
||||
return u.username === 'firstuser' && u.email === 'first@changed.com' && u.displayName === 'User First' && u.source === 'ldap';
|
||||
})).to.be.ok();
|
||||
}));
|
||||
});
|
||||
|
||||
it('maps already existing users with same username', async function () {
|
||||
@@ -495,9 +492,9 @@ describe('External LDAP', function () {
|
||||
|
||||
await externalLdap.sync(function progress() {});
|
||||
const result = await users.list();
|
||||
expect(result.find(function (u) {
|
||||
assert.ok(result.find(function (u) {
|
||||
return u.email === 'foobar@bar.com' || u.displayName === 'Something Else';
|
||||
})).to.be.ok();
|
||||
}));
|
||||
});
|
||||
|
||||
it('does not sync group if group sync is disabled', async function () {
|
||||
@@ -507,7 +504,7 @@ describe('External LDAP', function () {
|
||||
|
||||
await externalLdap.sync(function progress() {});
|
||||
const result = await groups.list();
|
||||
expect(result.length).to.equal(0);
|
||||
assert.equal(result.length, 0);
|
||||
|
||||
ldapGroups.splice(0, 1); // clear the group in-place
|
||||
});
|
||||
@@ -525,7 +522,7 @@ describe('External LDAP', function () {
|
||||
it('succeeds with groups enabled', async function () {
|
||||
await externalLdap.sync(function progress() {});
|
||||
const result = await groups.list();
|
||||
expect(result.length).to.equal(0);
|
||||
assert.equal(result.length, 0);
|
||||
});
|
||||
|
||||
it('succeeds with groups enabled and new group', async function () {
|
||||
@@ -535,9 +532,9 @@ describe('External LDAP', function () {
|
||||
|
||||
await externalLdap.sync(function progress() {});
|
||||
const result = await groups.list();
|
||||
expect(result.find(function (g) {
|
||||
assert.ok(result.find(function (g) {
|
||||
return g.name === 'extgroup1' && g.source === 'ldap';
|
||||
})).to.be.ok();
|
||||
}));
|
||||
});
|
||||
|
||||
it('succeeds with groups enabled and second new group', async function () {
|
||||
@@ -547,10 +544,10 @@ describe('External LDAP', function () {
|
||||
|
||||
await externalLdap.sync(function progress() {});
|
||||
const result = await groups.list();
|
||||
expect(result.length).to.be(2);
|
||||
expect(result.find(function (g) {
|
||||
assert.equal(result.length, 2);
|
||||
assert.ok(result.find(function (g) {
|
||||
return g.name === 'extgroup2' && g.source === 'ldap';
|
||||
})).to.be.ok();
|
||||
}));
|
||||
});
|
||||
|
||||
it('does not create or change already existing group', async function () {
|
||||
@@ -562,10 +559,10 @@ describe('External LDAP', function () {
|
||||
await externalLdap.sync(function progress() {});
|
||||
|
||||
const result = await groups.list();
|
||||
expect(result.length).to.equal(3);
|
||||
expect(result.find(function (g) {
|
||||
assert.equal(result.length, 3);
|
||||
assert.ok(result.find(function (g) {
|
||||
return g.name === 'internalgroup' && g.source === 'ldap'; // source is updated to LDAP
|
||||
})).to.be.ok();
|
||||
}));
|
||||
});
|
||||
|
||||
it('adds users of groups', async function () {
|
||||
@@ -576,10 +573,10 @@ describe('External LDAP', function () {
|
||||
|
||||
await externalLdap.sync(function progress() {});
|
||||
const result = await groups.getByName('nonemptygroup');
|
||||
expect(result).to.be.ok();
|
||||
assert.ok(result);
|
||||
|
||||
const result2 = await groups.getMemberIds(result.id);
|
||||
expect(result2.length).to.equal(2);
|
||||
assert.equal(result2.length, 2);
|
||||
});
|
||||
|
||||
it('adds new users of groups', async function () {
|
||||
@@ -590,10 +587,10 @@ describe('External LDAP', function () {
|
||||
|
||||
await externalLdap.sync(function progress() {});
|
||||
const result = await groups.getByName('nonemptygroup');
|
||||
expect(result).to.be.ok();
|
||||
assert.ok(result);
|
||||
|
||||
const result2 = await groups.getMemberIds(result.id);
|
||||
expect(result2.length).to.equal(2);
|
||||
assert.equal(result2.length, 2);
|
||||
});
|
||||
|
||||
it('succeeds with only one group member (string instead of array)', async function () {
|
||||
@@ -606,16 +603,16 @@ describe('External LDAP', function () {
|
||||
|
||||
const result = await groups.getByName('onemembergroup');
|
||||
const result2 = await groups.getMemberIds(result.id);
|
||||
expect(result2.length).to.equal(1);
|
||||
assert.equal(result2.length, 1);
|
||||
|
||||
const u = await users.get(result2[0]);
|
||||
expect(u.username).to.equal(ldapUsers[0].username);
|
||||
assert.equal(u.username, ldapUsers[0].username);
|
||||
});
|
||||
|
||||
it('cannot update profile of external user', async function () {
|
||||
const user = await users.getByUsername(ldapUsers[0].username);
|
||||
const [error] = await safe(users.updateProfile(user, { displayName: 'another name'}, auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_STATE);
|
||||
assert.equal(error.reason, BoxError.BAD_STATE);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -639,10 +636,10 @@ describe('External LDAP', function () {
|
||||
});
|
||||
|
||||
const [error] = await safe(users.verifyWithUsername('autologinuser0', LDAP_SHARED_PASSWORD, users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
|
||||
const result = await users.list();
|
||||
expect(result.find(function (u) {
|
||||
assert.ok(result.find(function (u) {
|
||||
return u.username === 'autologinuser0';
|
||||
})).to.not.be.ok();
|
||||
});
|
||||
@@ -655,12 +652,12 @@ describe('External LDAP', function () {
|
||||
|
||||
it('fails for unknown user', async function () {
|
||||
const [error] = await safe(users.verifyWithUsername('doesnotexist', LDAP_SHARED_PASSWORD, users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
|
||||
const result = await users.list();
|
||||
expect(result.find(function (u) {
|
||||
assert.ok(!(result.find(function (u) {
|
||||
return u.username === 'doesnotexist';
|
||||
})).to.not.be.ok();
|
||||
})));
|
||||
});
|
||||
|
||||
it('succeeds for known user with wrong password', async function () {
|
||||
@@ -671,12 +668,12 @@ describe('External LDAP', function () {
|
||||
});
|
||||
|
||||
const [error] = await safe(users.verifyWithUsername('autologinuser1', 'wrongpassword', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.be(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
|
||||
const result = await users.list();
|
||||
expect(result.find(function (u) {
|
||||
assert.ok(result.find(function (u) {
|
||||
return u.username === 'autologinuser1';
|
||||
})).to.be.ok();
|
||||
}));
|
||||
});
|
||||
|
||||
it('succeeds for known user with correct password', async function () {
|
||||
@@ -690,9 +687,9 @@ describe('External LDAP', function () {
|
||||
await users.verifyWithUsername('autologinuser2', LDAP_SHARED_PASSWORD, users.AP_WEBADMIN, {});
|
||||
|
||||
const result = await users.list();
|
||||
expect(result.find(function (u) {
|
||||
assert.ok(result.find(function (u) {
|
||||
return u.username === 'autologinuser2';
|
||||
})).to.be.ok();
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+54
-57
@@ -1,15 +1,12 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import groups from '../groups.js';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Groups', function () {
|
||||
const { setup, cleanup, admin, user, auditSource, app } = common;
|
||||
@@ -25,72 +22,72 @@ describe('Groups', function () {
|
||||
describe('add', function () {
|
||||
it('cannot add group - too small', async function () {
|
||||
const [error] = await safe(groups.add({ name: '' }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot add group - too big', async function () {
|
||||
const [error] = await safe(groups.add({ name: new Array(256).join('a') }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot add group - bad name', async function () {
|
||||
const [error] = await safe(groups.add({ name: 'bad:name' }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot add group - reserved', async function () {
|
||||
const [error] = await safe(groups.add({ name: 'users' }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot add group - invalid', async function () {
|
||||
const [error] = await safe(groups.add({ name: 'cloudron+admin' }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot add group - invalid source', async function () {
|
||||
const [error] = await safe(groups.add({ name: 'somegroup', source: 'unknownsource' }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can add valid groups', async function () {
|
||||
let [error, result] = await safe(groups.add({ name: group0Name }, auditSource));
|
||||
expect(error).to.be(null);
|
||||
assert.equal(error, null);
|
||||
group0Object = result;
|
||||
|
||||
[error, result] = await safe(groups.add({ name: group1Name}, auditSource));
|
||||
expect(error).to.be(null);
|
||||
assert.equal(error, null);
|
||||
group1Object = result;
|
||||
});
|
||||
|
||||
it('cannot add existing group with mixed case', async function () {
|
||||
const name = group0Name[0].toUpperCase() + group0Name.slice(1);
|
||||
const [error] = await safe(groups.add({ name }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('cannot add existing group', async function () {
|
||||
const [error] = await safe(groups.add({name: group0Name }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
});
|
||||
|
||||
describe('get', function () {
|
||||
it('cannot get invalid group', async function () {
|
||||
const result = await groups.get('sometrandom');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('can get valid group', async function () {
|
||||
const result = await groups.get(group0Object.id);
|
||||
expect(result.name).to.equal(group0Name);
|
||||
assert.equal(result.name, group0Name);
|
||||
});
|
||||
});
|
||||
|
||||
describe('members', function () {
|
||||
it('isMember returns false', async function () {
|
||||
const isMember = await groups.isMember(group0Object.id, admin.id);
|
||||
expect(isMember).to.be(false);
|
||||
assert.equal(isMember, false);
|
||||
});
|
||||
|
||||
it('can set members', async function () {
|
||||
@@ -99,34 +96,34 @@ describe('Groups', function () {
|
||||
|
||||
it('cannot set duplicate members', async function () {
|
||||
const [error] = await safe(groups.setMembers(group0Object, [ admin.id, user.id, admin.id ], {}, auditSource));
|
||||
expect(error.reason).to.be(BoxError.CONFLICT);
|
||||
assert.equal(error.reason, BoxError.CONFLICT);
|
||||
});
|
||||
|
||||
it('can list users of group', async function () {
|
||||
const result = await groups.getMemberIds(group0Object.id);
|
||||
expect(result.sort()).to.eql([ admin.id, user.id ].sort());
|
||||
assert.deepEqual(result.sort(), [ admin.id, user.id ].sort());
|
||||
});
|
||||
|
||||
it('cannot list members of non-existent group', async function () {
|
||||
const result = await groups.getMemberIds('randomgroup');
|
||||
expect(result.length).to.be(0); // currently, we cannot differentiate invalid groups and empty groups
|
||||
assert.equal(result.length, 0); // currently, we cannot differentiate invalid groups and empty groups
|
||||
});
|
||||
|
||||
it('can getWithMembers', async function () {
|
||||
const result = await groups.getWithMembers(group0Object.id);
|
||||
expect(result.name).to.be(group0Name);
|
||||
expect(result.userIds.sort()).to.eql([ admin.id, user.id ].sort());
|
||||
assert.equal(result.name, group0Name);
|
||||
assert.deepEqual(result.userIds.sort(), [ admin.id, user.id ].sort());
|
||||
});
|
||||
|
||||
it('can set group membership', async function () {
|
||||
await groups.setLocalMembership(admin, [ group0Object.id ], auditSource);
|
||||
const groupIds = await groups._getMembership(admin.id);
|
||||
expect(groupIds.length).to.be(1);
|
||||
assert.equal(groupIds.length, 1);
|
||||
});
|
||||
|
||||
it('cannot set user to same group twice', async function () {
|
||||
const [error] = await safe(groups.setLocalMembership(admin, [ group0Object.id, group0Object.id ], auditSource));
|
||||
expect(error.reason).to.be(BoxError.CONFLICT);
|
||||
assert.equal(error.reason, BoxError.CONFLICT);
|
||||
});
|
||||
|
||||
it('can set user to multiple groups', async function () {
|
||||
@@ -135,32 +132,32 @@ describe('Groups', function () {
|
||||
|
||||
it('can get groups membership', async function () {
|
||||
const groupIds = await groups._getMembership(admin.id);
|
||||
expect(groupIds.length).to.be(2);
|
||||
expect(groupIds.sort()).to.eql([ group0Object.id, group1Object.id ].sort());
|
||||
assert.equal(groupIds.length, 2);
|
||||
assert.deepEqual(groupIds.sort(), [ group0Object.id, group1Object.id ].sort());
|
||||
});
|
||||
});
|
||||
|
||||
describe('list', function () {
|
||||
it('can list', async function () {
|
||||
const result = await groups.list();
|
||||
expect(result.length).to.be(2);
|
||||
expect(result[0].name).to.be(group0Name);
|
||||
expect(result[1].name).to.be(group1Name);
|
||||
assert.equal(result.length, 2);
|
||||
assert.equal(result[0].name, group0Name);
|
||||
assert.equal(result[1].name, group1Name);
|
||||
});
|
||||
|
||||
it('can listWithMembers', async function () {
|
||||
const result = await groups.listWithMembers();
|
||||
expect(result.length).to.be(2);
|
||||
expect(result[0].name).to.be(group0Name);
|
||||
expect(result[1].userIds).to.eql([ admin.id ]);
|
||||
expect(result[1].name).to.be(group1Name);
|
||||
assert.equal(result.length, 2);
|
||||
assert.equal(result[0].name, group0Name);
|
||||
assert.deepEqual(result[1].userIds, [ admin.id ]);
|
||||
assert.equal(result[1].name, group1Name);
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete', function () {
|
||||
it('cannot delete invalid group', async function () {
|
||||
const [error] = await safe(groups.del({ id: 'random' }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('can delete valid group', async function () {
|
||||
@@ -174,24 +171,24 @@ describe('Groups', function () {
|
||||
|
||||
before(async function () {
|
||||
const [error, result] = await safe(groups.add({ name: 'kootam' }, auditSource));
|
||||
expect(error).to.be(null);
|
||||
assert.equal(error, null);
|
||||
groupObject = result;
|
||||
});
|
||||
|
||||
it('cannot set empty group name', async function () {
|
||||
const [error] = await safe(groups.setName(groupObject, '', auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot set bad group name', async function () {
|
||||
const [error] = await safe(groups.setName(groupObject, '!kootam', auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can set group name', async function () {
|
||||
await groups.setName(groupObject, 'kootam2', auditSource);
|
||||
groupObject = await groups.get(groupObject.id);
|
||||
expect(groupObject.name).to.be('kootam2');
|
||||
assert.equal(groupObject.name, 'kootam2');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -200,55 +197,55 @@ describe('Groups', function () {
|
||||
|
||||
before(async function () {
|
||||
const [error, result] = await safe(groups.add({ name: 'kootam' }, auditSource));
|
||||
expect(error).to.be(null);
|
||||
assert.equal(error, null);
|
||||
groupObject = result;
|
||||
});
|
||||
|
||||
it('has no app access', async function () {
|
||||
expect(groupObject.appIds).to.eql([]);
|
||||
assert.deepEqual(groupObject.appIds, []);
|
||||
|
||||
const g1 = await groups.get(groupObject.id);
|
||||
expect(g1.appIds).to.eql([]);
|
||||
assert.deepEqual(g1.appIds, []);
|
||||
|
||||
const g2 = await groups.getByName(groupObject.name);
|
||||
expect(g2.appIds).to.eql([]);
|
||||
assert.deepEqual(g2.appIds, []);
|
||||
|
||||
const g3 = await groups.getWithMembers(groupObject.id);
|
||||
expect(g3.appIds).to.eql([]);
|
||||
assert.deepEqual(g3.appIds, []);
|
||||
});
|
||||
|
||||
it('set app access', async function () {
|
||||
await groups.setAllowedApps(groupObject, [ app.id ], auditSource);
|
||||
|
||||
const g1 = await groups.get(groupObject.id);
|
||||
expect(g1.appIds).to.eql([ app.id ]);
|
||||
assert.deepEqual(g1.appIds, [ app.id ]);
|
||||
|
||||
const g2 = await groups.getByName(groupObject.name);
|
||||
expect(g2.appIds).to.eql([ app.id ]);
|
||||
assert.deepEqual(g2.appIds, [ app.id ]);
|
||||
|
||||
const g3 = await groups.getWithMembers(groupObject.id);
|
||||
expect(g3.appIds).to.eql([ app.id ]);
|
||||
assert.deepEqual(g3.appIds, [ app.id ]);
|
||||
|
||||
const allGroups = await groups.listWithMembers();
|
||||
const g4 = allGroups.filter(g => g.id === groupObject.id)[0];
|
||||
expect(g4.appIds).to.eql([ app.id ]);
|
||||
assert.deepEqual(g4.appIds, [ app.id ]);
|
||||
});
|
||||
|
||||
it('cleared app access', async function () {
|
||||
await groups.setAllowedApps(groupObject, [ ], auditSource);
|
||||
|
||||
const g1 = await groups.get(groupObject.id);
|
||||
expect(g1.appIds).to.eql([ ]);
|
||||
assert.deepEqual(g1.appIds, [ ]);
|
||||
|
||||
const g2 = await groups.getByName(groupObject.name);
|
||||
expect(g2.appIds).to.eql([ ]);
|
||||
assert.deepEqual(g2.appIds, [ ]);
|
||||
|
||||
const g3 = await groups.getWithMembers(groupObject.id);
|
||||
expect(g3.appIds).to.eql([ ]);
|
||||
assert.deepEqual(g3.appIds, [ ]);
|
||||
|
||||
const allGroups = await groups.listWithMembers();
|
||||
const g4 = allGroups.filter(g => g.id === groupObject.id)[0];
|
||||
expect(g4.appIds).to.eql([ ]);
|
||||
assert.deepEqual(g4.appIds, [ ]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -261,17 +258,17 @@ describe('Groups', function () {
|
||||
|
||||
it('cannot change name', async function () {
|
||||
const [error] = await safe(groups.setName(ldapGroup, 'ldap-kootam2', auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_STATE);
|
||||
assert.equal(error.reason, BoxError.BAD_STATE);
|
||||
});
|
||||
|
||||
it('cannot set members', async function () {
|
||||
const [error] = await safe(groups.setMembers(ldapGroup, [ admin.id ], { skipSourceSkip: false }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_STATE);
|
||||
assert.equal(error.reason, BoxError.BAD_STATE);
|
||||
});
|
||||
|
||||
it('cannot set membership', async function () {
|
||||
const [error] = await safe(groups.setLocalMembership(admin, [ ldapGroup.id ], auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_STATE);
|
||||
assert.equal(error.reason, BoxError.BAD_STATE);
|
||||
});
|
||||
|
||||
it('does not clear remote membership', async function () {
|
||||
@@ -279,8 +276,8 @@ describe('Groups', function () {
|
||||
await groups.setLocalMembership(admin, [ group1Object.id ], auditSource);
|
||||
|
||||
const groupIds = await groups._getMembership(admin.id);
|
||||
expect(groupIds.length).to.be(2);
|
||||
expect(groupIds.sort()).to.eql([ group1Object.id, ldapGroup.id ].sort());
|
||||
assert.equal(groupIds.length, 2);
|
||||
assert.deepEqual(groupIds.sort(), [ group1Object.id, ldapGroup.id ].sort());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+24
-24
@@ -1,6 +1,6 @@
|
||||
/* global it, describe */
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import ipaddr from '../ipaddr.js';
|
||||
|
||||
describe('ipaddr', function () {
|
||||
@@ -9,11 +9,11 @@ describe('ipaddr', function () {
|
||||
const badIPv4s = [ '1.2.3', '1.2.3.256', '-1.2.3.4', '1e2.5.6.7', 'x.7.8.9', '1..2.4' ];
|
||||
|
||||
for (const goodIPv4 of goodIPv4s) {
|
||||
it(`isValid returns true ${goodIPv4}`, () => expect(ipaddr.isValid(goodIPv4)).to.be(true));
|
||||
it(`isValid returns true ${goodIPv4}`, () => assert.equal(ipaddr.isValid(goodIPv4), true));
|
||||
}
|
||||
|
||||
for (const badIPv4 of badIPv4s) {
|
||||
it(`isValid returns false ${badIPv4}`, () => expect(ipaddr.isValid(badIPv4)).to.be(false));
|
||||
it(`isValid returns false ${badIPv4}`, () => assert.equal(ipaddr.isValid(badIPv4), false));
|
||||
}
|
||||
|
||||
const goodCIDRs = [
|
||||
@@ -28,22 +28,22 @@ describe('ipaddr', function () {
|
||||
];
|
||||
|
||||
for (const goodCIDR of goodCIDRs) {
|
||||
it(`isValidCIDR returns true ${goodCIDR}`, () => expect(ipaddr.isValidCIDR(goodCIDR)).to.be(true));
|
||||
it(`isValidCIDR returns true ${goodCIDR}`, () => assert.equal(ipaddr.isValidCIDR(goodCIDR), true));
|
||||
}
|
||||
|
||||
for (const badCIDR of badCIDRs) {
|
||||
it(`isValidCIDR returns false ${badCIDR}`, () => expect(ipaddr.isValidCIDR(badCIDR)).to.be(false));
|
||||
it(`isValidCIDR returns false ${badCIDR}`, () => assert.equal(ipaddr.isValidCIDR(badCIDR), false));
|
||||
}
|
||||
|
||||
it('isEqual', function () {
|
||||
expect(ipaddr.isEqual('1.2.3.4', '1.2.3.4')).to.be(true);
|
||||
expect(ipaddr.isEqual('1.2.3.4', '1.2.3.5')).to.be(false);
|
||||
expect(ipaddr.isEqual('1.2.3.4', '1.2.3.')).to.be(false);
|
||||
assert.equal(ipaddr.isEqual('1.2.3.4', '1.2.3.4'), true);
|
||||
assert.equal(ipaddr.isEqual('1.2.3.4', '1.2.3.5'), false);
|
||||
assert.equal(ipaddr.isEqual('1.2.3.4', '1.2.3.'), false);
|
||||
});
|
||||
|
||||
it('includes', function () {
|
||||
expect(ipaddr.includes('1.2.3.0/8', '1.2.3.4')).to.be(true);
|
||||
expect(ipaddr.includes('1.2.0.0/16', '1.3.0.0')).to.be(false);
|
||||
assert.equal(ipaddr.includes('1.2.3.0/8', '1.2.3.4'), true);
|
||||
assert.equal(ipaddr.includes('1.2.0.0/16', '1.3.0.0'), false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -68,11 +68,11 @@ describe('ipaddr', function () {
|
||||
];
|
||||
|
||||
for (const goodIPv6 of goodIPv6s) {
|
||||
it(`isValid returns true ${goodIPv6}`, () => expect(ipaddr.isValid(goodIPv6)).to.be(true));
|
||||
it(`isValid returns true ${goodIPv6}`, () => assert.equal(ipaddr.isValid(goodIPv6), true));
|
||||
}
|
||||
|
||||
for (const badIPv6 of badIPv6s) {
|
||||
it(`isValid returns false ${badIPv6}`, () => expect(ipaddr.isValid(badIPv6)).to.be(false));
|
||||
it(`isValid returns false ${badIPv6}`, () => assert.equal(ipaddr.isValid(badIPv6), false));
|
||||
}
|
||||
|
||||
const goodCIDRs = [
|
||||
@@ -86,26 +86,26 @@ describe('ipaddr', function () {
|
||||
];
|
||||
|
||||
for (const goodCIDR of goodCIDRs) {
|
||||
it(`isValidCIDR returns true ${goodCIDR}`, () => expect(ipaddr.isValidCIDR(goodCIDR)).to.be(true));
|
||||
it(`isValidCIDR returns true ${goodCIDR}`, () => assert.equal(ipaddr.isValidCIDR(goodCIDR), true));
|
||||
}
|
||||
|
||||
for (const badCIDR of badCIDRs) {
|
||||
it(`isValidCIDR returns false ${badCIDR}`, () => expect(ipaddr.isValidCIDR(badCIDR)).to.be(false));
|
||||
it(`isValidCIDR returns false ${badCIDR}`, () => assert.equal(ipaddr.isValidCIDR(badCIDR), false));
|
||||
}
|
||||
|
||||
it('isEqual', function () {
|
||||
expect(ipaddr.isEqual('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334')).to.be(true); // same
|
||||
expect(ipaddr.isEqual('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3::0000:8a2e:0370:7334')).to.be(true); // shorthand
|
||||
expect(ipaddr.isEqual('2001:db8:85A3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3::0000:8a2e:370:7334')).to.be(true); // casing change and no 0 prefix
|
||||
expect(ipaddr.isEqual('2001:db8:85A3:0000:0000:8a2e:0370:7334', '1.2.3.4')).to.be(false);
|
||||
expect(ipaddr.isEqual('::ffff:1.2.3.4', '1.2.3.4')).to.be(true); // ipv6 mapped ipv4
|
||||
expect(ipaddr.isEqual('2002:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334')).to.be(false);
|
||||
assert.equal(ipaddr.isEqual('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334'), true); // same
|
||||
assert.equal(ipaddr.isEqual('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3::0000:8a2e:0370:7334'), true); // shorthand
|
||||
assert.equal(ipaddr.isEqual('2001:db8:85A3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3::0000:8a2e:370:7334'), true); // casing change and no 0 prefix
|
||||
assert.equal(ipaddr.isEqual('2001:db8:85A3:0000:0000:8a2e:0370:7334', '1.2.3.4'), false);
|
||||
assert.equal(ipaddr.isEqual('::ffff:1.2.3.4', '1.2.3.4'), true); // ipv6 mapped ipv4
|
||||
assert.equal(ipaddr.isEqual('2002:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334'), false);
|
||||
});
|
||||
|
||||
it('includes', function () {
|
||||
expect(ipaddr.includes('2001:0db8:85a3::/64', '2001:0db8:85a3:0000:0000:8a2e:0370:7334')).to.be(true);
|
||||
expect(ipaddr.includes('2001:0db8:85a3::/64', '2002:0db8:85a3:0000:0000:8a2e:0370:7334')).to.be(false);
|
||||
expect(ipaddr.includes('::ffff:0:0/96', '1.2.3.4')).to.be(true); // ipv6 mapped ipv4
|
||||
assert.equal(ipaddr.includes('2001:0db8:85a3::/64', '2001:0db8:85a3:0000:0000:8a2e:0370:7334'), true);
|
||||
assert.equal(ipaddr.includes('2001:0db8:85a3::/64', '2002:0db8:85a3:0000:0000:8a2e:0370:7334'), false);
|
||||
assert.equal(ipaddr.includes('::ffff:0:0/96', '1.2.3.4'), true); // ipv6 mapped ipv4
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import janitor from '../janitor.js';
|
||||
import tokens from '../tokens.js';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('janitor', function () {
|
||||
const { setup, cleanup } = common;
|
||||
@@ -49,12 +46,12 @@ describe('janitor', function () {
|
||||
|
||||
it('did not remove the non-expired token', async function () {
|
||||
const result = await tokens.getByAccessToken(token1.accessToken);
|
||||
expect(result).to.be.eql(token1);
|
||||
assert.deepEqual(result, token1);
|
||||
});
|
||||
|
||||
it('did remove the non-expired token', async function () {
|
||||
const result = await tokens.getByAccessToken(token2.accessToken);
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+106
-109
@@ -1,20 +1,17 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import addonConfigs from '../addonconfigs.js';
|
||||
import async from 'async';
|
||||
import common from './common.js';
|
||||
import constants from '../constants.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import groups from '../groups.js';
|
||||
import ldap from 'ldapjs';
|
||||
import ldapServer from '../ldapserver.js';
|
||||
import mail from '../mail.js';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
async function ldapBind(dn, password) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -70,8 +67,10 @@ describe('Ldap Server', function () {
|
||||
const mailAliasWildcardName = 'help';
|
||||
const mailAliasWildcard = `helpmeplz@${domain.domain}`;
|
||||
|
||||
before(function (done) {
|
||||
async.series([
|
||||
before(async function () {
|
||||
ldapServer._setMockApp(mockApp);
|
||||
|
||||
await async.series([
|
||||
setup,
|
||||
async () => await mail.addMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: true, storageQuota: 0, messagesQuota: 0, enablePop3: false }, auditSource),
|
||||
async () => await mail.setAliases(mailboxName, domain.domain, [ { name: mailAliasName, domain: domain.domain}, { name: mailAliasWildcardName + '*', domain: domain.domain } ], auditSource),
|
||||
@@ -84,38 +83,36 @@ describe('Ldap Server', function () {
|
||||
group2 = await groups.add({ name: 'ldap-test-2' }, auditSource);
|
||||
await groups.setMembers(group2, [ admin.id ], {}, auditSource);
|
||||
}
|
||||
], done);
|
||||
|
||||
ldapServer._setMockApp(mockApp);
|
||||
]);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
async.series([
|
||||
after(async function () {
|
||||
await async.series([
|
||||
ldapServer.stop,
|
||||
cleanup
|
||||
], done);
|
||||
]);
|
||||
});
|
||||
|
||||
describe('root DSE', function () {
|
||||
it('can get root DSE', async function () {
|
||||
const entries = await ldapSearch('', { filter: 'objectcategory=person' });
|
||||
expect(entries.length).to.be(1);
|
||||
expect(entries[0].dn).to.be('');
|
||||
expect(entries[0].supportedLDAPVersion).to.be('3');
|
||||
expect(entries[0].vendorName).to.be('Cloudron LDAP');
|
||||
expect(entries[0].vendorVersion).to.be('1.0.0');
|
||||
assert.equal(entries.length, 1);
|
||||
assert.equal(entries[0].dn, '');
|
||||
assert.equal(entries[0].supportedLDAPVersion, '3');
|
||||
assert.equal(entries[0].vendorName, 'Cloudron LDAP');
|
||||
assert.equal(entries[0].vendorVersion, '1.0.0');
|
||||
});
|
||||
});
|
||||
|
||||
describe('admin bind', function () {
|
||||
it('cn= fails for nonexisting user', async function () {
|
||||
const [error] = await safe(ldapBind('cn=doesnotexist,ou=users,dc=cloudron', 'password'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('cn= fails with wrong password', async function () {
|
||||
const [error] = await safe(ldapBind(`cn=${admin.id},ou=users,dc=cloudron`, 'wrongpassword'));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
});
|
||||
|
||||
it('cn= succeeds with id', async function () {
|
||||
@@ -132,7 +129,7 @@ describe('Ldap Server', function () {
|
||||
|
||||
it('mail= fails with bad email', async function () {
|
||||
const [error] = await safe(ldapBind('mail=random,ou=users,dc=cloudron', admin.password));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('mail= succeeds with email', async function () {
|
||||
@@ -149,7 +146,7 @@ describe('Ldap Server', function () {
|
||||
it('fails without accessRestriction', async function () {
|
||||
mockApp.accessRestriction = { users: [], groups: [] };
|
||||
const [error] = await safe(ldapBind(`cn=${user.id},ou=users,dc=cloudron`, user.password));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('succeeds with accessRestriction', async function () {
|
||||
@@ -161,60 +158,60 @@ describe('Ldap Server', function () {
|
||||
describe('search users', function () {
|
||||
it('fails for non existing tree', async function () {
|
||||
const [error] = await safe(ldapSearch('o=example', { filter: '(&(l=Seattle)(email=*@' + domain.domain + '))' }));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('succeeds with basic filter', async function () {
|
||||
const entries = await ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' });
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
entries.sort(function (a, b) { return a.username > b.username; });
|
||||
expect(entries[0].username).to.equal(admin.username.toLowerCase());
|
||||
expect(entries[0].mail).to.equal(admin.email.toLowerCase());
|
||||
expect(entries[1].username).to.equal(user.username.toLowerCase());
|
||||
expect(entries[1].mail).to.equal(user.email.toLowerCase());
|
||||
assert.equal(entries[0].username, admin.username.toLowerCase());
|
||||
assert.equal(entries[0].mail, admin.email.toLowerCase());
|
||||
assert.equal(entries[1].username, user.username.toLowerCase());
|
||||
assert.equal(entries[1].mail, user.email.toLowerCase());
|
||||
});
|
||||
|
||||
it('succeeds with pagination', async function () {
|
||||
const entries = await ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person', paged: true });
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
entries.sort(function (a, b) { return a.username > b.username; });
|
||||
expect(entries[0].username).to.equal(admin.username.toLowerCase());
|
||||
expect(entries[0].mail).to.equal(admin.email.toLowerCase());
|
||||
expect(entries[1].username).to.equal(user.username.toLowerCase());
|
||||
expect(entries[1].mail).to.equal(user.email.toLowerCase());
|
||||
assert.equal(entries[0].username, admin.username.toLowerCase());
|
||||
assert.equal(entries[0].mail, admin.email.toLowerCase());
|
||||
assert.equal(entries[1].username, user.username.toLowerCase());
|
||||
assert.equal(entries[1].mail, user.email.toLowerCase());
|
||||
});
|
||||
|
||||
it('succeeds with username wildcard filter', async function () {
|
||||
const entries = await ldapSearch('ou=users,dc=cloudron', { filter: '&(objectcategory=person)(username=*)' });
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
entries.sort(function (a, b) { return a.username > b.username; });
|
||||
expect(entries[0].username).to.equal(admin.username.toLowerCase());
|
||||
expect(entries[1].username).to.equal(user.username.toLowerCase());
|
||||
assert.equal(entries[0].username, admin.username.toLowerCase());
|
||||
assert.equal(entries[1].username, user.username.toLowerCase());
|
||||
});
|
||||
|
||||
it('succeeds with username filter', async function () {
|
||||
const entries = await ldapSearch('ou=users,dc=cloudron', { filter: '&(objectcategory=person)(username=' + admin.username + ')' });
|
||||
expect(entries.length).to.equal(1);
|
||||
expect(entries[0].username).to.equal(admin.username.toLowerCase());
|
||||
expect(entries[0].memberof.length).to.equal(2);
|
||||
assert.equal(entries.length, 1);
|
||||
assert.equal(entries[0].username, admin.username.toLowerCase());
|
||||
assert.equal(entries[0].memberof.length, 2);
|
||||
});
|
||||
|
||||
it('can always lists admins', async function () {
|
||||
mockApp.accessRestriction = { users: [], groups: [] };
|
||||
const entries = await ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' });
|
||||
expect(entries.length).to.equal(1);
|
||||
expect(entries[0].username).to.equal(admin.username.toLowerCase());
|
||||
expect(entries[0].memberof.length).to.equal(2);
|
||||
assert.equal(entries.length, 1);
|
||||
assert.equal(entries[0].username, admin.username.toLowerCase());
|
||||
assert.equal(entries[0].memberof.length, 2);
|
||||
});
|
||||
|
||||
it ('does only list users who have access', async function () {
|
||||
mockApp.accessRestriction = { users: [], groups: [ group.id ] };
|
||||
const entries = await ldapSearch('ou=users,dc=cloudron', { filter: 'objectcategory=person' });
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
entries.sort(function (a, b) { return a.username > b.username; });
|
||||
|
||||
expect(entries[0].username).to.equal(admin.username.toLowerCase());
|
||||
expect(entries[1].username).to.equal(user.username.toLowerCase());
|
||||
assert.equal(entries[0].username, admin.username.toLowerCase());
|
||||
assert.equal(entries[1].username, user.username.toLowerCase());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -223,107 +220,107 @@ describe('Ldap Server', function () {
|
||||
mockApp.accessRestriction = null;
|
||||
|
||||
const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: 'objectclass=group' });
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
|
||||
// ensure order for testability
|
||||
entries.sort(function (a, b) { return a.cn < b.cn; });
|
||||
|
||||
expect(entries[0].cn).to.equal('ldap-test-1');
|
||||
expect(entries[0].memberuid.length).to.equal(2);
|
||||
expect(entries[0].memberuid).to.contain(admin.id);
|
||||
expect(entries[0].memberuid).to.contain(user.id);
|
||||
assert.equal(entries[0].cn, 'ldap-test-1');
|
||||
assert.equal(entries[0].memberuid.length, 2);
|
||||
assert.ok(entries[0].memberuid.includes(admin.id));
|
||||
assert.ok(entries[0].memberuid.includes(user.id));
|
||||
|
||||
expect(entries[1].cn).to.equal('ldap-test-2');
|
||||
expect(entries[1].memberuid).to.equal(admin.id);
|
||||
assert.equal(entries[1].cn, 'ldap-test-2');
|
||||
assert.equal(entries[1].memberuid, admin.id);
|
||||
});
|
||||
|
||||
it ('succeeds with cn wildcard filter', async function () {
|
||||
const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: '&(objectclass=group)(cn=*)' });
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
|
||||
// ensure order for testability
|
||||
entries.sort(function (a, b) { return a.cn < b.cn; });
|
||||
|
||||
expect(entries[0].cn).to.equal('ldap-test-1');
|
||||
expect(entries[0].memberuid.length).to.equal(2);
|
||||
expect(entries[0].memberuid).to.contain(admin.id);
|
||||
expect(entries[0].memberuid).to.contain(user.id);
|
||||
assert.equal(entries[0].cn, 'ldap-test-1');
|
||||
assert.equal(entries[0].memberuid.length, 2);
|
||||
assert.ok(entries[0].memberuid.includes(admin.id));
|
||||
assert.ok(entries[0].memberuid.includes(user.id));
|
||||
|
||||
expect(entries[1].cn).to.equal('ldap-test-2');
|
||||
expect(entries[1].memberuid).to.equal(admin.id);
|
||||
assert.equal(entries[1].cn, 'ldap-test-2');
|
||||
assert.equal(entries[1].memberuid, admin.id);
|
||||
});
|
||||
|
||||
it('succeeds with memberuid filter', async function () {
|
||||
const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: '&(objectclass=group)(memberuid=' + user.id + ')' });
|
||||
expect(entries.length).to.equal(1);
|
||||
assert.equal(entries.length, 1);
|
||||
|
||||
// ensure order for testability
|
||||
entries.sort(function (a, b) { return a.cn < b.cn; });
|
||||
|
||||
expect(entries[0].cn).to.equal('ldap-test-1');
|
||||
expect(entries[0].memberuid.length).to.equal(2);
|
||||
expect(entries[0].memberuid).to.contain(admin.id);
|
||||
expect(entries[0].memberuid).to.contain(user.id);
|
||||
assert.equal(entries[0].cn, 'ldap-test-1');
|
||||
assert.equal(entries[0].memberuid.length, 2);
|
||||
assert.ok(entries[0].memberuid.includes(admin.id));
|
||||
assert.ok(entries[0].memberuid.includes(user.id));
|
||||
});
|
||||
|
||||
it ('does only list groups who have access', async function () {
|
||||
mockApp.accessRestriction = { users: [], groups: [ group.id ] };
|
||||
const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: '&(objectclass=group)(cn=*)' });
|
||||
expect(entries.length).to.equal(1);
|
||||
assert.equal(entries.length, 1);
|
||||
|
||||
// ensure order for testability
|
||||
entries.sort(function (a, b) { return a.cn < b.cn; });
|
||||
|
||||
expect(entries[0].cn).to.equal('ldap-test-1');
|
||||
expect(entries[0].memberuid.length).to.equal(2);
|
||||
expect(entries[0].memberuid).to.contain(admin.id);
|
||||
expect(entries[0].memberuid).to.contain(user.id);
|
||||
assert.equal(entries[0].cn, 'ldap-test-1');
|
||||
assert.equal(entries[0].memberuid.length, 2);
|
||||
assert.ok(entries[0].memberuid.includes(admin.id));
|
||||
assert.ok(entries[0].memberuid.includes(user.id));
|
||||
});
|
||||
|
||||
it ('succeeds with pagination', async function () {
|
||||
mockApp.accessRestriction = null;
|
||||
const entries = await ldapSearch('ou=groups,dc=cloudron', { filter: 'objectclass=group', paged: true });
|
||||
expect(entries.length).to.equal(2);
|
||||
assert.equal(entries.length, 2);
|
||||
|
||||
// ensure order for testability
|
||||
entries.sort(function (a, b) { return a.cn < b.cn; });
|
||||
|
||||
expect(entries[0].cn).to.equal('ldap-test-1');
|
||||
expect(entries[0].memberuid.length).to.equal(2);
|
||||
expect(entries[0].memberuid).to.contain(admin.id);
|
||||
expect(entries[0].memberuid).to.contain(user.id);
|
||||
assert.equal(entries[0].cn, 'ldap-test-1');
|
||||
assert.equal(entries[0].memberuid.length, 2);
|
||||
assert.ok(entries[0].memberuid.includes(admin.id));
|
||||
assert.ok(entries[0].memberuid.includes(user.id));
|
||||
|
||||
expect(entries[1].cn).to.equal('ldap-test-2');
|
||||
expect(entries[1].memberuid).to.equal(admin.id);
|
||||
assert.equal(entries[1].cn, 'ldap-test-2');
|
||||
assert.equal(entries[1].memberuid, admin.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mailbox search', function () {
|
||||
it('get specific mailbox by email', async function () {
|
||||
const entries = await ldapSearch(`cn=${mailbox},ou=mailboxes,dc=cloudron`, 'objectclass=mailbox');
|
||||
expect(entries.length).to.equal(1);
|
||||
expect(entries[0].cn).to.equal(mailbox);
|
||||
assert.equal(entries.length, 1);
|
||||
assert.equal(entries[0].cn, mailbox);
|
||||
});
|
||||
|
||||
it('cannot get mailbox with just name', async function () {
|
||||
const [error] = await safe(ldapSearch(`cn=${mailboxName},ou=mailboxes,dc=cloudron`, 'objectclass=mailbox'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('cannot get alias as a mailbox', async function () {
|
||||
const [error] = await safe(ldapSearch(`cn=${mailAlias},ou=mailboxes,dc=cloudron`, 'objectclass=mailbox'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('non-existent mailbox', async function () {
|
||||
const [error] = await safe(ldapSearch(`cn=random@${domain.domain},ou=mailboxes,dc=cloudron`, 'objectclass=mailbox'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('cannot get inactive mailbox', async function () {
|
||||
await mail.updateMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: false, enablePop3: false }, auditSource);
|
||||
const [error] = await safe(ldapSearch(`cn=${mailbox},ou=mailboxes,dc=cloudron`, 'objectclass=mailbox'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
|
||||
await mail.updateMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: true, enablePop3: false }, auditSource);
|
||||
});
|
||||
@@ -332,26 +329,26 @@ describe('Ldap Server', function () {
|
||||
describe('search aliases', function () {
|
||||
it('get specific alias', async function () {
|
||||
const entries = await ldapSearch(`cn=${mailAlias},ou=mailaliases,dc=cloudron`, 'objectclass=nismailalias');
|
||||
expect(entries.length).to.equal(1);
|
||||
expect(entries[0].cn).to.equal(mailAlias);
|
||||
expect(entries[0].rfc822MailMember).to.equal(mailbox);
|
||||
assert.equal(entries.length, 1);
|
||||
assert.equal(entries[0].cn, mailAlias);
|
||||
assert.equal(entries[0].rfc822MailMember, mailbox);
|
||||
});
|
||||
|
||||
it('get alias matching wildcard', async function () {
|
||||
const entries = await ldapSearch(`cn=${mailAliasWildcard},ou=mailaliases,dc=cloudron`, 'objectclass=nismailalias');
|
||||
expect(entries.length).to.equal(1);
|
||||
expect(entries[0].cn).to.equal(mailAliasWildcard);
|
||||
expect(entries[0].rfc822MailMember).to.equal(mailbox);
|
||||
assert.equal(entries.length, 1);
|
||||
assert.equal(entries[0].cn, mailAliasWildcard);
|
||||
assert.equal(entries[0].rfc822MailMember, mailbox);
|
||||
});
|
||||
|
||||
it('cannot get mailbox as alias', async function () {
|
||||
const [error] = await safe(ldapSearch(`cn=${mailbox},ou=mailaliases,dc=cloudron`, 'objectclass=nismailalias'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('non-existent alias', async function () {
|
||||
const [error] = await safe(ldapSearch(`cn=random@${domain.domain},ou=mailaliases,dc=cloudron`, 'objectclass=mailbox'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -364,33 +361,33 @@ describe('Ldap Server', function () {
|
||||
|
||||
it('get specific list', async function () {
|
||||
const entries = await ldapSearch(`cn=${LIST},ou=mailinglists,dc=cloudron`, 'objectclass=mailGroup');
|
||||
expect(entries.length).to.equal(1);
|
||||
expect(entries[0].cn).to.equal(LIST);
|
||||
expect(entries[0].mgrpRFC822MailMember).to.eql([ mailbox, 'outsider@external.com' ]);
|
||||
assert.equal(entries.length, 1);
|
||||
assert.equal(entries[0].cn, LIST);
|
||||
assert.deepEqual(entries[0].mgrpRFC822MailMember, [ mailbox, 'outsider@external.com' ]);
|
||||
});
|
||||
|
||||
it('non-existent list', async function () {
|
||||
const [error] = await safe(ldapSearch('cn=random@example.com,ou=mailinglists,dc=cloudron', 'objectclass=mailGroup'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('inactive list', async function () {
|
||||
await mail.updateMailingList(LIST_NAME, domain.domain, { members: [ mailbox , 'outsider@external.com' ], membersOnly: false, active: false }, auditSource);
|
||||
const [error] = await safe(ldapSearch('cn=devs@example.com,ou=mailinglists,dc=cloudron', 'objectclass=mailGroup'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
});
|
||||
|
||||
describe('sogo mailbox bind', function () {
|
||||
it('email disabled - cannot auth', async function () {
|
||||
const [error] = await safe(ldapBind(`cn=${mailbox},domain=example.com,ou=mailboxes,dc=cloudron`, 'badpassword'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('email enabled - does not allow with invalid password', async function () {
|
||||
await mail._updateDomain(domain.domain, { enabled: true });
|
||||
const [error] = await safe(ldapBind(`cn=${mailbox},domain=example.com,ou=mailboxes,dc=cloudron`, 'badpassword'));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
await mail._updateDomain(domain.domain, { enabled: false });
|
||||
});
|
||||
|
||||
@@ -403,7 +400,7 @@ describe('Ldap Server', function () {
|
||||
it('email enabled - cannot auth with alias', async function () {
|
||||
await mail._updateDomain(domain.domain, { enabled: true });
|
||||
const [error] = await safe(ldapBind(`cn=${mailAlias},domain=example.com,ou=mailboxes,dc=cloudron`, 'badpassword'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
await mail._updateDomain(domain.domain, { enabled: false });
|
||||
});
|
||||
});
|
||||
@@ -412,7 +409,7 @@ describe('Ldap Server', function () {
|
||||
it('email disabled - cannot find domain email', async function () {
|
||||
await mail._updateDomain(domain.domain, { enabled: false });
|
||||
const [error] = await safe(ldapBind(`cn=${mailbox},ou=msa,dc=cloudron`, 'badpassword'));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
});
|
||||
|
||||
it('email enabled - allows with valid email', async function () {
|
||||
@@ -424,7 +421,7 @@ describe('Ldap Server', function () {
|
||||
it('email enabled - does not allow with invalid password', async function () {
|
||||
await mail._updateDomain(domain.domain, { enabled: true });
|
||||
const [error] = await safe(ldapBind(`cn=${mailbox},ou=msa,dc=cloudron`, 'badpassword'));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
await mail._updateDomain(domain.domain, { enabled: false });
|
||||
});
|
||||
|
||||
@@ -432,7 +429,7 @@ describe('Ldap Server', function () {
|
||||
await mail._updateDomain(domain.domain, { enabled: true });
|
||||
await mail.updateMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: false, enablePop3: false }, auditSource);
|
||||
const [error] = await safe(ldapBind(`cn=${mailbox},ou=msa,dc=cloudron`, 'badpassword'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
await mail.updateMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: true, enablePop3: false }, auditSource);
|
||||
});
|
||||
});
|
||||
@@ -445,12 +442,12 @@ describe('Ldap Server', function () {
|
||||
|
||||
it('does not allow with invalid app', async function () {
|
||||
const [error] = await safe(ldapBind(`cn=hacker.app@${domain.domain},ou=msa,dc=cloudron`, 'nope'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('does not allow with invalid password', async function () {
|
||||
const [error] = await safe(ldapBind(`cn=${app.subdomain}.app@${domain.domain},ou=msa,dc=cloudron`, 'nope'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('allows with valid password', async function () {
|
||||
@@ -464,7 +461,7 @@ describe('Ldap Server', function () {
|
||||
it('email disabled - cannot find domain email', async function () {
|
||||
await mail._updateDomain(domain.domain, { enabled: false });
|
||||
const [error] = await safe(ldapBind(`cn=${mailbox},ou=imap,dc=cloudron`, 'badpassword'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('email enabled - allows with valid email', async function () {
|
||||
@@ -475,14 +472,14 @@ describe('Ldap Server', function () {
|
||||
it('email enabled - does not allow with invalid password', async function () {
|
||||
await mail._updateDomain(domain.domain, { enabled: true });
|
||||
const [error] = await safe(ldapBind(`cn=${mailbox},ou=imap,dc=cloudron`, 'badpassword'));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
});
|
||||
|
||||
it('does not allow for inactive mailbox', async function () {
|
||||
await mail._updateDomain(domain.domain, { enabled: true });
|
||||
await mail.updateMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: false, enablePop3: false }, auditSource);
|
||||
const [error] = await safe(ldapBind(`cn=${mailbox},ou=imap,dc=cloudron`, 'badpassword'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
await mail._updateDomain(domain.domain, { enabled: false });
|
||||
await mail.updateMailbox(mailboxName, domain.domain, { ownerId: user.id, ownerType: mail.OWNERTYPE_USER, active: true, enablePop3: false }, auditSource);
|
||||
});
|
||||
@@ -495,19 +492,19 @@ describe('Ldap Server', function () {
|
||||
|
||||
it('does not allow with invalid app', async function () {
|
||||
const [error] = await safe(ldapBind(`cn=hacker.app@${domain.domain},ou=imap,dc=cloudron`, 'nope'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('does not allow with valid password (missing mailbox)', async function () {
|
||||
await addonConfigs.set(app.id, 'recvmail', [{ name: 'MAIL_IMAP_USERNAME', value : `${app.subdomain}.app@${domain.domain}` }, { name: 'MAIL_IMAP_PASSWORD', value : 'imappassword' }]);
|
||||
const [error] = await safe(ldapBind(`cn=${app.subdomain}.app@${domain.domain},ou=imap,dc=cloudron`, 'imappassword'));
|
||||
expect(error).to.be.a(ldap.NoSuchObjectError);
|
||||
assert.ok((error) instanceof (ldap.NoSuchObjectError));
|
||||
});
|
||||
|
||||
it('does not allow with invalid password', async function () {
|
||||
await addonConfigs.set(app.id, 'recvmail', [{ name: 'MAIL_IMAP_USERNAME', value : `${mailboxName}@${domain.domain}` }, { name: 'MAIL_IMAP_PASSWORD', value : 'imappassword' }]);
|
||||
const [error] = await safe(ldapBind(`cn=${mailboxName}@${domain.domain},ou=imap,dc=cloudron`, 'nope'));
|
||||
expect(error).to.be.a(ldap.InvalidCredentialsError);
|
||||
assert.ok((error) instanceof (ldap.InvalidCredentialsError));
|
||||
});
|
||||
|
||||
it('allows with valid password', async function () {
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
/* global it, describe, before, after */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
import locks from '../locks.js';
|
||||
|
||||
describe('Locks', function () {
|
||||
this.timeout(20000);
|
||||
describe('Locks', { timeout: 20000 }, function () {
|
||||
|
||||
const { setup, cleanup } = common;
|
||||
|
||||
@@ -24,7 +23,7 @@ describe('Locks', function () {
|
||||
|
||||
it('cannot reacquire lock foo', async function () {
|
||||
const [error] = await safe(locks.acquire('foo'));
|
||||
expect(error.reason).to.be(BoxError.BAD_STATE);
|
||||
assert.equal(error.reason, BoxError.BAD_STATE);
|
||||
});
|
||||
|
||||
it('cannot reacquire after release', async function () {
|
||||
@@ -43,7 +42,7 @@ describe('Locks', function () {
|
||||
const startTime = Date.now();
|
||||
await locks.wait('tasklock'); // retries only in 10s
|
||||
const endTime = Date.now();
|
||||
expect(endTime - startTime).to.be.greaterThan(9900);
|
||||
expect(endTime - startTime).to.be.lessThan(10100);
|
||||
assert.ok((endTime - startTime) > (9900));
|
||||
assert.ok((endTime - startTime) < (10100));
|
||||
});
|
||||
});
|
||||
|
||||
+14
-13
@@ -1,28 +1,29 @@
|
||||
/* global it:false */
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import logs from '../logs.js';
|
||||
import stream from 'node:stream';
|
||||
|
||||
/* global describe:false */
|
||||
|
||||
describe('log stream', function () {
|
||||
it('can create stream', function (done) {
|
||||
it('can create stream', async function () {
|
||||
fs.writeFileSync('/tmp/test-input.log', '2022-10-09T15:19:48.740Z message', 'utf8');
|
||||
const input = fs.createReadStream('/tmp/test-input.log');
|
||||
const log = new logs.LogStream({ format: 'json', source: 'test' });
|
||||
const output = fs.createWriteStream('/tmp/test-output.log');
|
||||
|
||||
stream.pipeline(input, log, output, function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
|
||||
const out = fs.readFileSync('/tmp/test-output.log', 'utf8');
|
||||
const firstLine = JSON.parse(out.split('\n')[0]);
|
||||
expect(firstLine.realtimeTimestamp).to.be.a('number');
|
||||
expect(firstLine.message).to.be('message');
|
||||
expect(firstLine.source).to.be('test');
|
||||
done();
|
||||
await new Promise((resolve, reject) => {
|
||||
stream.pipeline(input, log, output, function (error) {
|
||||
if (error) return reject(error);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
const out = fs.readFileSync('/tmp/test-output.log', 'utf8');
|
||||
const firstLine = JSON.parse(out.split('\n')[0]);
|
||||
assert.equal(typeof firstLine.realtimeTimestamp, 'number');
|
||||
assert.equal(firstLine.message, 'message');
|
||||
assert.equal(firstLine.source, 'test');
|
||||
});
|
||||
});
|
||||
|
||||
+75
-78
@@ -1,14 +1,11 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import common from './common.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import mail from '../mail.js';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Mail', function () {
|
||||
const { setup, cleanup, domain, auditSource } = common;
|
||||
@@ -19,36 +16,36 @@ describe('Mail', function () {
|
||||
describe('settings', function () {
|
||||
it('can get default', async function () {
|
||||
const mailConfig = await mail.getDomain(domain.domain);
|
||||
expect(mailConfig.enabled).to.be(false);
|
||||
expect(mailConfig.mailFromValidation).to.be(true);
|
||||
expect(mailConfig.catchAll).to.eql([]);
|
||||
expect(mailConfig.relay).to.eql({ provider: 'cloudron-smtp' });
|
||||
assert.equal(mailConfig.enabled, false);
|
||||
assert.equal(mailConfig.mailFromValidation, true);
|
||||
assert.deepEqual(mailConfig.catchAll, []);
|
||||
assert.deepEqual(mailConfig.relay, { provider: 'cloudron-smtp' });
|
||||
});
|
||||
|
||||
it('can get all domains', async function () {
|
||||
const result = await mail.listDomains();
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result[0]).to.be.an('object');
|
||||
expect(result[0].domain).to.eql(domain.domain);
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(typeof result[0], 'object');
|
||||
assert.deepEqual(result[0].domain, domain.domain);
|
||||
});
|
||||
|
||||
it('can set mail from validation', async function () {
|
||||
await mail.setMailFromValidation(domain.domain, false);
|
||||
|
||||
const mailConfig = await mail.getDomain(domain.domain);
|
||||
expect(mailConfig.mailFromValidation).to.be(false);
|
||||
assert.equal(mailConfig.mailFromValidation, false);
|
||||
});
|
||||
|
||||
it('cannot set invalid catch all address', async function () {
|
||||
const [error] = await safe(mail.setCatchAllAddress(domain.domain, [ 'user1' ]));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can set invalid catch all address', async function () {
|
||||
await mail.setCatchAllAddress(domain.domain, [ `user1@${domain.domain}`, `user2@${domain.domain}` ]);
|
||||
|
||||
const mailConfig = await mail.getDomain(domain.domain);
|
||||
expect(mailConfig.catchAll).to.eql([ `user1@${domain.domain}`, `user2@${domain.domain}` ]);
|
||||
assert.deepEqual(mailConfig.catchAll, [ `user1@${domain.domain}`, `user2@${domain.domain}` ]);
|
||||
});
|
||||
|
||||
it('can set mail relay', async function () {
|
||||
@@ -57,7 +54,7 @@ describe('Mail', function () {
|
||||
await mail.setMailRelay(domain.domain, relay, { skipVerify: true });
|
||||
|
||||
const mailConfig = await mail.getDomain(domain.domain);
|
||||
expect(mailConfig.relay).to.eql(relay);
|
||||
assert.deepEqual(mailConfig.relay, relay);
|
||||
});
|
||||
|
||||
it('can set banner', async function () {
|
||||
@@ -66,52 +63,52 @@ describe('Mail', function () {
|
||||
await mail.setBanner(domain.domain, banner);
|
||||
|
||||
const mailConfig = await mail.getDomain(domain.domain);
|
||||
expect(mailConfig.banner).to.eql(banner);
|
||||
assert.deepEqual(mailConfig.banner, banner);
|
||||
});
|
||||
|
||||
it('can enable mail', async function () {
|
||||
await mail.setMailEnabled(domain.domain, true, auditSource);
|
||||
|
||||
const mailConfig = await mail.getDomain(domain.domain);
|
||||
expect(mailConfig.enabled).to.be(true);
|
||||
assert.equal(mailConfig.enabled, true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mailbox name', function () {
|
||||
it('allows valid names', function () {
|
||||
expect(mail.validateName('1')).to.be(null); // single char
|
||||
expect(mail.validateName('ap')).to.be(null); // alpha
|
||||
expect(mail.validateName('aP')).to.be(null); // caps
|
||||
expect(mail.validateName('0P')).to.be(null); // number
|
||||
expect(mail.validateName('a.p.x')).to.be(null); // dot
|
||||
expect(mail.validateName('a-p-x')).to.be(null); // hyphen
|
||||
expect(mail.validateName('a-p_x')).to.be(null); // underscore
|
||||
assert.equal(mail.validateName('1'), null); // single char
|
||||
assert.equal(mail.validateName('ap'), null); // alpha
|
||||
assert.equal(mail.validateName('aP'), null); // caps
|
||||
assert.equal(mail.validateName('0P'), null); // number
|
||||
assert.equal(mail.validateName('a.p.x'), null); // dot
|
||||
assert.equal(mail.validateName('a-p-x'), null); // hyphen
|
||||
assert.equal(mail.validateName('a-p_x'), null); // underscore
|
||||
});
|
||||
|
||||
it('disallows invalid names', function () {
|
||||
expect(mail.validateName('@')).to.be.an(Error);
|
||||
expect(mail.validateName('a+p')).to.be.an(Error);
|
||||
expect(mail.validateName('a#p')).to.be.an(Error);
|
||||
expect(mail.validateName('a!')).to.be.an(Error);
|
||||
assert.ok((mail.validateName('@')) instanceof (Error));
|
||||
assert.ok((mail.validateName('a+p')) instanceof (Error));
|
||||
assert.ok((mail.validateName('a#p')) instanceof (Error));
|
||||
assert.ok((mail.validateName('a!')) instanceof (Error));
|
||||
});
|
||||
});
|
||||
|
||||
describe('mailbox display name', function () {
|
||||
it('allows valid names', function () {
|
||||
expect(mail.validateDisplayName('1')).to.be(null); // single char
|
||||
expect(mail.validateDisplayName('ap')).to.be(null); // alpha
|
||||
expect(mail.validateDisplayName('aP')).to.be(null); // caps
|
||||
expect(mail.validateDisplayName('0P')).to.be(null); // number
|
||||
expect(mail.validateDisplayName('a p.x')).to.be(null); // space
|
||||
expect(mail.validateDisplayName('a-p-x')).to.be(null); // hyphen
|
||||
expect(mail.validateDisplayName('a-p_x')).to.be(null); // underscore
|
||||
assert.equal(mail.validateDisplayName('1'), null); // single char
|
||||
assert.equal(mail.validateDisplayName('ap'), null); // alpha
|
||||
assert.equal(mail.validateDisplayName('aP'), null); // caps
|
||||
assert.equal(mail.validateDisplayName('0P'), null); // number
|
||||
assert.equal(mail.validateDisplayName('a p.x'), null); // space
|
||||
assert.equal(mail.validateDisplayName('a-p-x'), null); // hyphen
|
||||
assert.equal(mail.validateDisplayName('a-p_x'), null); // underscore
|
||||
});
|
||||
|
||||
it('disallows invalid names', function () {
|
||||
expect(mail.validateDisplayName('@')).to.be.an(Error);
|
||||
expect(mail.validateDisplayName('a<p')).to.be.an(Error);
|
||||
expect(mail.validateDisplayName('a>p')).to.be.an(Error);
|
||||
expect(mail.validateDisplayName('a"x"')).to.be.an(Error);
|
||||
assert.ok((mail.validateDisplayName('@')) instanceof (Error));
|
||||
assert.ok((mail.validateDisplayName('a<p')) instanceof (Error));
|
||||
assert.ok((mail.validateDisplayName('a>p')) instanceof (Error));
|
||||
assert.ok((mail.validateDisplayName('a"x"')) instanceof (Error));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -122,7 +119,7 @@ describe('Mail', function () {
|
||||
|
||||
it('cannot add dup entry', async function () {
|
||||
const [error] = await safe(mail.addMailbox('girish', domain.domain, { ownerId: 'uid-1', ownerType: mail.OWNERTYPE_GROUP, active: true, enablePop3: false, storageQuota: 0, messagesQuota: 0 }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('add app mailbox succeeds', async function () {
|
||||
@@ -131,48 +128,48 @@ describe('Mail', function () {
|
||||
|
||||
it('get succeeds', async function () {
|
||||
const mailbox = await mail.getMailbox('support', domain.domain);
|
||||
expect(mailbox.name).to.equal('support');
|
||||
expect(mailbox.ownerId).to.equal('osticket');
|
||||
expect(mailbox.domain).to.equal(domain.domain);
|
||||
expect(mailbox.creationTime).to.be.a(Date);
|
||||
expect(mailbox.storageQuota).to.be(10);
|
||||
expect(mailbox.messagesQuota).to.be(20);
|
||||
expect(mailbox.enablePop3).to.be(true);
|
||||
assert.equal(mailbox.name, 'support');
|
||||
assert.equal(mailbox.ownerId, 'osticket');
|
||||
assert.equal(mailbox.domain, domain.domain);
|
||||
assert.ok((mailbox.creationTime) instanceof (Date));
|
||||
assert.equal(mailbox.storageQuota, 10);
|
||||
assert.equal(mailbox.messagesQuota, 20);
|
||||
assert.equal(mailbox.enablePop3, true);
|
||||
});
|
||||
|
||||
it('get non-existent mailbox', async function () {
|
||||
const mailbox = await mail.getMailbox('random', domain.domain);
|
||||
expect(mailbox).to.be(null);
|
||||
assert.equal(mailbox, null);
|
||||
});
|
||||
|
||||
it('update app mailbox succeeds', async function () {
|
||||
await mail.updateMailbox('support', domain.domain, { ownerId: 'osticket', ownerType: 'user', active: true, enablePop3: true, storageQuota: 20, messagesQuota: 30}, auditSource);
|
||||
|
||||
const mailbox = await mail.getMailbox('support', domain.domain);
|
||||
expect(mailbox.storageQuota).to.be(20);
|
||||
expect(mailbox.messagesQuota).to.be(30);
|
||||
expect(mailbox.enablePop3).to.be(true);
|
||||
assert.equal(mailbox.storageQuota, 20);
|
||||
assert.equal(mailbox.messagesQuota, 30);
|
||||
assert.equal(mailbox.enablePop3, true);
|
||||
});
|
||||
|
||||
it('list mailboxes by domain succeeds', async function () {
|
||||
const mailboxes = await mail.listMailboxesByDomain(domain.domain, 1, 10);
|
||||
expect(mailboxes.length).to.be(2);
|
||||
expect(mailboxes[0].name).to.be('girish');
|
||||
expect(mailboxes[1].name).to.be('support');
|
||||
assert.equal(mailboxes.length, 2);
|
||||
assert.equal(mailboxes[0].name, 'girish');
|
||||
assert.equal(mailboxes[1].name, 'support');
|
||||
});
|
||||
|
||||
it('list all mailboxes succeeds', async function () {
|
||||
const mailboxes = await mail.listMailboxes(1, 10);
|
||||
expect(mailboxes.length).to.be(2);
|
||||
expect(mailboxes[0].name).to.be('girish');
|
||||
expect(mailboxes[0].domain).to.be(domain.domain);
|
||||
expect(mailboxes[1].name).to.be('support');
|
||||
expect(mailboxes[1].domain).to.be(domain.domain);
|
||||
assert.equal(mailboxes.length, 2);
|
||||
assert.equal(mailboxes[0].name, 'girish');
|
||||
assert.equal(mailboxes[0].domain, domain.domain);
|
||||
assert.equal(mailboxes[1].name, 'support');
|
||||
assert.equal(mailboxes[1].domain, domain.domain);
|
||||
});
|
||||
|
||||
it('mailbox count succeeds', async function () {
|
||||
const stats = await mail.getStats(domain.domain);
|
||||
expect(stats.mailboxCount).to.be(2);
|
||||
assert.equal(stats.mailboxCount, 2);
|
||||
});
|
||||
|
||||
it('can set alias', async function () {
|
||||
@@ -181,11 +178,11 @@ describe('Mail', function () {
|
||||
|
||||
it('can get aliases of name', async function () {
|
||||
const results = await mail.getAliases('support', domain.domain);
|
||||
expect(results.length).to.be(2);
|
||||
expect(results[0].name).to.be('help');
|
||||
expect(results[0].domain).to.be(domain.domain);
|
||||
expect(results[1].name).to.be('support2');
|
||||
expect(results[1].domain).to.be(domain.domain);
|
||||
assert.equal(results.length, 2);
|
||||
assert.equal(results[0].name, 'help');
|
||||
assert.equal(results[0].domain, domain.domain);
|
||||
assert.equal(results[1].name, 'support2');
|
||||
assert.equal(results[1].domain, domain.domain);
|
||||
});
|
||||
|
||||
it('can set wildcard alias', async function () {
|
||||
@@ -194,18 +191,18 @@ describe('Mail', function () {
|
||||
|
||||
it('can get aliases of name', async function () {
|
||||
const results = await mail.getAliases('support', domain.domain);
|
||||
expect(results.length).to.be(2);
|
||||
expect(results[0].name).to.be('help');
|
||||
expect(results[0].domain).to.be(domain.domain);
|
||||
expect(results[1].name).to.be('support*');
|
||||
expect(results[1].domain).to.be(domain.domain);
|
||||
assert.equal(results.length, 2);
|
||||
assert.equal(results[0].name, 'help');
|
||||
assert.equal(results[0].domain, domain.domain);
|
||||
assert.equal(results[1].name, 'support*');
|
||||
assert.equal(results[1].domain, domain.domain);
|
||||
});
|
||||
|
||||
it('unset aliases', async function () {
|
||||
await mail.setAliases('support', domain.domain, [], auditSource);
|
||||
|
||||
const results = await mail.getAliases('support', domain.domain);
|
||||
expect(results.length).to.be(0);
|
||||
assert.equal(results.length, 0);
|
||||
});
|
||||
|
||||
it('add list succeeds', async function () {
|
||||
@@ -214,34 +211,34 @@ describe('Mail', function () {
|
||||
|
||||
it('cannot add dup list', async function () {
|
||||
const [error] = await safe(mail.addMailingList('people', domain.domain, { members: [ 'admin@cloudron.io' ], membersOnly: false, active: true }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('cannot get non-existing list', async function () {
|
||||
const result = await mail.getMailingList('random', domain.domain);
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('del list succeeds', async function () {
|
||||
await mail.delMailingList('people', domain.domain, auditSource);
|
||||
const result = await mail.getMailingList('people', domain.domain);
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('del non-existent list fails', async function () {
|
||||
const [error] = await safe(mail.delMailingList('people', domain.domain, auditSource));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('del mailbox succeeds', async function () {
|
||||
await mail.delMailbox('girish', domain.domain, {/*options*/}, auditSource);
|
||||
const result = await mail.getMailbox('girish', domain.domain);
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('del non-existent mailbox fails', async function () {
|
||||
const [error] = await safe(mail.delMailbox('girish', domain.domain, {/*options*/}, auditSource));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import mailPasswords from '../mailpasswords.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Mail passwords', function () {
|
||||
const { setup, cleanup, admin, app } = common;
|
||||
@@ -19,48 +16,48 @@ describe('Mail passwords', function () {
|
||||
|
||||
it('cannot add with empty appId', async function () {
|
||||
const [error] = await safe(mailPasswords.add('', admin.id, 'token123'));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot add with empty userId', async function () {
|
||||
const [error] = await safe(mailPasswords.add(app.id, '', 'token123'));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot add with empty password', async function () {
|
||||
const [error] = await safe(mailPasswords.add(app.id, admin.id, ''));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can add mail password', async function () {
|
||||
const result = await mailPasswords.add(app.id, admin.id, 'secret-token');
|
||||
expect(result.appId).to.be(app.id);
|
||||
expect(result.userId).to.be(admin.id);
|
||||
assert.equal(result.appId, app.id);
|
||||
assert.equal(result.userId, admin.id);
|
||||
});
|
||||
|
||||
it('can get mail password', async function () {
|
||||
const result = await mailPasswords.get(app.id, admin.id);
|
||||
expect(result).to.be.ok();
|
||||
expect(result.appId).to.be(app.id);
|
||||
expect(result.userId).to.be(admin.id);
|
||||
expect(result.password).to.be('secret-token');
|
||||
assert.ok(result);
|
||||
assert.equal(result.appId, app.id);
|
||||
assert.equal(result.userId, admin.id);
|
||||
assert.equal(result.password, 'secret-token');
|
||||
});
|
||||
|
||||
it('cannot get random mail password', async function () {
|
||||
const result = await mailPasswords.get('random', 'random');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('can list mail passwords for user', async function () {
|
||||
const results = await mailPasswords.list(admin.id);
|
||||
expect(results.length).to.be(1);
|
||||
expect(results[0].appId).to.be(app.id);
|
||||
expect(results[0].userId).to.be(admin.id);
|
||||
assert.equal(results.length, 1);
|
||||
assert.equal(results[0].appId, app.id);
|
||||
assert.equal(results[0].userId, admin.id);
|
||||
});
|
||||
|
||||
it('cannot add duplicate appId and userId', async function () {
|
||||
const [error] = await safe(mailPasswords.add(app.id, admin.id, 'another-token'));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('can del mail password', async function () {
|
||||
@@ -69,16 +66,16 @@ describe('Mail passwords', function () {
|
||||
|
||||
it('cannot del random mail password', async function () {
|
||||
const [error] = await safe(mailPasswords.del('random', 'random'));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('cannot add with non-existent appId', async function () {
|
||||
const [error] = await safe(mailPasswords.add('nonexistent-app-id', admin.id, 'token'));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('cannot add with non-existent userId', async function () {
|
||||
const [error] = await safe(mailPasswords.add(app.id, 'nonexistent-user-id', 'token'));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
});
|
||||
|
||||
+23
-26
@@ -1,16 +1,13 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import network from '../network.js';
|
||||
import paths from '../paths.js';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Network', function () {
|
||||
const { setup, cleanup, auditSource } = common;
|
||||
@@ -25,111 +22,111 @@ describe('Network', function () {
|
||||
|
||||
it('can get empty blocklist', async function () {
|
||||
const result = await network.getBlocklist();
|
||||
expect(result).to.equal('');
|
||||
assert.equal(result, '');
|
||||
});
|
||||
|
||||
it('can set empty blocklist', async function () {
|
||||
await network.setBlocklist('', auditSource);
|
||||
const result = await network.getBlocklist();
|
||||
expect(result).to.equal('');
|
||||
assert.equal(result, '');
|
||||
});
|
||||
|
||||
it('can set single IPv4 in blocklist', async function () {
|
||||
await network.setBlocklist('192.168.178.1', auditSource);
|
||||
const result = await network.getBlocklist();
|
||||
expect(result).to.equal('192.168.178.1');
|
||||
assert.equal(result, '192.168.178.1');
|
||||
});
|
||||
|
||||
it('can set single IPv6 in blocklist', async function () {
|
||||
await network.setBlocklist('2a02:8106:2f:bb00:7afc:5703:ee71:3ef8', auditSource);
|
||||
const result = await network.getBlocklist();
|
||||
expect(result).to.equal('2a02:8106:2f:bb00:7afc:5703:ee71:3ef8');
|
||||
assert.equal(result, '2a02:8106:2f:bb00:7afc:5703:ee71:3ef8');
|
||||
});
|
||||
|
||||
it('can set mixed IPs with comment in blocklist', async function () {
|
||||
await network.setBlocklist('2a02:8106:2f:bb00:7afc:5703:ee71:3ef8\n# some comment\n192.168.178.1', auditSource);
|
||||
const result = await network.getBlocklist();
|
||||
expect(result).to.equal('2a02:8106:2f:bb00:7afc:5703:ee71:3ef8\n# some comment\n192.168.178.1');
|
||||
assert.equal(result, '2a02:8106:2f:bb00:7afc:5703:ee71:3ef8\n# some comment\n192.168.178.1');
|
||||
});
|
||||
|
||||
it('can set single IPv4 range in blocklist', async function () {
|
||||
await network.setBlocklist('192.168.178.1/24', auditSource);
|
||||
const result = await network.getBlocklist();
|
||||
expect(result).to.equal('192.168.178.1/24');
|
||||
assert.equal(result, '192.168.178.1/24');
|
||||
});
|
||||
|
||||
it('can set single IPv6 range in blocklist', async function () {
|
||||
await network.setBlocklist('2001:db8::', auditSource);
|
||||
const result = await network.getBlocklist();
|
||||
expect(result).to.equal('2001:db8::');
|
||||
assert.equal(result, '2001:db8::');
|
||||
});
|
||||
|
||||
it('cannot set IPv4 in blocklist if source is same', async function () {
|
||||
const [error] = await safe(network.setBlocklist('127.0.0.1', { ip: '127.0.0.1' }));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot set IPv6 in blocklist if source is same', async function () {
|
||||
const [error] = await safe(network.setBlocklist('2001:db8:1234::1', { ip: '2001:db8:1234::1' }));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot set IPv4 range in blocklist if source is same', async function () {
|
||||
const [error] = await safe(network.setBlocklist('127.0.0.1/32', { ip: '127.0.0.1' }));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot set IPv6 range in blocklist if source is same', async function () {
|
||||
const [error] = await safe(network.setBlocklist('2001:db8:1234:::', { ip: '2001:db8:1234::1' }));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can set IPv4 in blocklist if source is IPv6', async function () {
|
||||
await network.setBlocklist('192.168.178.1', { ip: '2001:db8:1234::1' });
|
||||
const result = await network.getBlocklist();
|
||||
expect(result).to.equal('192.168.178.1');
|
||||
assert.equal(result, '192.168.178.1');
|
||||
});
|
||||
|
||||
it('can set IPv6 in blocklist if source is IPv4', async function () {
|
||||
await network.setBlocklist('2001:db8:1234::1', auditSource);
|
||||
const result = await network.getBlocklist();
|
||||
expect(result).to.equal('2001:db8:1234::1');
|
||||
assert.equal(result, '2001:db8:1234::1');
|
||||
});
|
||||
|
||||
it('can set IPv4 range in blocklist if source is IPv6', async function () {
|
||||
await network.setBlocklist('192.168.178.1/32', { ip: '2001:db8:1234::1' });
|
||||
const result = await network.getBlocklist();
|
||||
expect(result).to.equal('192.168.178.1/32');
|
||||
assert.equal(result, '192.168.178.1/32');
|
||||
});
|
||||
|
||||
it('can set IPv6 range in blocklist if source is IPv4', async function () {
|
||||
await network.setBlocklist('2001:db8:1234::', auditSource);
|
||||
const result = await network.getBlocklist();
|
||||
expect(result).to.equal('2001:db8:1234::');
|
||||
assert.equal(result, '2001:db8:1234::');
|
||||
});
|
||||
});
|
||||
|
||||
describe('IPv6 config', function () {
|
||||
it('can get default IPv6 setting', async function () {
|
||||
const config = await network.getIPv6Config();
|
||||
expect(config.provider).to.be('noop');
|
||||
assert.equal(config.provider, 'noop');
|
||||
});
|
||||
|
||||
it('can set IPv6 setting', async function () {
|
||||
await network.setIPv6Config({ provider: 'generic' });
|
||||
|
||||
const config = await network.getIPv6Config();
|
||||
expect(config.provider).to.be('generic');
|
||||
assert.equal(config.provider, 'generic');
|
||||
});
|
||||
|
||||
it('test machine has IPv6 support', function () {
|
||||
expect(network.hasIPv6()).to.equal(true);
|
||||
assert.equal(network.hasIPv6(), true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Dynamic DNS', function () {
|
||||
it('can get default dyndns', async function () {
|
||||
expect(await network.getDynamicDns()).to.be(false);
|
||||
assert.equal(await network.getDynamicDns(), false);
|
||||
});
|
||||
|
||||
it('can set dyndns', async function () {
|
||||
@@ -137,13 +134,13 @@ describe('Network', function () {
|
||||
});
|
||||
|
||||
it('can get dyndns', async function () {
|
||||
expect(await network.getDynamicDns()).to.be(true);
|
||||
assert.equal(await network.getDynamicDns(), true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Default interface', function () {
|
||||
it('can get default interface', async function () {
|
||||
expect(await network.getDefaultInterface()).to.be.ok();
|
||||
assert.ok(await network.getDefaultInterface());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import notifications from '../notifications.js';
|
||||
import safe from 'safetydance';
|
||||
import timers from 'timers/promises';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
const EVENT_0 = {
|
||||
id: 'event_0',
|
||||
@@ -30,8 +27,8 @@ describe('Notifications', function () {
|
||||
it('can add notifications', async function () {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const [error, id] = await safe(notifications._add(notifications.TYPE_APP_UPDATED, `title ${i}`, `message ${i}`, { eventId: EVENT_0.id }));
|
||||
expect(error).to.equal(null);
|
||||
expect(id).to.be.a('string');
|
||||
assert.equal(error, null);
|
||||
assert.equal(typeof id, 'string');
|
||||
notificationIds.push(id);
|
||||
await timers.setTimeout(1000);
|
||||
}
|
||||
@@ -39,39 +36,39 @@ describe('Notifications', function () {
|
||||
|
||||
it('can get by id', async function () {
|
||||
const [error, result] = await safe(notifications.get(notificationIds[0]));
|
||||
expect(error).to.be(null);
|
||||
expect(result.title).to.be('title 0');
|
||||
expect(result.type).to.be(notifications.TYPE_APP_UPDATED);
|
||||
expect(result.message).to.be('message 0');
|
||||
expect(result.acknowledged).to.be(false);
|
||||
assert.equal(error, null);
|
||||
assert.equal(result.title, 'title 0');
|
||||
assert.equal(result.type, notifications.TYPE_APP_UPDATED);
|
||||
assert.equal(result.message, 'message 0');
|
||||
assert.equal(result.acknowledged, false);
|
||||
});
|
||||
|
||||
it('cannot get non-existent id', async function () {
|
||||
const result = await notifications.get('random');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('can list notifications', async function () {
|
||||
const result = await notifications.list({}, 1, 10);
|
||||
expect(result.length).to.be(3);
|
||||
expect(result[0].title).to.be('title 2');
|
||||
expect(result[1].title).to.be('title 1');
|
||||
expect(result[2].title).to.be('title 0');
|
||||
assert.equal(result.length, 3);
|
||||
assert.equal(result[0].title, 'title 2');
|
||||
assert.equal(result[1].title, 'title 1');
|
||||
assert.equal(result[2].title, 'title 0');
|
||||
});
|
||||
|
||||
it('can update notification', async function () {
|
||||
await notifications.update({ id: notificationIds[0] }, { type: notifications.TYPE_APP_OOM, title: 'updated title 0', message: 'updated message 0', acknowledged: true });
|
||||
|
||||
const result = await notifications.get(notificationIds[0]);
|
||||
expect(result.title).to.be('updated title 0');
|
||||
expect(result.type).to.be(notifications.TYPE_APP_OOM);
|
||||
expect(result.message).to.be('updated message 0');
|
||||
expect(result.acknowledged).to.be(true);
|
||||
assert.equal(result.title, 'updated title 0');
|
||||
assert.equal(result.type, notifications.TYPE_APP_OOM);
|
||||
assert.equal(result.message, 'updated message 0');
|
||||
assert.equal(result.acknowledged, true);
|
||||
});
|
||||
|
||||
it('cannot update non-existent notification', async function () {
|
||||
const [error] = await safe(notifications.update({ id: '1245' }, { title: 'updated title 0', message: 'updated message 0', acknowledged: true }));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
|
||||
});
|
||||
|
||||
@@ -81,7 +78,7 @@ describe('Notifications', function () {
|
||||
|
||||
it('cannot delete non-existent notification', async function () {
|
||||
const [error] = await safe(notifications.del('5213'));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
let pinId;
|
||||
@@ -90,40 +87,40 @@ describe('Notifications', function () {
|
||||
pinId = await notifications.pin(notifications.TYPE_BOX_UPDATE, 'Cloudron xx is available', 'Awesome changelog', { context: 'xx' });
|
||||
|
||||
const result = await notifications.get(pinId);
|
||||
expect(result.title).to.be('Cloudron xx is available');
|
||||
expect(result.message).to.be('Awesome changelog');
|
||||
expect(result.acknowledged).to.be(false);
|
||||
assert.equal(result.title, 'Cloudron xx is available');
|
||||
assert.equal(result.message, 'Awesome changelog');
|
||||
assert.equal(result.acknowledged, false);
|
||||
});
|
||||
|
||||
it('updating pin with same message does nothing', async function () {
|
||||
await notifications.update({ id: pinId }, { acknowledged: true }); // ack the alert
|
||||
|
||||
const id = await notifications.pin(notifications.TYPE_BOX_UPDATE, 'Cloudron xx is available', 'Awesome changelog', { context: 'xx' });
|
||||
expect(id).to.be(pinId);
|
||||
assert.equal(id, pinId);
|
||||
|
||||
const result = await notifications.get(pinId);
|
||||
expect(result.title).to.be('Cloudron xx is available');
|
||||
expect(result.message).to.be('Awesome changelog');
|
||||
expect(result.acknowledged).to.be(true); // notification does not resurface
|
||||
assert.equal(result.title, 'Cloudron xx is available');
|
||||
assert.equal(result.message, 'Awesome changelog');
|
||||
assert.equal(result.acknowledged, true); // notification does not resurface
|
||||
});
|
||||
|
||||
it('updating pin with new message resurfaces', async function () {
|
||||
await notifications.update({ id: pinId }, { acknowledged: true }); // ack the alert
|
||||
|
||||
const id = await notifications.pin(notifications.TYPE_BOX_UPDATE, 'Cloudron xy is available', 'Awesome new changelog', { context: 'xx' });
|
||||
expect(id).to.be(pinId);
|
||||
assert.equal(id, pinId);
|
||||
|
||||
const result = await notifications.get(pinId);
|
||||
expect(result.title).to.be('Cloudron xy is available');
|
||||
expect(result.message).to.be('Awesome new changelog');
|
||||
expect(result.acknowledged).to.be(false); // notification resurfaces
|
||||
assert.equal(result.title, 'Cloudron xy is available');
|
||||
assert.equal(result.message, 'Awesome new changelog');
|
||||
assert.equal(result.acknowledged, false); // notification resurfaces
|
||||
});
|
||||
|
||||
it('can unpin', async function () {
|
||||
await notifications.unpin(notifications.TYPE_BOX_UPDATE, { context: 'xx' });
|
||||
|
||||
const result = await notifications.get(pinId);
|
||||
expect(result.acknowledged).to.be(true);
|
||||
assert.equal(result.acknowledged, true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -132,28 +129,28 @@ describe('Notifications', function () {
|
||||
pinId = await notifications.pin(notifications.TYPE_REBOOT, 'Reboot required', 'Do it now', {});
|
||||
|
||||
const result = await notifications.get(pinId);
|
||||
expect(result.title).to.be('Reboot required');
|
||||
expect(result.message).to.be('Do it now');
|
||||
expect(result.acknowledged).to.be(false);
|
||||
assert.equal(result.title, 'Reboot required');
|
||||
assert.equal(result.message, 'Do it now');
|
||||
assert.equal(result.acknowledged, false);
|
||||
});
|
||||
|
||||
it('can update the alert', async function () {
|
||||
await notifications.update({ id: pinId }, { acknowledged: true }); // ack the alert
|
||||
|
||||
const id = await notifications.pin(notifications.TYPE_REBOOT, 'Reboot required', 'Do it now', {});
|
||||
expect(id).to.be(pinId);
|
||||
assert.equal(id, pinId);
|
||||
|
||||
const result = await notifications.get(pinId);
|
||||
expect(result.title).to.be('Reboot required');
|
||||
expect(result.message).to.be('Do it now');
|
||||
expect(result.acknowledged).to.be(false); // resurfaces
|
||||
assert.equal(result.title, 'Reboot required');
|
||||
assert.equal(result.message, 'Do it now');
|
||||
assert.equal(result.acknowledged, false); // resurfaces
|
||||
});
|
||||
|
||||
it('can unpin', async function () {
|
||||
await notifications.unpin(notifications.TYPE_REBOOT, {});
|
||||
|
||||
const result = await notifications.get(pinId);
|
||||
expect(result.acknowledged).to.be(true);
|
||||
assert.equal(result.acknowledged, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* global describe, before, it, after */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import oidcClients from '../oidcclients.js';
|
||||
import safe from 'safetydance';
|
||||
|
||||
@@ -24,25 +24,25 @@ describe('OIDC Clients', function () {
|
||||
const result = await oidcClients.add(CLIENT_0);
|
||||
id = result.id;
|
||||
secret = result.secret;
|
||||
expect(id).to.be.a('string');
|
||||
expect(secret).to.be.a('string');
|
||||
assert.equal(typeof id, 'string');
|
||||
assert.equal(typeof secret, 'string');
|
||||
});
|
||||
|
||||
it('cannot get client', async function () {
|
||||
const client = await oidcClients.get(id);
|
||||
expect(client.appId).to.be('someappid');
|
||||
expect(client.secret).to.be(secret);
|
||||
assert.equal(client.appId, 'someappid');
|
||||
assert.equal(client.secret, secret);
|
||||
});
|
||||
|
||||
it('cannot get random client', async function () {
|
||||
const client = await oidcClients.get('random');
|
||||
expect(client).to.be(null);
|
||||
assert.equal(client, null);
|
||||
});
|
||||
|
||||
it('can list clients', async function () {
|
||||
const clients = await oidcClients.list();
|
||||
expect(clients.length).to.be(1);
|
||||
expect(clients[0].secret).to.be(secret);
|
||||
assert.equal(clients.length, 1);
|
||||
assert.equal(clients[0].secret, secret);
|
||||
});
|
||||
|
||||
it('can update client', async function () {
|
||||
@@ -51,14 +51,14 @@ describe('OIDC Clients', function () {
|
||||
await oidcClients.update(id, clientCopy);
|
||||
|
||||
const client = await oidcClients.get(id);
|
||||
expect(client.name).to.be('newname');
|
||||
assert.equal(client.name, 'newname');
|
||||
});
|
||||
|
||||
it('cannot update random client', async function () {
|
||||
const clientCopy = Object.assign({}, CLIENT_0);
|
||||
clientCopy.name = 'newname';
|
||||
const [error] = await safe(oidcClients.update('random', clientCopy));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('can del client', async function () {
|
||||
@@ -67,6 +67,6 @@ describe('OIDC Clients', function () {
|
||||
|
||||
it('cannot del random client', async function () {
|
||||
const [error] = await safe(oidcClients.del(id));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
});
|
||||
|
||||
+13
-14
@@ -1,11 +1,10 @@
|
||||
/* global it:false */
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import openssl from '../openssl.js';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global describe:false */
|
||||
|
||||
describe('openssl', function () {
|
||||
describe('validateCertificate', function () {
|
||||
@@ -49,30 +48,30 @@ describe('openssl', function () {
|
||||
|
||||
it('does not allow empty string for cert', async function () {
|
||||
const [error] = await safe(openssl.validateCertificate('', foobarDomain, { cert: '', key: 'key' }));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('does not allow empty string for key', async function () {
|
||||
const [error] = await safe(openssl.validateCertificate('', foobarDomain, { cert: 'cert', key: '' }));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('does not allow invalid cert', async function () {
|
||||
const [error] = await safe(openssl.validateCertificate('', foobarDomain, { cert: 'someinvalidcert', key: validKey0 }));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('does not allow invalid key', async function () {
|
||||
const [error] = await safe(openssl.validateCertificate('', foobarDomain, { cert: validCert0, key: 'invalidkey' }));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('does not allow cert without matching domain', async function () {
|
||||
const [error] = await safe(openssl.validateCertificate('', 'cloudron.io', { cert: validCert0, key: validKey0 }));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
|
||||
const [error2] = await safe(openssl.validateCertificate('cloudron.io', foobarDomain, { cert: validCert0, key: validKey0 }));
|
||||
expect(error2.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error2.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('allows valid cert with matching domain', async function () {
|
||||
@@ -85,10 +84,10 @@ describe('openssl', function () {
|
||||
|
||||
it('does now allow cert without matching domain (wildcard)', async function () {
|
||||
const [error] = await safe(openssl.validateCertificate('', foobarDomain, { cert: validCert1, key: validKey1 }));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
|
||||
const [error2] = await safe(openssl.validateCertificate('bar.abc', foobarDomain, { cert: validCert1, key: validKey1 }));
|
||||
expect(error2.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error2.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('allows valid cert with matching domain (subdomain)', async function () {
|
||||
@@ -97,11 +96,11 @@ describe('openssl', function () {
|
||||
|
||||
it('does not allow cert without matching domain (subdomain)', async function () {
|
||||
const [error] = await safe(openssl.validateCertificate('baz', foobarDomain, { cert: validCert0, key: validKey0 }));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('does not allow invalid cert/key tuple', async function () {
|
||||
//expect(openssl.validateCertificate('', foobarDomain, { cert: validCert0, key: validKey1 })).to.be.an(Error);
|
||||
//assert.ok((openssl.validateCertificate('', foobarDomain, { cert: validCert0, key: validKey1 })) instanceof (Error));
|
||||
});
|
||||
|
||||
it('picks certificate in SAN', async function () {
|
||||
@@ -120,7 +119,7 @@ describe('openssl', function () {
|
||||
|
||||
it('can generate fallback certs', async function () {
|
||||
result = await openssl.generateCertificate(domain);
|
||||
expect(result).to.be.ok();
|
||||
assert.ok(result);
|
||||
});
|
||||
|
||||
it('can validate the certs', async function () {
|
||||
|
||||
+68
-71
@@ -1,17 +1,14 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import passkeys from '../passkeys.js';
|
||||
import safe from 'safetydance';
|
||||
import speakeasy from 'speakeasy';
|
||||
import users from '../users.js';
|
||||
import webauthnHelper from './webauthn-helper.js';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Passkeys', function () {
|
||||
const { domainSetup, cleanup, admin, auditSource, dashboardFqdn } = common;
|
||||
@@ -37,87 +34,87 @@ describe('Passkeys', function () {
|
||||
|
||||
it('list returns empty', async function () {
|
||||
const result = await passkeys.listByUserId(admin.id);
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.be(0);
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 0);
|
||||
});
|
||||
|
||||
it('can add a passkey', async function () {
|
||||
const { id } = await passkeys.add(admin.id, 'credId123', 'pubKeyBase64', 0, ['internal'], 'Test Key');
|
||||
expect(id).to.be.a('string');
|
||||
expect(id).to.match(/^pk-/);
|
||||
assert.equal(typeof id, 'string');
|
||||
assert.match(String(id), /^pk-/);
|
||||
});
|
||||
|
||||
it('list returns one passkey', async function () {
|
||||
const result = await passkeys.listByUserId(admin.id);
|
||||
expect(result.length).to.be(1);
|
||||
expect(result[0].userId).to.be(admin.id);
|
||||
expect(result[0].credentialId).to.be('credId123');
|
||||
expect(result[0].publicKey).to.be('pubKeyBase64');
|
||||
expect(result[0].counter).to.be(0);
|
||||
expect(result[0].transports).to.eql(['internal']);
|
||||
expect(result[0].name).to.be('Test Key');
|
||||
assert.equal(result.length, 1);
|
||||
assert.equal(result[0].userId, admin.id);
|
||||
assert.equal(result[0].credentialId, 'credId123');
|
||||
assert.equal(result[0].publicKey, 'pubKeyBase64');
|
||||
assert.equal(result[0].counter, 0);
|
||||
assert.deepEqual(result[0].transports, ['internal']);
|
||||
assert.equal(result[0].name, 'Test Key');
|
||||
});
|
||||
|
||||
it('can get by id', async function () {
|
||||
const list = await passkeys.listByUserId(admin.id);
|
||||
const result = await passkeys.get(list[0].id);
|
||||
expect(result).to.not.be(null);
|
||||
expect(result.credentialId).to.be('credId123');
|
||||
assert.notEqual(result, null);
|
||||
assert.equal(result.credentialId, 'credId123');
|
||||
});
|
||||
|
||||
it('can get by credentialId', async function () {
|
||||
const result = await passkeys.getByCredentialId('credId123');
|
||||
expect(result).to.not.be(null);
|
||||
expect(result.userId).to.be(admin.id);
|
||||
assert.notEqual(result, null);
|
||||
assert.equal(result.userId, admin.id);
|
||||
});
|
||||
|
||||
it('get returns null for unknown id', async function () {
|
||||
const result = await passkeys.get('pk-nonexistent');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('getByCredentialId returns null for unknown', async function () {
|
||||
const result = await passkeys.getByCredentialId('unknownCredId');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('rejects duplicate credentialId', async function () {
|
||||
const [error] = await safe(passkeys.add(admin.id, 'credId123', 'otherPubKey', 0, [], 'Dup'));
|
||||
expect(error).to.not.be(null);
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.notEqual(error, null);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('can delete a passkey', async function () {
|
||||
const list = await passkeys.listByUserId(admin.id);
|
||||
await passkeys.del(list[0].id);
|
||||
const afterDel = await passkeys.listByUserId(admin.id);
|
||||
expect(afterDel.length).to.be(0);
|
||||
assert.equal(afterDel.length, 0);
|
||||
});
|
||||
|
||||
it('delete throws for unknown passkey', async function () {
|
||||
const [error] = await safe(passkeys.del('pk-nonexistent'));
|
||||
expect(error).to.not.be(null);
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.notEqual(error, null);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('delAll clears all passkeys', async function () {
|
||||
await passkeys.add(admin.id, 'cred1', 'pk1', 0, [], 'Key1');
|
||||
await passkeys.delAll();
|
||||
const result = await passkeys.listByUserId(admin.id);
|
||||
expect(result.length).to.be(0);
|
||||
assert.equal(result.length, 0);
|
||||
});
|
||||
|
||||
it('removePrivateFields strips sensitive data', async function () {
|
||||
const { id } = await passkeys.add(admin.id, 'credStrip', 'pkStrip', 0, ['usb'], 'Strip Test');
|
||||
const pk = await passkeys.get(id);
|
||||
const filtered = passkeys.removePrivateFields(pk);
|
||||
expect(filtered.id).to.be(id);
|
||||
expect(filtered.name).to.be('Strip Test');
|
||||
expect(filtered.creationTime).to.not.be(undefined);
|
||||
expect(filtered.credentialId).to.be(undefined);
|
||||
expect(filtered.publicKey).to.be(undefined);
|
||||
expect(filtered.counter).to.be(undefined);
|
||||
expect(filtered.userId).to.be(undefined);
|
||||
assert.equal(filtered.id, id);
|
||||
assert.equal(filtered.name, 'Strip Test');
|
||||
assert.notEqual(filtered.creationTime, undefined);
|
||||
assert.equal(filtered.credentialId, undefined);
|
||||
assert.equal(filtered.publicKey, undefined);
|
||||
assert.equal(filtered.counter, undefined);
|
||||
assert.equal(filtered.userId, undefined);
|
||||
|
||||
await passkeys.del(id);
|
||||
});
|
||||
@@ -131,12 +128,12 @@ describe('Passkeys', function () {
|
||||
it('can generate registration options', async function () {
|
||||
const adminUser = await users.get(admin.id);
|
||||
const options = await passkeys.getRegistrationOptions(adminUser);
|
||||
expect(options).to.be.an(Object);
|
||||
expect(options.challenge).to.be.a('string');
|
||||
expect(options.rp).to.be.an(Object);
|
||||
expect(options.rp.name).to.be('Cloudron');
|
||||
expect(options.rp.id).to.be(dashboardFqdn);
|
||||
expect(options.user).to.be.an(Object);
|
||||
assert.ok((options) && typeof (options) === 'object' && !Array.isArray(options));
|
||||
assert.equal(typeof options.challenge, 'string');
|
||||
assert.ok((options.rp) && typeof (options.rp) === 'object' && !Array.isArray(options.rp));
|
||||
assert.equal(options.rp.name, 'Cloudron');
|
||||
assert.equal(options.rp.id, dashboardFqdn);
|
||||
assert.ok((options.user) && typeof (options.user) === 'object' && !Array.isArray(options.user));
|
||||
});
|
||||
|
||||
it('can register with virtual authenticator', async function () {
|
||||
@@ -147,20 +144,20 @@ describe('Passkeys', function () {
|
||||
const response = await webauthnHelper.createRegistrationResponse(authenticator, options, origin);
|
||||
|
||||
const result = await passkeys.verifyRegistration(adminUser, response, 'My Test Key');
|
||||
expect(result).to.be.an(Object);
|
||||
expect(result.id).to.be.a('string');
|
||||
expect(result.id).to.match(/^pk-/);
|
||||
assert.ok((result) && typeof (result) === 'object' && !Array.isArray(result));
|
||||
assert.equal(typeof result.id, 'string');
|
||||
assert.match(String(result.id), /^pk-/);
|
||||
|
||||
const list = await passkeys.listByUserId(admin.id);
|
||||
expect(list.length).to.be(1);
|
||||
expect(list[0].name).to.be('My Test Key');
|
||||
assert.equal(list.length, 1);
|
||||
assert.equal(list[0].name, 'My Test Key');
|
||||
});
|
||||
|
||||
it('rejects duplicate registration', async function () {
|
||||
const adminUser = await users.get(admin.id);
|
||||
const [error] = await safe(passkeys.getRegistrationOptions(adminUser));
|
||||
expect(error).to.not.be(null);
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.notEqual(error, null);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('cleanup passkey for further tests', async function () {
|
||||
@@ -177,7 +174,7 @@ describe('Passkeys', function () {
|
||||
|
||||
const response = await webauthnHelper.createRegistrationResponse(authenticator, options, origin);
|
||||
const [error] = await safe(passkeys.verifyRegistration(adminUser, response, 'Bad Key'));
|
||||
expect(error).to.not.be(null);
|
||||
assert.notEqual(error, null);
|
||||
});
|
||||
|
||||
it('rejects registration when TOTP is enabled', async function () {
|
||||
@@ -191,8 +188,8 @@ describe('Passkeys', function () {
|
||||
adminUser.twoFactorAuthenticationEnabled = true;
|
||||
|
||||
const [error] = await safe(passkeys.getRegistrationOptions(adminUser));
|
||||
expect(error).to.not.be(null);
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.notEqual(error, null);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
|
||||
// disable TOTP for further tests
|
||||
await users.disableTwoFactorAuthentication(adminUser, auditSource);
|
||||
@@ -217,10 +214,10 @@ describe('Passkeys', function () {
|
||||
it('can generate authentication options', async function () {
|
||||
const adminUser = await users.get(admin.id);
|
||||
const options = await passkeys.getAuthenticationOptions(adminUser);
|
||||
expect(options).to.be.an(Object);
|
||||
expect(options.challenge).to.be.a('string');
|
||||
expect(options.allowCredentials).to.be.an(Array);
|
||||
expect(options.allowCredentials.length).to.be(1);
|
||||
assert.ok((options) && typeof (options) === 'object' && !Array.isArray(options));
|
||||
assert.equal(typeof options.challenge, 'string');
|
||||
assert.ok(Array.isArray(options.allowCredentials));
|
||||
assert.equal(options.allowCredentials.length, 1);
|
||||
});
|
||||
|
||||
it('can authenticate with virtual authenticator', async function () {
|
||||
@@ -229,15 +226,15 @@ describe('Passkeys', function () {
|
||||
const response = await webauthnHelper.createAuthenticationResponse(authenticator, options, origin);
|
||||
|
||||
const result = await passkeys.verifyAuthentication(adminUser, response);
|
||||
expect(result).to.be.an(Object);
|
||||
expect(result.verified).to.be(true);
|
||||
expect(result.passkeyId).to.be.a('string');
|
||||
assert.ok((result) && typeof (result) === 'object' && !Array.isArray(result));
|
||||
assert.equal(result.verified, true);
|
||||
assert.equal(typeof result.passkeyId, 'string');
|
||||
});
|
||||
|
||||
it('counter was updated after authentication', async function () {
|
||||
const list = await passkeys.listByUserId(admin.id);
|
||||
expect(list[0].counter).to.be(1);
|
||||
expect(list[0].lastUsedTime).to.not.be(null);
|
||||
assert.equal(list[0].counter, 1);
|
||||
assert.notEqual(list[0].lastUsedTime, null);
|
||||
});
|
||||
|
||||
it('can authenticate again (counter increments)', async function () {
|
||||
@@ -246,10 +243,10 @@ describe('Passkeys', function () {
|
||||
const response = await webauthnHelper.createAuthenticationResponse(authenticator, options, origin);
|
||||
|
||||
const result = await passkeys.verifyAuthentication(adminUser, response);
|
||||
expect(result.verified).to.be(true);
|
||||
assert.equal(result.verified, true);
|
||||
|
||||
const list = await passkeys.listByUserId(admin.id);
|
||||
expect(list[0].counter).to.be(2);
|
||||
assert.equal(list[0].counter, 2);
|
||||
});
|
||||
|
||||
it('rejects authentication with wrong credential', async function () {
|
||||
@@ -261,8 +258,8 @@ describe('Passkeys', function () {
|
||||
const response = await webauthnHelper.createAuthenticationResponse(fakeAuth, options, origin);
|
||||
|
||||
const [error] = await safe(passkeys.verifyAuthentication(adminUser, response));
|
||||
expect(error).to.not.be(null);
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.notEqual(error, null);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('rejects authentication with tampered challenge', async function () {
|
||||
@@ -272,7 +269,7 @@ describe('Passkeys', function () {
|
||||
|
||||
const response = await webauthnHelper.createAuthenticationResponse(authenticator, options, origin);
|
||||
const [error] = await safe(passkeys.verifyAuthentication(adminUser, response));
|
||||
expect(error).to.not.be(null);
|
||||
assert.notEqual(error, null);
|
||||
});
|
||||
|
||||
it('fails to generate auth options when no passkey registered', async function () {
|
||||
@@ -280,8 +277,8 @@ describe('Passkeys', function () {
|
||||
|
||||
const adminUser = await users.get(admin.id);
|
||||
const [error] = await safe(passkeys.getAuthenticationOptions(adminUser));
|
||||
expect(error).to.not.be(null);
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.notEqual(error, null);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -302,8 +299,8 @@ describe('Passkeys', function () {
|
||||
const totpToken = speakeasy.totp({ secret: twofa.secret, encoding: 'base32' });
|
||||
|
||||
const [error] = await safe(users.enableTwoFactorAuthentication(adminUser, totpToken, auditSource));
|
||||
expect(error).to.not.be(null);
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.notEqual(error, null);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
|
||||
await passkeys.delAll();
|
||||
});
|
||||
@@ -319,8 +316,8 @@ describe('Passkeys', function () {
|
||||
adminUser.twoFactorAuthenticationEnabled = true;
|
||||
|
||||
const [error] = await safe(passkeys.getRegistrationOptions(adminUser));
|
||||
expect(error).to.not.be(null);
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.notEqual(error, null);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
|
||||
// cleanup
|
||||
await users.disableTwoFactorAuthentication(adminUser, auditSource);
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
/* global it:false */
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import ProgressStream from '../progress-stream.js';
|
||||
import stream from 'node:stream';
|
||||
|
||||
/* global describe:false */
|
||||
|
||||
describe('progress stream', function () {
|
||||
it('can create stream', function (done) {
|
||||
it('can create stream', async function () {
|
||||
const input = fs.createReadStream(`${import.meta.dirname}/progress-stream-test.js`);
|
||||
const progress = new ProgressStream({ interval: 1000 });
|
||||
const output = fs.createWriteStream('/dev/null');
|
||||
|
||||
stream.pipeline(input, progress, output, function (error) {
|
||||
expect(error).to.not.be.ok();
|
||||
const size = fs.statSync(`${import.meta.dirname}/progress-stream-test.js`).size;
|
||||
expect(progress.stats().transferred).to.be(size);
|
||||
|
||||
done();
|
||||
await new Promise((resolve, reject) => {
|
||||
stream.pipeline(input, progress, output, function (error) {
|
||||
if (error) return reject(error);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
const size = fs.statSync(`${import.meta.dirname}/progress-stream-test.js`).size;
|
||||
assert.equal(progress.stats().transferred, size);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
import { describe, it } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import promiseRetry from '../promise-retry.js';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
|
||||
describe('promiseRetry', function () {
|
||||
this.timeout(0);
|
||||
|
||||
it('normal return', async function () {
|
||||
const result = await promiseRetry({ times: 5, interval: 1000 }, async () => {
|
||||
return 42;
|
||||
});
|
||||
|
||||
expect(result).to.be(42);
|
||||
assert.equal(result, 42);
|
||||
});
|
||||
|
||||
it('throws error', async function () {
|
||||
@@ -23,7 +20,7 @@ describe('promiseRetry', function () {
|
||||
throw new Error('42');
|
||||
}));
|
||||
|
||||
expect(error.message).to.be('42');
|
||||
assert.equal(error.message, '42');
|
||||
});
|
||||
|
||||
it('3 tries', async function () {
|
||||
@@ -32,7 +29,7 @@ describe('promiseRetry', function () {
|
||||
if (++tryCount == 3) return 42; else throw new Error('42');
|
||||
});
|
||||
|
||||
expect(result).to.be(42);
|
||||
assert.equal(result, 42);
|
||||
});
|
||||
|
||||
it('can abort with 1 try only', async function () {
|
||||
@@ -42,7 +39,7 @@ describe('promiseRetry', function () {
|
||||
throw tryCount;
|
||||
}));
|
||||
|
||||
expect(tryCount).to.be(1);
|
||||
expect(error).to.be(1);
|
||||
assert.equal(tryCount, 1);
|
||||
assert.equal(error, 1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import appstore from '../appstore.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import nock from 'nock';
|
||||
import provision from '../provision.js';
|
||||
import safe from 'safetydance';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Provision', function () {
|
||||
const { domainSetup, auditSource, cleanup } = common;
|
||||
@@ -24,7 +21,7 @@ describe('Provision', function () {
|
||||
|
||||
it('cannot activate when appstore unreachable', async function () {
|
||||
const [error] = await safe(provision.activate('username', 'password', 'test@cloudron.io', 'Some Name', '1.2.3.4', auditSource));
|
||||
expect(error.reason).to.be(BoxError.NETWORK_ERROR);
|
||||
assert.equal(error.reason, BoxError.NETWORK_ERROR);
|
||||
});
|
||||
|
||||
it('cannot activate with non-201', async function () {
|
||||
@@ -33,8 +30,8 @@ describe('Provision', function () {
|
||||
.reply(401, {});
|
||||
|
||||
const [error] = await safe(provision.activate('username', 'password', 'test@cloudron.io', 'Some Name', '1.2.3.4', auditSource));
|
||||
expect(error.reason).to.be(BoxError.EXTERNAL_ERROR);
|
||||
expect(scope1.isDone()).to.be.ok();
|
||||
assert.equal(error.reason, BoxError.EXTERNAL_ERROR);
|
||||
assert.ok(scope1.isDone());
|
||||
scope1.persist(false);
|
||||
});
|
||||
|
||||
@@ -44,8 +41,8 @@ describe('Provision', function () {
|
||||
.reply(201, { id: '32' });
|
||||
|
||||
const [error] = await safe(provision.activate('username', 'password', 'test@cloudron.io', 'Some Name', '1.2.3.4', auditSource));
|
||||
expect(error.reason).to.be(BoxError.EXTERNAL_ERROR);
|
||||
expect(scope1.isDone()).to.be.ok();
|
||||
assert.equal(error.reason, BoxError.EXTERNAL_ERROR);
|
||||
assert.ok(scope1.isDone());
|
||||
scope1.persist(false);
|
||||
});
|
||||
|
||||
@@ -59,10 +56,10 @@ describe('Provision', function () {
|
||||
.reply(200, { features: {} });
|
||||
|
||||
await provision.activate('username', 'password', 'test@cloudron.io', 'Some Name', '1.2.3.4', auditSource);
|
||||
expect(scope1.isDone()).to.be.ok();
|
||||
assert.ok(scope1.isDone());
|
||||
scope1.persist(false);
|
||||
|
||||
expect(scope2.isDone()).to.be.ok();
|
||||
assert.ok(scope2.isDone());
|
||||
scope2.persist(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import common from './common.js';
|
||||
import domains from '../domains.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import paths from '../paths.js';
|
||||
import reverseProxy from '../reverseproxy.js';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Reverse Proxy', function () {
|
||||
const { setup, cleanup, domain, auditSource, app } = common;
|
||||
@@ -27,12 +24,14 @@ describe('Reverse Proxy', function () {
|
||||
|
||||
it('configure nginx correctly', async function () {
|
||||
await reverseProxy.configureApp(app, auditSource);
|
||||
expect(fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + app.id + '.conf'));
|
||||
const appConfigDir = `${paths.NGINX_APPCONFIG_DIR}/${app.id}`;
|
||||
assert.ok(fs.existsSync(appConfigDir));
|
||||
assert.ok(fs.readdirSync(appConfigDir).some((f) => f.endsWith('.conf')));
|
||||
});
|
||||
|
||||
it('unconfigure nginx', async function () {
|
||||
await reverseProxy.unconfigureApp(app);
|
||||
expect(!fs.existsSync(paths.NGINX_APPCONFIG_DIR + '/' + app.id + '.conf'));
|
||||
assert.ok(!fs.existsSync(`${paths.NGINX_APPCONFIG_DIR}/${app.id}`));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+12
-15
@@ -1,15 +1,12 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import constants from '../constants.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
import server from '../server.js';
|
||||
import superagent from '@cloudron/superagent';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
const SERVER_URL = 'http://localhost:' + constants.PORT;
|
||||
|
||||
@@ -23,12 +20,12 @@ describe('Server', function () {
|
||||
|
||||
it('is reachable', async function () {
|
||||
const response = await superagent.get(SERVER_URL + '/api/v1/cloudron/status');
|
||||
expect(response.status).to.equal(200);
|
||||
assert.equal(response.status, 200);
|
||||
});
|
||||
|
||||
it('should fail because already running', async function () {
|
||||
const [error] = await safe(server.start());
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -38,21 +35,21 @@ describe('Server', function () {
|
||||
|
||||
it('random bad superagents', async function () {
|
||||
const response = await superagent.get(SERVER_URL + '/random').ok(() => true);
|
||||
expect(response.status).to.equal(404);
|
||||
assert.equal(response.status, 404);
|
||||
});
|
||||
|
||||
it('version', async function () {
|
||||
const response = await superagent.get(SERVER_URL + '/api/v1/cloudron/status');
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.body.version).to.contain('-test');
|
||||
assert.equal(response.status, 200);
|
||||
assert.ok(response.body.version.includes('-test'));
|
||||
});
|
||||
|
||||
it('status route is GET', async function () {
|
||||
const response = await superagent.post(SERVER_URL + '/api/v1/cloudron/status').ok(() => true);
|
||||
expect(response.status).to.equal(404);
|
||||
assert.equal(response.status, 404);
|
||||
|
||||
const response2 = await superagent.get(SERVER_URL + '/api/v1/cloudron/status');
|
||||
expect(response2.status).to.equal(200);
|
||||
assert.equal(response2.status, 200);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -62,12 +59,12 @@ describe('Server', function () {
|
||||
|
||||
it('config fails due missing token', async function () {
|
||||
const response = await superagent.get(SERVER_URL + '/api/v1/dashboard/config').ok(() => true);
|
||||
expect(response.status).to.equal(401);
|
||||
assert.equal(response.status, 401);
|
||||
});
|
||||
|
||||
it('config fails due wrong token', async function () {
|
||||
const response = await superagent.get(SERVER_URL + '/api/v1/dashboard/config').query({ access_token: 'somewrongtoken' }).ok(() => true);
|
||||
expect(response.status).to.equal(401);
|
||||
assert.equal(response.status, 401);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -76,7 +73,7 @@ describe('Server', function () {
|
||||
|
||||
it('is not reachable anymore', async function () {
|
||||
const [error] = await safe(superagent.get(SERVER_URL + '/api/v1/cloudron/status').ok(() => true));
|
||||
expect(error).to.not.be(null);
|
||||
assert.notEqual(error, null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+15
-16
@@ -1,15 +1,14 @@
|
||||
import { describe, it } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import path from 'node:path';
|
||||
import safe from 'safetydance';
|
||||
import shellModule from '../shell.js';
|
||||
|
||||
const shell = shellModule('test');
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
|
||||
describe('shell', function () {
|
||||
describe('spawn', function () {
|
||||
@@ -19,12 +18,12 @@ describe('shell', function () {
|
||||
|
||||
it('fails on invalid program', async function () {
|
||||
const [error] = await safe(shell.spawn('randomprogram', [], {}));
|
||||
expect(error.reason).to.be(BoxError.SHELL_ERROR);
|
||||
assert.equal(error.reason, BoxError.SHELL_ERROR);
|
||||
});
|
||||
|
||||
it('fails on failing program', async function () {
|
||||
const [error] = await safe(shell.spawn('/usr/bin/false', [], {}));
|
||||
expect(error.reason).to.be(BoxError.SHELL_ERROR);
|
||||
assert.equal(error.reason, BoxError.SHELL_ERROR);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,56 +34,56 @@ describe('shell', function () {
|
||||
|
||||
it('maxLines=2 kills the process (stdout)', async function () {
|
||||
const [error] = await safe(shell.bash('for i in {1..10}; do echo $i; sleep 1; done', { encoding: 'utf8', maxLines: 2}));
|
||||
expect(error).to.be.ok();
|
||||
expect(error.stdoutLineCount).to.be(2);
|
||||
assert.ok(error);
|
||||
assert.equal(error.stdoutLineCount, 2);
|
||||
});
|
||||
|
||||
it('maxLines=2 kills the process (stderr)', async function () {
|
||||
const [error] = await safe(shell.bash('for i in {1..10}; do echo $i >&2; sleep 1; done', { encoding: 'utf8', maxLines: 2}));
|
||||
expect(error).to.be.ok();
|
||||
expect(error.stderrLineCount).to.be(2);
|
||||
assert.ok(error);
|
||||
assert.equal(error.stderrLineCount, 2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sudo', function () {
|
||||
it('cannot sudo invalid program', async function () {
|
||||
const [error] = await safe(shell.sudo([ 'randomprogram' ], {}));
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
});
|
||||
|
||||
it('can sudo valid program', async function () {
|
||||
const RELOAD_NGINX_CMD = path.join(import.meta.dirname, '../src/scripts/restartservice.sh');
|
||||
const [error] = await safe(shell.sudo([ RELOAD_NGINX_CMD, 'nginx' ], {}));
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
});
|
||||
});
|
||||
|
||||
describe('spawn', function () {
|
||||
it('spawn throws for invalid program', async function () {
|
||||
const [error] = await safe(shell.spawn('cannotexist', [], {}));
|
||||
expect(error.reason).to.be(BoxError.SHELL_ERROR);
|
||||
assert.equal(error.reason, BoxError.SHELL_ERROR);
|
||||
});
|
||||
|
||||
it('spawn throws for failed program', async function () {
|
||||
const [error] = await safe(shell.spawn('false', [], {}));
|
||||
expect(error.reason).to.be(BoxError.SHELL_ERROR);
|
||||
assert.equal(error.reason, BoxError.SHELL_ERROR);
|
||||
});
|
||||
|
||||
it('spawn times out properly', async function () {
|
||||
const [error] = await safe(shell.spawn('sleep', ['20'], { timeout: 1000 }));
|
||||
expect(error.reason).to.be(BoxError.SHELL_ERROR);
|
||||
assert.equal(error.reason, BoxError.SHELL_ERROR);
|
||||
});
|
||||
});
|
||||
|
||||
describe('bash', function () {
|
||||
it('can bash a shell program', async function () {
|
||||
const out = await shell.bash('ls -l | wc -c', {});
|
||||
expect(Buffer.isBuffer(out)).to.be(true);
|
||||
assert.equal(Buffer.isBuffer(out), true);
|
||||
});
|
||||
|
||||
it('can bash a shell program', async function () {
|
||||
const out = await shell.bash('ls -l | wc -c', { encoding: 'utf8' });
|
||||
expect(out).to.be.a('string');
|
||||
assert.equal(typeof out, 'string');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import backupSites from '../backupsites.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import consumers from 'node:stream/consumers';
|
||||
import { execSync } from 'node:child_process';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import filesystem from '../storage/filesystem.js';
|
||||
import fs from 'node:fs';
|
||||
import gcs from '../storage/gcs.js';
|
||||
@@ -15,10 +15,6 @@ import s3 from '../storage/s3.js';
|
||||
import safe from 'safetydance';
|
||||
import stream from 'stream/promises';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
/* global xit:false */
|
||||
|
||||
describe('Storage', function () {
|
||||
const { setup, cleanup, getDefaultBackupSite, auditSource } = common;
|
||||
@@ -44,20 +40,19 @@ describe('Storage', function () {
|
||||
gBackupConfig.backupDir = path.join(gTmpFolder, 'backups/');
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
after(function () {
|
||||
fs.rmSync(gTmpFolder, { recursive: true, force: true });
|
||||
done();
|
||||
});
|
||||
|
||||
it('fails to set backup storage for bad folder', async function () {
|
||||
const tmp = Object.assign({}, gBackupConfig, { backupDir: '/root/oof' });
|
||||
const [error] = await safe(backupSites.setConfig(defaultBackupSite, tmp, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('succeeds to set backup storage', async function () {
|
||||
await backupSites.setConfig(defaultBackupSite, gBackupConfig, auditSource);
|
||||
expect(fs.existsSync(path.join(gBackupConfig.backupDir, 'someprefix/snapshot'))).to.be(true); // auto-created
|
||||
assert.equal(fs.existsSync(path.join(gBackupConfig.backupDir, 'someprefix/snapshot')), true); // auto-created
|
||||
});
|
||||
|
||||
it('can upload', async function () {
|
||||
@@ -67,19 +62,19 @@ describe('Storage', function () {
|
||||
const uploader = await filesystem.upload(gBackupConfig, {}, 'uploadtest/test.txt');
|
||||
await stream.pipeline(sourceStream, uploader.createStream());
|
||||
await uploader.finish();
|
||||
expect(fs.existsSync(destFile));
|
||||
expect(fs.statSync(sourceFile).size).to.be(fs.statSync(destFile).size);
|
||||
assert.ok(fs.existsSync(destFile));
|
||||
assert.equal(fs.statSync(sourceFile).size, fs.statSync(destFile).size);
|
||||
});
|
||||
|
||||
xit('upload waits for empty file to be created', async function () {
|
||||
it.skip('upload waits for empty file to be created', async function () {
|
||||
const sourceFile = path.join(import.meta.dirname, 'storage/data/empty');
|
||||
const sourceStream = fs.createReadStream(sourceFile);
|
||||
const destFile = path.join(gBackupConfig.backupDir, gBackupConfig.prefix, '/uploadtest/empty');
|
||||
const uploader = await filesystem.upload(gBackupConfig, {}, destFile);
|
||||
await stream.pipeline(sourceStream, uploader.createStream());
|
||||
await uploader.finish();
|
||||
expect(fs.existsSync(destFile));
|
||||
expect(fs.statSync(sourceFile).size).to.be(fs.statSync(destFile).size);
|
||||
assert.ok(fs.existsSync(destFile));
|
||||
assert.equal(fs.statSync(sourceFile).size, fs.statSync(destFile).size);
|
||||
});
|
||||
|
||||
it('upload unlinks old file', async function () {
|
||||
@@ -90,23 +85,23 @@ describe('Storage', function () {
|
||||
const uploader = await filesystem.upload(gBackupConfig, {}, 'uploadtest/test.txt');
|
||||
await stream.pipeline(sourceStream, uploader.createStream());
|
||||
await uploader.finish();
|
||||
expect(fs.existsSync(destFile)).to.be(true);
|
||||
expect(fs.statSync(sourceFile).size).to.be(fs.statSync(destFile).size);
|
||||
expect(oldStat.inode).to.not.be(fs.statSync(destFile).size);
|
||||
assert.equal(fs.existsSync(destFile), true);
|
||||
assert.equal(fs.statSync(sourceFile).size, fs.statSync(destFile).size);
|
||||
assert.notEqual(oldStat.inode, fs.statSync(destFile).size);
|
||||
});
|
||||
|
||||
it('can download file', async function () {
|
||||
const sourceFile = path.join(gBackupConfig.backupDir, gBackupConfig.prefix, '/uploadtest/test.txt');
|
||||
const [error, downloadStream] = await safe(filesystem.download(gBackupConfig, 'uploadtest/test.txt'));
|
||||
expect(error).to.be(null);
|
||||
expect(downloadStream).to.be.an('object');
|
||||
assert.equal(error, null);
|
||||
assert.equal(typeof downloadStream, 'object');
|
||||
const data = await consumers.buffer(downloadStream);
|
||||
expect(fs.readFileSync(sourceFile)).to.eql(data); // buffer compare
|
||||
assert.deepEqual(fs.readFileSync(sourceFile), data); // buffer compare
|
||||
});
|
||||
|
||||
it('download errors for missing file', async function () {
|
||||
const [error] = await safe(filesystem.download(gBackupConfig, 'uploadtest/missing'));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('list dir lists the source dir', async function () {
|
||||
@@ -122,7 +117,7 @@ describe('Storage', function () {
|
||||
}
|
||||
|
||||
const expectedFiles = execSync(`find . -type f -printf '%P\n'`, { cwd: sourceDir, encoding: 'utf8' }).trim().split('\n').map(p => `storage/${p}`);
|
||||
expect(allFiles.map(function (f) { return f.path; }).sort()).to.eql(expectedFiles.sort());
|
||||
assert.deepEqual(allFiles.map(function (f) { return f.path; }).sort(), expectedFiles.sort());
|
||||
});
|
||||
|
||||
it('can copy', async function () {
|
||||
@@ -130,14 +125,14 @@ describe('Storage', function () {
|
||||
const destFile = path.join(gBackupConfig.backupDir, gBackupConfig.prefix, '/uploadtest/test-hardlink.txt');
|
||||
|
||||
await filesystem.copy(gBackupConfig, 'uploadtest/test.txt', 'uploadtest/test-hardlink.txt', () => {});
|
||||
expect(fs.statSync(destFile).nlink).to.be(2); // created a hardlink
|
||||
assert.equal(fs.statSync(destFile).nlink, 2); // created a hardlink
|
||||
});
|
||||
|
||||
it('can remove file', async function () {
|
||||
const sourceFile = path.join(gBackupConfig.backupDir, gBackupConfig.prefix, '/uploadtest/test-hardlink.txt');
|
||||
|
||||
await filesystem.remove(gBackupConfig, 'uploadtest/test-hardlink.txt');
|
||||
expect(fs.existsSync(sourceFile)).to.be(false);
|
||||
assert.equal(fs.existsSync(sourceFile), false);
|
||||
});
|
||||
|
||||
it('can remove empty dir', async function () {
|
||||
@@ -145,7 +140,7 @@ describe('Storage', function () {
|
||||
fs.mkdirSync(sourceDir);
|
||||
|
||||
await filesystem.remove(gBackupConfig, 'emptydir', () => {});
|
||||
expect(fs.existsSync(sourceDir)).to.be(false);
|
||||
assert.equal(fs.existsSync(sourceDir), false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -181,21 +176,21 @@ describe('Storage', function () {
|
||||
|
||||
class S3Mock {
|
||||
constructor(cfg) {
|
||||
expect(cfg.credentials).to.eql({ // retryDelayOptions is a function
|
||||
assert.deepEqual(cfg.credentials, { // retryDelayOptions is a function
|
||||
accessKeyId: backupConfig.accessKeyId,
|
||||
secretAccessKey: backupConfig.secretAccessKey
|
||||
});
|
||||
expect(cfg.region).to.be(backupConfig.region);
|
||||
assert.equal(cfg.region, backupConfig.region);
|
||||
}
|
||||
|
||||
async headObject(params) {
|
||||
expect(params.Bucket).to.be(backupConfig.bucket);
|
||||
assert.equal(params.Bucket, backupConfig.bucket);
|
||||
const stat = await fs.promises.stat(path.join(bucketPathNoPrefix, params.Key));
|
||||
return { ContentLength: stat.size };
|
||||
}
|
||||
|
||||
async listObjectsV2(params) {
|
||||
expect(params.Bucket).to.be(backupConfig.bucket);
|
||||
assert.equal(params.Bucket, backupConfig.bucket);
|
||||
return {
|
||||
Contents: [{
|
||||
Key: `${backupConfig.prefix}/uploadtest/test.txt`,
|
||||
@@ -218,12 +213,12 @@ describe('Storage', function () {
|
||||
}
|
||||
|
||||
async deleteObject(params) {
|
||||
expect(params.Bucket).to.be(backupConfig.bucket);
|
||||
assert.equal(params.Bucket, backupConfig.bucket);
|
||||
fs.rmSync(path.join(bucketPathNoPrefix, params.Key));
|
||||
}
|
||||
|
||||
async deleteObjects(params) {
|
||||
expect(params.Bucket).to.be(backupConfig.bucket);
|
||||
assert.equal(params.Bucket, backupConfig.bucket);
|
||||
params.Delete.Objects.forEach(o => fs.rmSync(path.join(bucketPathNoPrefix, o.Key)));
|
||||
}
|
||||
}
|
||||
@@ -247,15 +242,15 @@ describe('Storage', function () {
|
||||
const uploader = await s3.upload(backupConfig, {}, destKey);
|
||||
await stream.pipeline(sourceStream, uploader.createStream());
|
||||
await uploader.finish();
|
||||
expect(fs.existsSync(path.join(bucketPath, destKey))).to.be(true);
|
||||
expect(fs.statSync(path.join(bucketPath, destKey)).size).to.be(fs.statSync(sourceFile).size);
|
||||
assert.equal(fs.existsSync(path.join(bucketPath, destKey)), true);
|
||||
assert.equal(fs.statSync(path.join(bucketPath, destKey)).size, fs.statSync(sourceFile).size);
|
||||
});
|
||||
|
||||
it('can download file', async function () {
|
||||
const sourceKey = 'uploadtest/test.txt';
|
||||
const [error, outstream] = await safe(s3.download(backupConfig, sourceKey));
|
||||
expect(error).to.be(null);
|
||||
expect(outstream).to.be.an('object');
|
||||
assert.equal(error, null);
|
||||
assert.equal(typeof outstream, 'object');
|
||||
});
|
||||
|
||||
it('list dir lists contents of source dir', async function () {
|
||||
@@ -268,7 +263,7 @@ describe('Storage', function () {
|
||||
marker = result.marker;
|
||||
}
|
||||
|
||||
expect(allFiles.map(function (f) { return f.path; })).to.contain('uploadtest/test.txt');
|
||||
assert.ok(allFiles.map(function (f) { return f.path; }).includes('uploadtest/test.txt'));
|
||||
});
|
||||
|
||||
it('can copy', async function () {
|
||||
@@ -276,18 +271,18 @@ describe('Storage', function () {
|
||||
|
||||
await s3.copyDir(backupConfig, {}, 'uploadtest', 'uploadtest-copy', () => {});
|
||||
const sourceFile = path.join(import.meta.dirname, 'storage/data/test.txt');
|
||||
expect(fs.statSync(path.join(bucketPath, 'uploadtest-copy/test.txt')).size).to.be(fs.statSync(sourceFile).size);
|
||||
expect(fs.statSync(path.join(bucketPath, 'uploadtest-copy/C++.gitignore')).size).to.be(7);
|
||||
assert.equal(fs.statSync(path.join(bucketPath, 'uploadtest-copy/test.txt')).size, fs.statSync(sourceFile).size);
|
||||
assert.equal(fs.statSync(path.join(bucketPath, 'uploadtest-copy/C++.gitignore')).size, 7);
|
||||
});
|
||||
|
||||
it('can remove file', async function () {
|
||||
await s3.remove(backupConfig, 'uploadtest/test.txt');
|
||||
expect(fs.existsSync(path.join(bucketPath, 'uploadtest/test.txt'))).to.be(false);
|
||||
assert.equal(fs.existsSync(path.join(bucketPath, 'uploadtest/test.txt')), false);
|
||||
});
|
||||
|
||||
it('cannot remove non-existent file', async function () {
|
||||
const [error] = await safe(s3.remove(backupConfig, 'blah'));
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -310,7 +305,7 @@ describe('Storage', function () {
|
||||
|
||||
class GCSMockBucket {
|
||||
constructor(name) {
|
||||
expect(name).to.be(backupConfig.bucket);
|
||||
assert.equal(name, backupConfig.bucket);
|
||||
}
|
||||
file(key) { // already has prefix
|
||||
// console.log('gcs file object:', key);
|
||||
@@ -344,8 +339,8 @@ describe('Storage', function () {
|
||||
};
|
||||
}
|
||||
async getFiles(q) {
|
||||
expect(q.maxResults).to.be.a('number');
|
||||
expect(q.prefix).to.be.a('string');
|
||||
assert.equal(typeof q.maxResults, 'number');
|
||||
assert.equal(typeof q.prefix, 'string');
|
||||
|
||||
const files = [{
|
||||
name: `${backupConfig.prefix}/uploadtest/test.txt`,
|
||||
@@ -359,8 +354,8 @@ describe('Storage', function () {
|
||||
|
||||
class GCSMock {
|
||||
constructor(config) {
|
||||
expect(config.projectId).to.be(backupConfig.projectId);
|
||||
expect(config.credentials.private_key).to.be(backupConfig.credentials.private_key);
|
||||
assert.equal(config.projectId, backupConfig.projectId);
|
||||
assert.equal(config.credentials.private_key, backupConfig.credentials.private_key);
|
||||
}
|
||||
|
||||
bucket(name) {
|
||||
@@ -384,15 +379,15 @@ describe('Storage', function () {
|
||||
const uploader = await gcs.upload(backupConfig, {}, destKey);
|
||||
await stream.pipeline(sourceStream, uploader.createStream());
|
||||
await uploader.finish();
|
||||
expect(fs.existsSync(path.join(bucketPath, destKey))).to.be(true);
|
||||
expect(fs.statSync(path.join(bucketPath, destKey)).size).to.be(fs.statSync(sourceFile).size);
|
||||
assert.equal(fs.existsSync(path.join(bucketPath, destKey)), true);
|
||||
assert.equal(fs.statSync(path.join(bucketPath, destKey)).size, fs.statSync(sourceFile).size);
|
||||
});
|
||||
|
||||
it('can download file', async function () {
|
||||
const sourceKey = 'uploadtest/test.txt';
|
||||
const [error, downloadStream] = await safe(gcs.download(backupConfig, sourceKey));
|
||||
expect(error).to.be(null);
|
||||
expect(downloadStream).to.be.an('object');
|
||||
assert.equal(error, null);
|
||||
assert.equal(typeof downloadStream, 'object');
|
||||
});
|
||||
|
||||
it('list dir lists contents of source dir', async function () {
|
||||
@@ -405,7 +400,7 @@ describe('Storage', function () {
|
||||
marker = result.marker;
|
||||
}
|
||||
|
||||
expect(allFiles.map(function (f) { return f.path; })).to.contain('uploadtest/test.txt');
|
||||
assert.ok(allFiles.map(function (f) { return f.path; }).includes('uploadtest/test.txt'));
|
||||
});
|
||||
|
||||
it('can copy', async function () {
|
||||
@@ -413,13 +408,13 @@ describe('Storage', function () {
|
||||
|
||||
await gcs.copyDir(backupConfig, {}, 'uploadtest', 'uploadtest-copy', () => {});
|
||||
const sourceFile = path.join(import.meta.dirname, 'storage/data/test.txt');
|
||||
expect(fs.statSync(path.join(bucketPath, 'uploadtest-copy/test.txt')).size).to.be(fs.statSync(sourceFile).size);
|
||||
expect(fs.statSync(path.join(bucketPath, 'uploadtest-copy/C++.gitignore')).size).to.be(7);
|
||||
assert.equal(fs.statSync(path.join(bucketPath, 'uploadtest-copy/test.txt')).size, fs.statSync(sourceFile).size);
|
||||
assert.equal(fs.statSync(path.join(bucketPath, 'uploadtest-copy/C++.gitignore')).size, 7);
|
||||
});
|
||||
|
||||
it('can remove file', async function () {
|
||||
await gcs.remove(backupConfig, 'uploadtest-copy/test.txt');
|
||||
expect(fs.existsSync(path.join(basePath, 'uploadtest-copy/test.txt'))).to.be(false);
|
||||
assert.equal(fs.existsSync(path.join(basePath, 'uploadtest-copy/test.txt')), false);
|
||||
});
|
||||
|
||||
it('can remove non-existent dir', async function () {
|
||||
|
||||
+12
-13
@@ -1,10 +1,9 @@
|
||||
/* global it:false */
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
import superagent from '@cloudron/superagent';
|
||||
|
||||
/* global describe:false */
|
||||
|
||||
describe('Superagent', function () {
|
||||
it('can get URL', async function () {
|
||||
@@ -13,40 +12,40 @@ describe('Superagent', function () {
|
||||
|
||||
it('cannot get invalid URL', async function () {
|
||||
const [error] = await safe(superagent.get('htt://www.cloudron.io'));
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
});
|
||||
|
||||
it('cannot get non-existent domain', async function () {
|
||||
const [error] = await safe(superagent.get('https://www.cloudron.io.nxdomain'));
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
});
|
||||
|
||||
it('throws for 404', async function () {
|
||||
const [error] = await safe(superagent.get('https://www.cloudron.io/no-such-page'));
|
||||
expect(error).to.be.ok();
|
||||
expect(error.status).to.be(404);
|
||||
expect(error.text).to.be.a('string');
|
||||
assert.ok(error);
|
||||
assert.equal(error.status, 404);
|
||||
assert.equal(typeof error.text, 'string');
|
||||
});
|
||||
|
||||
it('can catch a 404', async function () {
|
||||
const response = await superagent.get('https://www.cloudron.io/no-such-page').ok(({status}) => status === 404);
|
||||
expect(response.status).to.be(404);
|
||||
expect(response.text).to.be.a('string');
|
||||
assert.equal(response.status, 404);
|
||||
assert.equal(typeof response.text, 'string');
|
||||
});
|
||||
|
||||
it('did parse json', async function () {
|
||||
const response = await superagent.get('https://ipv4.api.cloudron.io/api/v1/helper/public_ip');
|
||||
expect(response.body.ip).to.be.ok();
|
||||
assert.ok(response.body.ip);
|
||||
});
|
||||
|
||||
it('follows redirect', async function () {
|
||||
const response = await superagent.get('https://cloudron.io').set('User-Agent', 'Mozilla').timeout(10*1000);
|
||||
expect(response.url.toString()).to.be('https://www.cloudron.io/');
|
||||
assert.equal(response.url.toString(), 'https://www.cloudron.io/');
|
||||
});
|
||||
|
||||
it('can disable redirects', async function () {
|
||||
const [error] = await safe(superagent.get('https://cloudron.io').set('User-Agent', 'Mozilla').timeout(10*1000).redirects(0));
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
});
|
||||
|
||||
it('can disable certs', async function () {
|
||||
|
||||
+26
-28
@@ -1,10 +1,10 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before } from 'node:test';
|
||||
|
||||
import common from './common.js';
|
||||
const { createTree } = common;
|
||||
import DataLayout from '../datalayout.js';
|
||||
import { execSync } from 'node:child_process';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
@@ -12,8 +12,6 @@ import paths from '../paths.js';
|
||||
import safe from 'safetydance';
|
||||
import syncer from '../syncer.js';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
|
||||
const gTmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'syncer-test')),
|
||||
gCacheFile = path.join(paths.BACKUP_INFO_DIR, 'syncer-test.sync.cache');
|
||||
@@ -49,11 +47,11 @@ describe('Syncer', function () {
|
||||
// for every 'delete' operation, there must be no entry in the cache file
|
||||
for (const change of changes) {
|
||||
if (change.operation === 'add') {
|
||||
expect(pathMap.get(change.path).integrity.sha256).to.be('fake-sha256');
|
||||
expect(pathMap.get(change.path).stat).to.be.an('object');
|
||||
assert.equal(pathMap.get(change.path).integrity.sha256, 'fake-sha256');
|
||||
assert.equal(typeof pathMap.get(change.path).stat, 'object');
|
||||
} else if (change.operation === 'remove') {
|
||||
// if a file was removed, it won't be in pathMap. but if the file became a dir, it can be in pathMap without integrity info
|
||||
expect(!pathMap.has(change.path) || !pathMap.get(change.path).integrity).to.be(true);
|
||||
assert.equal(!pathMap.has(change.path) || !pathMap.get(change.path).integrity, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,9 +62,9 @@ describe('Syncer', function () {
|
||||
|
||||
const dataLayout = new DataLayout(gTmpDir, []);
|
||||
const changes = await getChanges(dataLayout);
|
||||
expect(changes).to.eql([{ operation: 'removedir', path: '', reason: 'nocache' }]);
|
||||
assert.deepEqual(changes, [{ operation: 'removedir', path: '', reason: 'nocache' }]);
|
||||
|
||||
expect(fs.readFileSync(gCacheFile, 'utf8')).to.be('');
|
||||
assert.equal(fs.readFileSync(gCacheFile, 'utf8'), '');
|
||||
});
|
||||
|
||||
it('empty cache - adds all', async function () {
|
||||
@@ -76,7 +74,7 @@ describe('Syncer', function () {
|
||||
const dataLayout = new DataLayout(gTmpDir, []);
|
||||
const changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes).to.eql([
|
||||
assert.deepEqual(changes, [
|
||||
{ operation: 'add', path: 'src/index.js', reason: 'new', position: 0 },
|
||||
{ operation: 'add', path: 'test/test.js', reason: 'new', position: 1 },
|
||||
{ operation: 'add', path: 'walrus', reason: 'new', position: 2 }
|
||||
@@ -92,7 +90,7 @@ describe('Syncer', function () {
|
||||
const dataLayout = new DataLayout(gTmpDir, []);
|
||||
const changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes).to.eql([
|
||||
assert.deepEqual(changes, [
|
||||
{ operation: 'add', path: 'a/b/c/d/e', reason: 'new', position: 0 }
|
||||
]);
|
||||
|
||||
@@ -106,7 +104,7 @@ describe('Syncer', function () {
|
||||
const dataLayout = new DataLayout(gTmpDir, []);
|
||||
const changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes).to.eql([
|
||||
assert.deepEqual(changes, [
|
||||
{ operation: 'add', path: 'readme', reason: 'new', position: 0 }
|
||||
]);
|
||||
|
||||
@@ -120,13 +118,13 @@ describe('Syncer', function () {
|
||||
const dataLayout = new DataLayout(gTmpDir, []);
|
||||
let changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes.length).to.be(3);
|
||||
assert.equal(changes.length, 3);
|
||||
|
||||
execSync('touch src/index.js test/test.js', { cwd: gTmpDir });
|
||||
|
||||
changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes).to.eql([
|
||||
assert.deepEqual(changes, [
|
||||
{ operation: 'add', path: 'src/index.js', reason: 'changed', position: 0 },
|
||||
{ operation: 'add', path: 'test/test.js', reason: 'changed', position: 1 }
|
||||
]);
|
||||
@@ -141,13 +139,13 @@ describe('Syncer', function () {
|
||||
const dataLayout = new DataLayout(gTmpDir, []);
|
||||
let changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes.length).to.be(3);
|
||||
assert.equal(changes.length, 3);
|
||||
|
||||
execSync('rm src/index.js walrus', { cwd: gTmpDir });
|
||||
|
||||
changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes).to.eql([
|
||||
assert.deepEqual(changes, [
|
||||
{ operation: 'remove', path: 'src/index.js', reason: 'missing' },
|
||||
{ operation: 'remove', path: 'walrus', reason: 'missing' }
|
||||
]);
|
||||
@@ -162,13 +160,13 @@ describe('Syncer', function () {
|
||||
const dataLayout = new DataLayout(gTmpDir, []);
|
||||
let changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes.length).to.be(3);
|
||||
assert.equal(changes.length, 3);
|
||||
|
||||
execSync('rm -rf src test', { cwd: gTmpDir });
|
||||
|
||||
changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes).to.eql([
|
||||
assert.deepEqual(changes, [
|
||||
{ operation: 'removedir', path: 'src', reason: 'missing' },
|
||||
{ operation: 'removedir', path: 'test', reason: 'missing' }
|
||||
]);
|
||||
@@ -183,13 +181,13 @@ describe('Syncer', function () {
|
||||
const dataLayout = new DataLayout(gTmpDir, []);
|
||||
let changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes.length).to.be(3);
|
||||
assert.equal(changes.length, 3);
|
||||
|
||||
execSync('find . -delete', { cwd: gTmpDir });
|
||||
|
||||
changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes).to.eql([
|
||||
assert.deepEqual(changes, [
|
||||
{ operation: 'removedir', path: 'src', reason: 'missing' },
|
||||
{ operation: 'removedir', path: 'test', reason: 'missing' },
|
||||
{ operation: 'remove', path: 'walrus', reason: 'missing' }
|
||||
@@ -205,13 +203,13 @@ describe('Syncer', function () {
|
||||
const dataLayout = new DataLayout(gTmpDir, []);
|
||||
let changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes.length).to.be(1);
|
||||
assert.equal(changes.length, 1);
|
||||
|
||||
execSync('rm -r a/b; touch a/f', { cwd: gTmpDir });
|
||||
|
||||
changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes).to.eql([
|
||||
assert.deepEqual(changes, [
|
||||
{ operation: 'removedir', path: 'a/b', reason: 'missing' },
|
||||
{ operation: 'add', path: 'a/f', reason: 'new', position: 0 }
|
||||
]);
|
||||
@@ -226,13 +224,13 @@ describe('Syncer', function () {
|
||||
const dataLayout = new DataLayout(gTmpDir, []);
|
||||
let changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes.length).to.be(3);
|
||||
assert.equal(changes.length, 3);
|
||||
|
||||
execSync('rm data/test/test.js; mkdir data/test/test.js; touch data/test/test.js/trick', { cwd: gTmpDir });
|
||||
|
||||
changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes).to.eql([
|
||||
assert.deepEqual(changes, [
|
||||
{ operation: 'remove', path: 'data/test/test.js', reason: 'wasfile' },
|
||||
{ operation: 'add', path: 'data/test/test.js/trick', reason: 'new', position: 0 }
|
||||
]);
|
||||
@@ -247,13 +245,13 @@ describe('Syncer', function () {
|
||||
const dataLayout = new DataLayout(gTmpDir, []);
|
||||
let changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes.length).to.be(4);
|
||||
assert.equal(changes.length, 4);
|
||||
|
||||
execSync('rm -r test; touch test', { cwd: gTmpDir });
|
||||
|
||||
changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes).to.eql([
|
||||
assert.deepEqual(changes, [
|
||||
{ operation: 'removedir', path: 'test', reason: 'wasdir' },
|
||||
{ operation: 'add', path: 'test', reason: 'wasdir', position: 0 }
|
||||
]);
|
||||
@@ -296,7 +294,7 @@ describe('Syncer', function () {
|
||||
|
||||
changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes).to.eql([
|
||||
assert.deepEqual(changes, [
|
||||
{ operation: 'remove', path: 'a', reason: 'wasfile' },
|
||||
{ operation: 'remove', path: 'a2', reason: 'missing' },
|
||||
{ operation: 'remove', path: 'file', reason: 'missing' },
|
||||
@@ -311,7 +309,7 @@ describe('Syncer', function () {
|
||||
|
||||
changes = await getChanges(dataLayout);
|
||||
|
||||
expect(changes.length).to.be(0);
|
||||
assert.equal(changes.length, 0);
|
||||
|
||||
checkCache(gCacheFile, changes);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
/* global it:false */
|
||||
import { describe, it, after } from 'node:test';
|
||||
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import net from 'node:net';
|
||||
import path from 'node:path';
|
||||
@@ -10,8 +10,6 @@ import safe from 'safetydance';
|
||||
import syslogServer from '../../syslog.js';
|
||||
import timers from 'timers/promises';
|
||||
|
||||
/* global describe:false */
|
||||
/* global after:false */
|
||||
|
||||
async function sendMessage(message) {
|
||||
const client = net.createConnection(paths.SYSLOG_SOCKET_FILE);
|
||||
@@ -34,8 +32,7 @@ async function verifyMessage(pattern, fileName) {
|
||||
if (found === null) throw new Error(`${pattern} not found in ${fileName}`);
|
||||
}
|
||||
|
||||
describe('Syslog', function () {
|
||||
this.timeout(5000);
|
||||
describe('Syslog', { timeout: 5000 }, function () {
|
||||
|
||||
after(async function () {
|
||||
await syslogServer.stop();
|
||||
@@ -57,7 +54,7 @@ describe('Syslog', function () {
|
||||
const invalidLine = 'foobar';
|
||||
await sendMessage(invalidLine);
|
||||
const [error] = await safe(verifyMessage(/foobar/, 'testapp/app.log'));
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
});
|
||||
|
||||
it('can handle message with colons', async function () {
|
||||
|
||||
+19
-22
@@ -1,15 +1,12 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import child_process from 'node:child_process';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import nock from 'nock';
|
||||
import system from '../system.js';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('System', function () {
|
||||
const { setup, cleanup } = common;
|
||||
@@ -25,8 +22,8 @@ describe('System', function () {
|
||||
if (child_process.execSync('uname -a').toString().indexOf('-arch') !== -1) return;
|
||||
|
||||
const filesystems = await system.getFilesystems();
|
||||
expect(filesystems).to.be.ok();
|
||||
expect(filesystems.some(fs => fs.mountpoint === '/')).to.be(true);
|
||||
assert.ok(filesystems);
|
||||
assert.equal(filesystems.some(fs => fs.mountpoint === '/'), true);
|
||||
});
|
||||
|
||||
it('can get swaps', async function () {
|
||||
@@ -34,8 +31,8 @@ describe('System', function () {
|
||||
if (child_process.execSync('uname -a').toString().indexOf('-arch') !== -1) return;
|
||||
|
||||
const swaps = await system.getSwaps();
|
||||
expect(swaps).to.be.ok();
|
||||
expect(Object.keys(swaps).some(n => swaps[n].type === 'partition' || swaps[n].type === 'file')).to.be.ok();
|
||||
assert.ok(swaps);
|
||||
assert.ok(Object.keys(swaps).some(n => swaps[n].type === 'partition' || swaps[n].type === 'file'));
|
||||
});
|
||||
|
||||
it('can check for disk space', async function () {
|
||||
@@ -47,49 +44,49 @@ describe('System', function () {
|
||||
|
||||
it('can get memory', async function () {
|
||||
const memory = await system.getMemory();
|
||||
expect(memory.memory).to.be.a('number');
|
||||
expect(memory.swap).to.be.a('number');
|
||||
assert.equal(typeof memory.memory, 'number');
|
||||
assert.equal(typeof memory.swap, 'number');
|
||||
});
|
||||
|
||||
it('can get CPUs', async function () {
|
||||
const cpus = await system.getCpus();
|
||||
expect(cpus).to.be.an(Array);
|
||||
expect(cpus[0].model).to.be.a('string');
|
||||
assert.ok(Array.isArray(cpus));
|
||||
assert.equal(typeof cpus[0].model, 'string');
|
||||
});
|
||||
|
||||
it('can get ubuntu version', async function () {
|
||||
const v = await system.getUbuntuVersion();
|
||||
expect(v).to.be.ok();
|
||||
assert.ok(v);
|
||||
});
|
||||
|
||||
it('can get kernel version', async function () {
|
||||
const v = await system.getKernelVersion();
|
||||
expect(v).to.be.ok();
|
||||
assert.ok(v);
|
||||
});
|
||||
|
||||
it('can get info', async function () {
|
||||
const info = await system.getInfo();
|
||||
|
||||
expect(info.sysVendor).to.be.a('string');
|
||||
expect(info.productName).to.be.a('string');
|
||||
expect(info.uptimeSecs).to.be.a('number');
|
||||
expect(info.rebootRequired).to.be.a('boolean');
|
||||
assert.equal(typeof info.sysVendor, 'string');
|
||||
assert.equal(typeof info.productName, 'string');
|
||||
assert.equal(typeof info.uptimeSecs, 'number');
|
||||
assert.equal(typeof info.rebootRequired, 'boolean');
|
||||
});
|
||||
|
||||
it('can get block devices', async function () {
|
||||
const devices = await system.getBlockDevices();
|
||||
expect(devices).to.be.ok();
|
||||
assert.ok(devices);
|
||||
});
|
||||
|
||||
it('can get filesystems', async function () {
|
||||
const filesystems = await system.getFilesystems();
|
||||
expect(filesystems.find(v => v.mountpoint === '/')).to.be.ok();
|
||||
assert.ok(filesystems.find(v => v.mountpoint === '/'));
|
||||
});
|
||||
|
||||
it('can get filesystemUsage', async function () {
|
||||
const filesystems = await system.getFilesystems();
|
||||
const rootFs = filesystems.find(v => v.mountpoint === '/');
|
||||
expect(rootFs.filesystem).to.be.ok();
|
||||
assert.ok(rootFs.filesystem);
|
||||
|
||||
const usageTask = await system.getFilesystemUsage(rootFs.filesystem);
|
||||
|
||||
|
||||
+25
-28
@@ -1,18 +1,15 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import paths from '../paths.js';
|
||||
import safe from 'safetydance';
|
||||
import tasks from '../tasks.js';
|
||||
import _ from '../underscore.js';
|
||||
|
||||
/* global it:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
/* global describe:false */
|
||||
|
||||
describe('task', function () {
|
||||
const { setup, cleanup } = common;
|
||||
@@ -31,18 +28,18 @@ describe('task', function () {
|
||||
|
||||
it('add succeeds', async function () {
|
||||
const id = await tasks.add(TASK.type, TASK.args);
|
||||
expect(id).to.be.ok();
|
||||
assert.ok(id);
|
||||
taskId = id;
|
||||
});
|
||||
|
||||
it('get succeeds', async function () {
|
||||
const task = await tasks.get(taskId);
|
||||
expect(_.pick(task, Object.keys(TASK))).to.eql(TASK);
|
||||
assert.deepEqual(_.pick(task, Object.keys(TASK)), TASK);
|
||||
});
|
||||
|
||||
it('get random task fails', async function () {
|
||||
const task = await tasks.get('random');
|
||||
expect(task).to.be(null);
|
||||
assert.equal(task, null);
|
||||
});
|
||||
|
||||
it('update succeeds', async function () {
|
||||
@@ -50,35 +47,35 @@ describe('task', function () {
|
||||
TASK.message = 'almost ther';
|
||||
await tasks.update(taskId, { percent: TASK.percent, message: TASK.message });
|
||||
const task = await tasks.get(taskId);
|
||||
expect(_.pick(task, Object.keys(TASK))).to.eql(TASK);
|
||||
assert.deepEqual(_.pick(task, Object.keys(TASK)), TASK);
|
||||
});
|
||||
|
||||
it('list succeeds - does not exist', async function () {
|
||||
const result = await tasks.list(1, 1, { type: 'randomtask' });
|
||||
expect(result.length).to.be(0);
|
||||
assert.equal(result.length, 0);
|
||||
});
|
||||
|
||||
it('list succeeds - by type', async function () {
|
||||
const result = await tasks.list(1, 1, { type: TASK.type });
|
||||
expect(result.length).to.be(1);
|
||||
expect(_.pick(result[0], Object.keys(TASK))).to.eql(TASK);
|
||||
assert.equal(result.length, 1);
|
||||
assert.deepEqual(_.pick(result[0], Object.keys(TASK)), TASK);
|
||||
});
|
||||
|
||||
it('list succeeds - all', async function () {
|
||||
const result = await tasks.list(1, 1, { type: null });
|
||||
expect(result.length).to.be(1);
|
||||
expect(_.pick(result[0], Object.keys(TASK))).to.eql(TASK);
|
||||
assert.equal(result.length, 1);
|
||||
assert.deepEqual(_.pick(result[0], Object.keys(TASK)), TASK);
|
||||
});
|
||||
|
||||
it('del succeeds', async function () {
|
||||
await tasks._del(taskId);
|
||||
const task = await tasks.get(taskId);
|
||||
expect(task).to.be(null);
|
||||
assert.equal(task, null);
|
||||
});
|
||||
|
||||
it('del missing task fails', async function () {
|
||||
const [error] = await safe(tasks._del('1235'));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('can run valid task - success', async function () {
|
||||
@@ -86,7 +83,7 @@ describe('task', function () {
|
||||
|
||||
const [error, result] = await safe(tasks.startTask(successTaskId, {}));
|
||||
if (error) throw error;
|
||||
expect(result).to.equal('ping');
|
||||
assert.equal(result, 'ping');
|
||||
});
|
||||
|
||||
it('can run valid task - error', async function () {
|
||||
@@ -94,8 +91,8 @@ describe('task', function () {
|
||||
|
||||
const [error, result] = await safe(tasks.startTask(errorTaskId, {}));
|
||||
if (!error) throw new Error('expecting task to fail');
|
||||
expect(error.message).to.be('Task crashed. Failed for arg: ping');
|
||||
expect(result).to.not.be.ok();
|
||||
assert.equal(error.message, 'Task crashed. Failed for arg: ping');
|
||||
assert.ok(!(result));
|
||||
});
|
||||
|
||||
it('can get logs of crash', async function () {
|
||||
@@ -103,11 +100,11 @@ describe('task', function () {
|
||||
|
||||
const [error, result] = await safe(tasks.startTask(crashTaskId, {}));
|
||||
if (!error) throw new Error('expecting task to crash');
|
||||
expect(error.message).to.contain(`Task ${crashTaskId} crashed`);
|
||||
expect(result).to.not.be.ok();
|
||||
assert.ok(error.message.includes(`Task ${crashTaskId} crashed`));
|
||||
assert.ok(!(result));
|
||||
|
||||
const logs = fs.readFileSync(`${paths.TASKS_LOG_DIR}/${crashTaskId}.log`, 'utf8');
|
||||
expect(logs).to.contain('Crashing for arg: ping');
|
||||
assert.ok(logs.includes('Crashing for arg: ping'));
|
||||
});
|
||||
|
||||
it('can stop task', async function () {
|
||||
@@ -119,9 +116,9 @@ describe('task', function () {
|
||||
|
||||
const [error, result] = await safe(tasks.startTask(sleepTaskId, {}));
|
||||
if (!error) throw new Error('expecting task to stop');
|
||||
expect(error.message).to.contain('stopped');
|
||||
expect(error.code).to.be(tasks.ESTOPPED);
|
||||
expect(result).to.not.be.ok();
|
||||
assert.ok(error.message.includes('stopped'));
|
||||
assert.equal(error.code, tasks.ESTOPPED);
|
||||
assert.ok(!(result));
|
||||
});
|
||||
|
||||
it('task timesout', async function () {
|
||||
@@ -129,8 +126,8 @@ describe('task', function () {
|
||||
|
||||
const [error, result] = await safe(tasks.startTask(timeoutTaskId, { timeout: 2000 }));
|
||||
if (!error) throw new Error('expecting task to timeout');
|
||||
expect(error.code).to.be(tasks.ETIMEOUT);
|
||||
expect(error.message).to.contain('timed out');
|
||||
expect(result).to.not.be.ok();
|
||||
assert.equal(error.code, tasks.ETIMEOUT);
|
||||
assert.ok(error.message.includes('timed out'));
|
||||
assert.ok(!(result));
|
||||
});
|
||||
});
|
||||
|
||||
+24
-27
@@ -1,16 +1,13 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import oidcClients from '../oidcclients.js';
|
||||
import safe from 'safetydance';
|
||||
import tokens from '../tokens.js';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Tokens', function () {
|
||||
const { setup, cleanup } = common;
|
||||
@@ -34,35 +31,35 @@ describe('Tokens', function () {
|
||||
const badToken = Object.assign({}, TOKEN_0);
|
||||
badToken.name = new Array(100).fill('x').join('');
|
||||
const [error] = await safe(tokens.add(badToken));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('add fails with unknown scope', async function () {
|
||||
const badToken = Object.assign({}, TOKEN_0);
|
||||
badToken.scope = { 'foobar': 'rw', '*': 'r' };
|
||||
const [error] = await safe(tokens.add(badToken));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('add fails with invalid scope rule', async function () {
|
||||
const badToken = Object.assign({}, TOKEN_0);
|
||||
badToken.scope = { '*': 'rw ' };
|
||||
const [error] = await safe(tokens.add(badToken));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('add fails with bad name', async function () {
|
||||
const badToken = Object.assign({}, TOKEN_0);
|
||||
badToken.name = new Array(100).fill('x').join('');
|
||||
const [error] = await safe(tokens.add(badToken));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('add fails for bad allowed ips', async function () {
|
||||
const badToken = Object.assign({}, TOKEN_0);
|
||||
badToken.allowedIpRanges = '1.2.3./4';
|
||||
const [error] = await safe(tokens.add(badToken));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('add succeeds', async function () {
|
||||
@@ -73,31 +70,31 @@ describe('Tokens', function () {
|
||||
|
||||
it('get succeeds', async function () {
|
||||
const result = await tokens.get(TOKEN_0.id);
|
||||
expect(result).to.be.eql(TOKEN_0);
|
||||
assert.deepEqual(result, TOKEN_0);
|
||||
});
|
||||
|
||||
it('getByAccessToken succeeds', async function () {
|
||||
const result = await tokens.getByAccessToken(TOKEN_0.accessToken);
|
||||
expect(result).to.be.eql(TOKEN_0);
|
||||
assert.deepEqual(result, TOKEN_0);
|
||||
});
|
||||
|
||||
it('get of nonexisting token fails', async function () {
|
||||
const result = await tokens.getByAccessToken('somerandomaccesstoken');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('listByUserId succeeds', async function () {
|
||||
const result = await tokens.listByUserId(TOKEN_0.identifier);
|
||||
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);
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 1);
|
||||
assert.equal(typeof result[0], 'object');
|
||||
assert.deepEqual(result[0], TOKEN_0);
|
||||
});
|
||||
|
||||
it('delete fails', async function () {
|
||||
const [error] = await safe(tokens.del(TOKEN_0.id + 'x'));
|
||||
expect(error).to.be.a(BoxError);
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.ok((error) instanceof (BoxError));
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('delete succeeds', async function () {
|
||||
@@ -106,13 +103,13 @@ describe('Tokens', function () {
|
||||
|
||||
it('get returns null after token deletion', async function () {
|
||||
const result = await tokens.get(TOKEN_0.id);
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('cannot delete previously delete record', async function () {
|
||||
const [error] = await safe(tokens.del(TOKEN_0.id));
|
||||
expect(error).to.be.a(BoxError);
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.ok((error) instanceof (BoxError));
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('delExpired succeeds', async function () {
|
||||
@@ -145,10 +142,10 @@ describe('Tokens', function () {
|
||||
await tokens.delExpired();
|
||||
|
||||
result = await tokens.getByAccessToken(token2.accessToken);
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
|
||||
result = await tokens.getByAccessToken(token1.accessToken);
|
||||
expect(result).to.eql(token1);
|
||||
assert.deepEqual(result, token1);
|
||||
});
|
||||
|
||||
it('delByUserIdAndType succeeds', async function () {
|
||||
@@ -175,11 +172,11 @@ describe('Tokens', function () {
|
||||
|
||||
await tokens.delByUserIdAndType('user2', oidcClients.ID_WEBADMIN);
|
||||
let result = await tokens.listByUserId('user1');
|
||||
expect(result.length).to.be(2); // should not have deleted user1 tokens
|
||||
assert.equal(result.length, 2); // should not have deleted user1 tokens
|
||||
|
||||
await tokens.delByUserIdAndType('user1', oidcClients.ID_WEBADMIN);
|
||||
result = await tokens.listByUserId('user1');
|
||||
expect(result.length).to.be(1);
|
||||
expect(result[0].name).to.be(token2.name);
|
||||
assert.equal(result.length, 1);
|
||||
assert.equal(result[0].name, token2.name);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { describe, it } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import translations from '../translations.js';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
|
||||
describe('translation', function () {
|
||||
|
||||
@@ -12,31 +11,31 @@ describe('translation', function () {
|
||||
it('nonexisting token', function () {
|
||||
const assets = { translations: {}, fallback: {} };
|
||||
const out = translations.translate('Foo {{ bar }}', assets);
|
||||
expect(out).to.contain('{{ bar }}');
|
||||
assert.ok(out.includes('{{ bar }}'));
|
||||
});
|
||||
|
||||
it('existing token', function () {
|
||||
const assets = { translations: { bar: 'here' }, fallback: {} };
|
||||
const out = translations.translate('Foo {{ bar }}', assets);
|
||||
expect(out).to.contain('here');
|
||||
assert.ok(out.includes('here'));
|
||||
});
|
||||
|
||||
it('existing token as fallback', function () {
|
||||
const assets = { translations: {}, fallback: { bar: 'here' } };
|
||||
const out = translations.translate('Foo {{ bar }}', assets);
|
||||
expect(out).to.contain('here');
|
||||
assert.ok(out.includes('here'));
|
||||
});
|
||||
|
||||
it('existing token deep', function () {
|
||||
const assets = { translations: { bar: { baz: { foo: 'here' }}}, fallback: {} };
|
||||
const out = translations.translate('Foo {{ bar.baz.foo }}', assets);
|
||||
expect(out).to.contain('here');
|
||||
assert.ok(out.includes('here'));
|
||||
});
|
||||
|
||||
it('existing token deep as fallback', function () {
|
||||
const assets = { translations: { bar: '' }, fallback: { bar: { baz: { foo: 'here' } } } };
|
||||
const out = translations.translate('Foo {{ bar.baz.foo }}', assets);
|
||||
expect(out).to.contain('here');
|
||||
assert.ok(out.includes('here'));
|
||||
});
|
||||
|
||||
it('with whitespace tokens', function () {
|
||||
@@ -57,11 +56,11 @@ describe('translation', function () {
|
||||
const input = 'Hello {{ something.missing.there}} and some more {{here}} and {{ there }} with odd spacing {{foo }} lots of{{ bar }}';
|
||||
|
||||
const out = translations.translate(input, assets);
|
||||
expect(out).to.contain('1');
|
||||
expect(out).to.contain('2');
|
||||
expect(out).to.contain('3');
|
||||
expect(out).to.contain('4');
|
||||
expect(out).to.contain('5');
|
||||
assert.ok(out.includes('1'));
|
||||
assert.ok(out.includes('2'));
|
||||
assert.ok(out.includes('3'));
|
||||
assert.ok(out.includes('4'));
|
||||
assert.ok(out.includes('5'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+27
-27
@@ -1,49 +1,49 @@
|
||||
/* global it, describe */
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import _ from '../underscore.js';
|
||||
|
||||
describe('Underscore', function () {
|
||||
it('pick', function () {
|
||||
expect(_.pick({ x: 1, y: 2 }, ['x'])).to.eql({x: 1});
|
||||
expect(_.pick({ x: 1, y: 2 }, ['x', 'y', 'z'])).to.eql({x: 1, y:2});
|
||||
expect(_.pick({ x: 1, y: 2 }, ['z'])).to.eql({});
|
||||
expect(_.pick({ x: 1, y: 2 }, [])).to.eql({});
|
||||
assert.deepEqual(_.pick({ x: 1, y: 2 }, ['x']), {x: 1});
|
||||
assert.deepEqual(_.pick({ x: 1, y: 2 }, ['x', 'y', 'z']), {x: 1, y:2});
|
||||
assert.deepEqual(_.pick({ x: 1, y: 2 }, ['z']), {});
|
||||
assert.deepEqual(_.pick({ x: 1, y: 2 }, []), {});
|
||||
});
|
||||
|
||||
it('omit', function () {
|
||||
expect(_.omit({ x: 1, y: 2 }, ['x'])).to.eql({ y: 2 });
|
||||
expect(_.omit({ x: 1, y: 2 }, ['x', 'y', 'z'])).to.eql({});
|
||||
expect(_.omit({ x: 1, y: 2 }, ['z'])).to.eql({ x: 1, y: 2 });
|
||||
expect(_.omit({ x: 1, y: 2 }, [])).to.eql({ x: 1, y: 2 });
|
||||
assert.deepEqual(_.omit({ x: 1, y: 2 }, ['x']), { y: 2 });
|
||||
assert.deepEqual(_.omit({ x: 1, y: 2 }, ['x', 'y', 'z']), {});
|
||||
assert.deepEqual(_.omit({ x: 1, y: 2 }, ['z']), { x: 1, y: 2 });
|
||||
assert.deepEqual(_.omit({ x: 1, y: 2 }, []), { x: 1, y: 2 });
|
||||
});
|
||||
|
||||
it('intersection', function () {
|
||||
expect(_.intersection([], [2,3])).to.eql([]);
|
||||
expect(_.intersection([1,2], [2,3])).to.eql([2]);
|
||||
expect(_.intersection([1,2], [3])).to.eql([]);
|
||||
expect(_.intersection([1,2], [1,2])).to.eql([1,2]);
|
||||
assert.deepEqual(_.intersection([], [2,3]), []);
|
||||
assert.deepEqual(_.intersection([1,2], [2,3]), [2]);
|
||||
assert.deepEqual(_.intersection([1,2], [3]), []);
|
||||
assert.deepEqual(_.intersection([1,2], [1,2]), [1,2]);
|
||||
});
|
||||
|
||||
it('isEqual', function () {
|
||||
expect(_.isEqual(null, null)).to.be(true);
|
||||
assert.equal(_.isEqual(null, null), true);
|
||||
|
||||
expect(_.isEqual(1, 1)).to.be(true);
|
||||
expect(_.isEqual(1, 2)).to.be(false);
|
||||
assert.equal(_.isEqual(1, 1), true);
|
||||
assert.equal(_.isEqual(1, 2), false);
|
||||
|
||||
expect(_.isEqual([], [])).to.be(true);
|
||||
expect(_.isEqual([2,3,4], [3,4,2])).to.be(false);
|
||||
assert.equal(_.isEqual([], []), true);
|
||||
assert.equal(_.isEqual([2,3,4], [3,4,2]), false);
|
||||
|
||||
expect(_.isEqual({x:1}, {y:2})).to.be(false);
|
||||
expect(_.isEqual({x:1}, {x:1})).to.be(true);
|
||||
expect(_.isEqual({x:1,z:2}, {z:1,x:1})).to.be(false);
|
||||
expect(_.isEqual({x:1,y:3,z:2}, {y:3,z:2,x:1})).to.be(true);
|
||||
assert.equal(_.isEqual({x:1}, {y:2}), false);
|
||||
assert.equal(_.isEqual({x:1}, {x:1}), true);
|
||||
assert.equal(_.isEqual({x:1,z:2}, {z:1,x:1}), false);
|
||||
assert.equal(_.isEqual({x:1,y:3,z:2}, {y:3,z:2,x:1}), true);
|
||||
});
|
||||
|
||||
it('difference', function () {
|
||||
expect(_.difference([1,2], [2,3])).to.eql([1]);
|
||||
expect(_.difference([1,2], [3])).to.eql([1,2]);
|
||||
expect(_.difference([1,2], [1,2])).to.eql([]);
|
||||
expect(_.difference([], [1,2])).to.eql([]);
|
||||
assert.deepEqual(_.difference([1,2], [2,3]), [1]);
|
||||
assert.deepEqual(_.difference([1,2], [3]), [1,2]);
|
||||
assert.deepEqual(_.difference([1,2], [1,2]), []);
|
||||
assert.deepEqual(_.difference([], [1,2]), []);
|
||||
});
|
||||
});
|
||||
|
||||
+23
-26
@@ -1,19 +1,16 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import apps from '../apps.js';
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import constants from '../constants.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import nock from 'nock';
|
||||
import paths from '../paths.js';
|
||||
import safe from 'safetydance';
|
||||
import semver from 'semver';
|
||||
import updater from '../updater.js';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
const UPDATE_VERSION = semver.inc(constants.VERSION, 'major');
|
||||
|
||||
@@ -26,12 +23,12 @@ describe('updater', function () {
|
||||
|
||||
it('can get default autoupdate_pattern', async function () {
|
||||
const pattern = await updater.getAutoupdatePattern();
|
||||
expect(pattern).to.be('00 00 1,3,5,23 * * *');
|
||||
assert.equal(pattern, '00 00 1,3,5,23 * * *');
|
||||
});
|
||||
|
||||
it('cannot set invalid autoupdate_pattern', async function () {
|
||||
const [error] = await safe(updater.setAutoupdatePattern('02 * 1 *'));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can set default autoupdate_pattern', async function () {
|
||||
@@ -61,8 +58,8 @@ describe('updater', function () {
|
||||
|
||||
await updater.checkBoxUpdate({ stableOnly: false });
|
||||
const boxUpdateInfo = await updater.getBoxUpdate();
|
||||
expect(boxUpdateInfo).to.be(null);
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
assert.equal(boxUpdateInfo, null);
|
||||
assert.ok(scope.isDone());
|
||||
});
|
||||
|
||||
it('new version', async function () {
|
||||
@@ -76,10 +73,10 @@ describe('updater', function () {
|
||||
await updater.checkBoxUpdate({ stableOnly: false });
|
||||
const boxUpdateInfo = await updater.getBoxUpdate();
|
||||
|
||||
expect(boxUpdateInfo).to.be.ok();
|
||||
expect(boxUpdateInfo.version).to.be(UPDATE_VERSION);
|
||||
expect(boxUpdateInfo.sourceTarballUrl).to.be('box.tar.gz');
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
assert.ok(boxUpdateInfo);
|
||||
assert.equal(boxUpdateInfo.version, UPDATE_VERSION);
|
||||
assert.equal(boxUpdateInfo.sourceTarballUrl, 'box.tar.gz');
|
||||
assert.ok(scope.isDone());
|
||||
});
|
||||
|
||||
it('bad response offers whatever was last valid', async function () {
|
||||
@@ -93,9 +90,9 @@ describe('updater', function () {
|
||||
await safe(updater.checkBoxUpdate({ stableOnly: false })); // ignore error
|
||||
const boxUpdateInfo = await updater.getBoxUpdate();
|
||||
|
||||
expect(boxUpdateInfo.version).to.be(UPDATE_VERSION);
|
||||
expect(boxUpdateInfo.sourceTarballUrl).to.be('box.tar.gz');
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
assert.equal(boxUpdateInfo.version, UPDATE_VERSION);
|
||||
assert.equal(boxUpdateInfo.sourceTarballUrl, 'box.tar.gz');
|
||||
assert.ok(scope.isDone());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -113,11 +110,11 @@ describe('updater', function () {
|
||||
.reply(204, { } );
|
||||
|
||||
const appUpdateInfo = await updater.checkAppUpdate(app, { stableOnly: false });
|
||||
expect(appUpdateInfo).to.eql(null);
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
assert.deepEqual(appUpdateInfo, null);
|
||||
assert.ok(scope.isDone());
|
||||
|
||||
const tmp = await apps.get(app.id);
|
||||
expect(tmp.updateInfo).to.be(null);
|
||||
assert.equal(tmp.updateInfo, null);
|
||||
});
|
||||
|
||||
it('bad response', async function () {
|
||||
@@ -129,8 +126,8 @@ describe('updater', function () {
|
||||
.reply(500, { update: { manifest: { version: '1.0.0', changelog: '* some changes' } } } );
|
||||
|
||||
const [error] = await safe(updater.checkAppUpdate(app, { stableOnly: false }));
|
||||
expect(error).to.be.ok();
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
assert.ok(error);
|
||||
assert.ok(scope.isDone());
|
||||
});
|
||||
|
||||
it('offers new version', async function () {
|
||||
@@ -149,11 +146,11 @@ describe('updater', function () {
|
||||
};
|
||||
|
||||
const appUpdateInfo = await updater.checkAppUpdate(app, { stableOnly: false });
|
||||
expect(appUpdateInfo.manifest).to.eql(expectedUpdateInfo.manifest);
|
||||
expect(scope.isDone()).to.be.ok();
|
||||
assert.deepEqual(appUpdateInfo.manifest, expectedUpdateInfo.manifest);
|
||||
assert.ok(scope.isDone());
|
||||
|
||||
const tmp = await apps.get(app.id);
|
||||
expect(tmp.updateInfo).to.eql(expectedUpdateInfo);
|
||||
assert.deepEqual(tmp.updateInfo, expectedUpdateInfo);
|
||||
});
|
||||
|
||||
it('does not offer old version', async function () {
|
||||
@@ -167,10 +164,10 @@ describe('updater', function () {
|
||||
};
|
||||
|
||||
const [error] = await safe(updater.checkAppUpdate(app, { stableOnly: false }));
|
||||
expect(error).to.be.ok();
|
||||
assert.ok(error);
|
||||
|
||||
const tmp = await apps.get(app.id);
|
||||
expect(tmp.updateInfo).to.eql(expectedUpdateInfo);
|
||||
assert.deepEqual(tmp.updateInfo, expectedUpdateInfo);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import oidcClients from '../oidcclients.js';
|
||||
import tokens from '../tokens.js';
|
||||
import userDirectory from '../user-directory.js';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('User Directory', function () {
|
||||
const { setup, cleanup, admin, auditSource } = common;
|
||||
@@ -19,18 +16,18 @@ describe('User Directory', function () {
|
||||
describe('profile config', function () {
|
||||
it('can get default profile config', async function () {
|
||||
const profileConfig = await userDirectory.getProfileConfig();
|
||||
expect(profileConfig.lockUserProfiles).to.be(false);
|
||||
expect(profileConfig.mandatory2FA).to.be(false);
|
||||
assert.equal(profileConfig.lockUserProfiles, false);
|
||||
assert.equal(profileConfig.mandatory2FA, false);
|
||||
});
|
||||
|
||||
it('can set default profile config', async function () {
|
||||
await tokens.add({ name: 'token1', identifier: admin.id, clientId: oidcClients.ID_WEBADMIN, expires: Number.MAX_SAFE_INTEGER, lastUsedTime: null, allowedIpRanges: '' });
|
||||
let result = await tokens.listByUserId(admin.id);
|
||||
expect(result.length).to.be(1); // just confirm the token was really added!
|
||||
assert.equal(result.length, 1); // just confirm the token was really added!
|
||||
|
||||
await userDirectory.setProfileConfig({ mandatory2FA: true, lockUserProfiles: true }, { persistUserIdSessions: 'random' }, auditSource);
|
||||
result = await tokens.listByUserId(admin.id);
|
||||
expect(result.length).to.be(0); // should have been removed by mandatory 2fa setting change
|
||||
assert.equal(result.length, 0); // should have been removed by mandatory 2fa setting change
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+106
-109
@@ -1,16 +1,13 @@
|
||||
/* global it:false */
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import safe from 'safetydance';
|
||||
import speakeasy from 'speakeasy';
|
||||
import users from '../users.js';
|
||||
import _ from '../underscore.js';
|
||||
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('User', function () {
|
||||
const { domainSetup, cleanup, admin, user, auditSource, checkMails, clearMailQueue } = common;
|
||||
@@ -32,61 +29,61 @@ describe('User', function () {
|
||||
after(cleanup);
|
||||
|
||||
function checkUser(a, b) {
|
||||
expect(a.creationTime).to.be.a(Date);
|
||||
expect(a.resetTokenCreationTime).to.be.a(Date);
|
||||
assert.ok((a.creationTime) instanceof (Date));
|
||||
assert.ok((a.resetTokenCreationTime) instanceof (Date));
|
||||
|
||||
const fields = [ 'id', 'username', 'email', 'fallbackEmail', 'role', 'displayName', 'source', 'permissions', 'active' ];
|
||||
|
||||
expect(_.pick(a, fields)).to.be.eql(_.pick(b, fields));
|
||||
assert.deepEqual(_.pick(a, fields), _.pick(b, fields));
|
||||
}
|
||||
|
||||
describe('add', function () {
|
||||
it('fails due to short password', async function () {
|
||||
const testUser = Object.assign({}, admin, { password: 'Fo$%23' });
|
||||
const [error] = await safe(users.add(testUser.email, testUser, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('fails due to reserved username', async function () {
|
||||
const testUser = Object.assign({}, admin, { username: 'admin' });
|
||||
const [error] = await safe(users.add(testUser.email, testUser, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('fails due to invalid username', async function () {
|
||||
const testUser = Object.assign({}, admin, { username: 'moo+daemon' });
|
||||
const [error] = await safe(users.add(testUser.email, testUser, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('fails due to empty username', async function () {
|
||||
const testUser = Object.assign({}, admin, { username: '' });
|
||||
const [error] = await safe(users.add(testUser.email, testUser, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('fails due to long username', async function () {
|
||||
const testUser = Object.assign({}, admin, { username: new Array(257).fill('Z').join('') });
|
||||
const [error] = await safe(users.add(testUser.email, testUser, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('fails due to reserved app pattern', async function () {
|
||||
const testUser = Object.assign({}, admin, { username: 'maybe.app' });
|
||||
const [error] = await safe(users.add(testUser.email, testUser, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('fails because password is empty', async function () {
|
||||
const testUser = Object.assign({}, admin, { password: '' });
|
||||
const [error] = await safe(users.add(testUser.email, testUser, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('fails because fallbackEmail is not an email', async function () {
|
||||
const testUser = Object.assign({}, admin, { fallbackEmail: 'notanemail' });
|
||||
const [error] = await safe(users.add(testUser.email, testUser, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can add user', async function () {
|
||||
@@ -96,14 +93,14 @@ describe('User', function () {
|
||||
|
||||
it('cannot add user with same email again', async function () {
|
||||
const [error] = await safe(users.add(admin.email, admin, auditSource));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
expect(error.message).to.equal('email already exists');
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.message, 'email already exists');
|
||||
});
|
||||
|
||||
it('cannot add user with same username again', async function () {
|
||||
const [error] = await safe(users.add('somethingelse@not.taken', admin, auditSource));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
expect(error.message).to.equal('username already exists');
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.message, 'username already exists');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -112,12 +109,12 @@ describe('User', function () {
|
||||
|
||||
it('cannot get by bad user id', async function () {
|
||||
const result = await users.get('random');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('fails because there is no owner', async function () {
|
||||
const owner = await users.getOwner();
|
||||
expect(owner).to.be(null);
|
||||
assert.equal(owner, null);
|
||||
});
|
||||
|
||||
it('getOwner succeeds', async function () {
|
||||
@@ -151,25 +148,25 @@ describe('User', function () {
|
||||
|
||||
it('getSuperadmins succeeds', async function () {
|
||||
const results = await users.getSuperadmins();
|
||||
expect(results.length).to.be(1);
|
||||
assert.equal(results.length, 1);
|
||||
checkUser(results[0], admin);
|
||||
});
|
||||
|
||||
it('getAdmins succeeds', async function () {
|
||||
const results = await users.getAdmins();
|
||||
expect(results.length).to.be(2);
|
||||
assert.equal(results.length, 2);
|
||||
checkUser(results[0], admin); // owner is always the first
|
||||
checkUser(results[1], user);
|
||||
});
|
||||
|
||||
it('getByResetToken fails for empty resetToken', async function () {
|
||||
const [error] = await safe(users.getByResetToken(''));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('getByResetToken fails for bad resetToken', async function () {
|
||||
const result = await users.getByResetToken(new Array(64).fill('Z').join(''));
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('can get by resetToken', async function () {
|
||||
@@ -181,24 +178,24 @@ describe('User', function () {
|
||||
|
||||
it('can list', async function () {
|
||||
const results = await users.list();
|
||||
expect(results.length).to.be(2);
|
||||
assert.equal(results.length, 2);
|
||||
checkUser(results[0], admin);
|
||||
checkUser(results[1], user);
|
||||
});
|
||||
|
||||
it('can listPaged', async function () {
|
||||
let results = await users.listPaged(null, null, 1, 1);
|
||||
expect(results.length).to.be(1);
|
||||
assert.equal(results.length, 1);
|
||||
checkUser(results[0], admin);
|
||||
|
||||
results = await users.listPaged(null, null, 2, 1);
|
||||
expect(results.length).to.be(1);
|
||||
assert.equal(results.length, 1);
|
||||
checkUser(results[0], user);
|
||||
});
|
||||
|
||||
it('can listPaged (search)', async function () {
|
||||
const results = await users.listPaged(admin.email.slice(0, 8), null, 1, 1);
|
||||
expect(results.length).to.be(1);
|
||||
assert.equal(results.length, 1);
|
||||
checkUser(results[0], admin);
|
||||
});
|
||||
});
|
||||
@@ -209,12 +206,12 @@ describe('User', function () {
|
||||
it('fails due to unknown userid', async function () {
|
||||
const unknownUser = Object.assign({}, admin, { id: 'random' });
|
||||
const [error] = await safe(users.update(unknownUser, { displayName: 'full name' }, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('fails due to invalid email', async function () {
|
||||
const [error] = await safe(users.update(admin, { email: 'brokenemailaddress' }, auditSource));
|
||||
expect(error.reason).to.equal(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot update the user with already existing email', async function () {
|
||||
@@ -222,21 +219,21 @@ describe('User', function () {
|
||||
user.id = result;
|
||||
|
||||
const [error] = await safe(users.update(admin, { email: user.email }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
expect(error.message).to.equal('email already exists');
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.message, 'email already exists');
|
||||
});
|
||||
|
||||
it('cannot update username', async function () {
|
||||
const [error] = await safe(users.update(admin, { username: user.username }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.CONFLICT);
|
||||
expect(error.message).to.equal('Username cannot be changed');
|
||||
assert.equal(error.reason, BoxError.CONFLICT);
|
||||
assert.equal(error.message, 'Username cannot be changed');
|
||||
});
|
||||
|
||||
it('can update the user', async function () {
|
||||
await users.update(admin, { email: 'some@thing.com', displayName: 'Heiter' }, auditSource);
|
||||
const updatedUser = await users.get(admin.id);
|
||||
expect(updatedUser.email).to.equal('some@thing.com');
|
||||
expect(updatedUser.displayName).to.equal('Heiter');
|
||||
assert.equal(updatedUser.email, 'some@thing.com');
|
||||
assert.equal(updatedUser.displayName, 'Heiter');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -245,52 +242,52 @@ describe('User', function () {
|
||||
|
||||
it('fails due to non existing user', async function () {
|
||||
const [error] = await safe(users.verifyWithId('somerandomid', 'somepassword', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('fails due to empty password', async function () {
|
||||
const [error] = await safe(users.verifyWithId(admin.id, '', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('fails due to wrong password', async function () {
|
||||
const [error] = await safe(users.verifyWithId(admin.id, admin.password+'x', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('succeeds', async function () {
|
||||
const result = await users.verifyWithId(admin.id, admin.password, users.AP_WEBADMIN, {});
|
||||
expect(result).to.be.ok();
|
||||
expect(result.appPassword).to.not.be.ok();
|
||||
expect(result.ghost).to.not.be.ok();
|
||||
assert.ok(result);
|
||||
assert.ok(!(result.appPassword));
|
||||
assert.ok(!(result.ghost));
|
||||
});
|
||||
|
||||
it('fails for ghost if not enabled', async function () {
|
||||
const [error] = await safe(users.verifyWithId(admin.id, 'foobar', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('fails for ghost with wrong password', async function () {
|
||||
await users.setGhost(admin, 'testpassword', 0);
|
||||
|
||||
const [error] = await safe(users.verifyWithId(admin.id, 'foobar', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('succeeds for ghost', async function () {
|
||||
await users.setGhost(admin, 'testpassword', 0);
|
||||
|
||||
const result = await users.verifyWithId(admin.id, 'testpassword', users.AP_WEBADMIN, {});
|
||||
expect(result.id).to.equal(admin.id);
|
||||
expect(result.ghost).to.be(true);
|
||||
assert.equal(result.id, admin.id);
|
||||
assert.equal(result.ghost, true);
|
||||
});
|
||||
|
||||
it('succeeds for normal user password when ghost file exists', async function () {
|
||||
await users.setGhost(admin, 'testpassword', 0);
|
||||
|
||||
const result = await users.verifyWithId(admin.id, admin.password, users.AP_WEBADMIN, {});
|
||||
expect(result.id).to.equal(admin.id);
|
||||
expect(result.ghost).to.not.be.ok();
|
||||
assert.equal(result.id, admin.id);
|
||||
assert.ok(!(result.ghost));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -299,42 +296,42 @@ describe('User', function () {
|
||||
|
||||
it('fails due to non existing username', async function () {
|
||||
const [error] = await safe(users.verifyWithUsername('someusername', 'somepass', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('fails due to empty password', async function () {
|
||||
const [error] = await safe(users.verifyWithUsername(admin.username, '', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('fails due to wrong password', async function () {
|
||||
const [error] = await safe(users.verifyWithUsername(admin.username, 'somepass', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('succeeds', async function () {
|
||||
const result = await users.verifyWithUsername(admin.username, admin.password, users.AP_WEBADMIN, {});
|
||||
expect(result.id).to.equal(admin.id);
|
||||
assert.equal(result.id, admin.id);
|
||||
});
|
||||
|
||||
it('succeeds for different username case', async function () {
|
||||
const result = await users.verifyWithUsername(admin.username.toUpperCase(), admin.password, users.AP_WEBADMIN, {});
|
||||
expect(result.id).to.equal(admin.id);
|
||||
assert.equal(result.id, admin.id);
|
||||
});
|
||||
|
||||
it('fails for ghost with wrong password', async function () {
|
||||
await users.setGhost(admin, 'testpassword', 0);
|
||||
|
||||
const [error] = await safe(users.verifyWithUsername(admin.username, 'foobar', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('succeeds for ghost', async function () {
|
||||
await users.setGhost(admin, 'testpassword', 0);
|
||||
|
||||
const result = await users.verifyWithUsername(admin.username, 'testpassword', users.AP_WEBADMIN, {});
|
||||
expect(result.id).to.equal(admin.id);
|
||||
expect(result.ghost).to.be(true);
|
||||
assert.equal(result.id, admin.id);
|
||||
assert.equal(result.ghost, true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -343,42 +340,42 @@ describe('User', function () {
|
||||
|
||||
it('fails due to non existing user', async function () {
|
||||
const [error] = await safe(users.verifyWithEmail('bad@email.com', admin.password, users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('fails due to empty password', async function () {
|
||||
const [error] = await safe(users.verifyWithEmail(admin.email, '', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('fails due to wrong password', async function () {
|
||||
const [error] = await safe(users.verifyWithEmail(admin.email, 'badpassword', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('succeeds', async function () {
|
||||
const result = await users.verifyWithEmail(admin.email, admin.password, users.AP_WEBADMIN, {});
|
||||
expect(result.id).to.be(admin.id);
|
||||
assert.equal(result.id, admin.id);
|
||||
});
|
||||
|
||||
it('succeeds for different email case', async function () {
|
||||
const result = await users.verifyWithEmail(admin.email.toUpperCase(), admin.password, users.AP_WEBADMIN, {});
|
||||
expect(result.id).to.be(admin.id);
|
||||
assert.equal(result.id, admin.id);
|
||||
});
|
||||
|
||||
it('fails for ghost with wrong password', async function () {
|
||||
await users.setGhost(admin, 'testpassword', 0);
|
||||
|
||||
const [error] = await safe(users.verifyWithEmail(admin.email, 'foobar', users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('succeeds for ghost', async function () {
|
||||
await users.setGhost(admin, 'testpassword', 0);
|
||||
|
||||
const result = await users.verifyWithEmail(admin.email, 'testpassword', users.AP_WEBADMIN, {});
|
||||
expect(result.id).to.equal(admin.id);
|
||||
expect(result.ghost).to.equal(true);
|
||||
assert.equal(result.id, admin.id);
|
||||
assert.equal(result.ghost, true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -389,14 +386,14 @@ describe('User', function () {
|
||||
|
||||
it('create secret', async function () {
|
||||
twofa = await users.setTwoFactorAuthenticationSecret(admin, auditSource);
|
||||
expect(twofa.secret).to.be.a('string');
|
||||
expect(twofa.qrcode).to.be.a('string');
|
||||
assert.equal(typeof twofa.secret, 'string');
|
||||
assert.equal(typeof twofa.qrcode, 'string');
|
||||
});
|
||||
|
||||
it('can create secret again', async function () {
|
||||
twofa = await users.setTwoFactorAuthenticationSecret(admin, auditSource);
|
||||
expect(twofa.secret).to.be.a('string');
|
||||
expect(twofa.qrcode).to.be.a('string');
|
||||
assert.equal(typeof twofa.secret, 'string');
|
||||
assert.equal(typeof twofa.qrcode, 'string');
|
||||
admin.twoFactorAuthenticationSecret = twofa.secret; // update user object
|
||||
});
|
||||
|
||||
@@ -405,41 +402,41 @@ describe('User', function () {
|
||||
await users.enableTwoFactorAuthentication(admin, totpToken, auditSource);
|
||||
|
||||
const u = await users.get(admin.id);
|
||||
expect(u.twoFactorAuthenticationEnabled).to.be(true);
|
||||
assert.equal(u.twoFactorAuthenticationEnabled, true);
|
||||
admin.twoFactorAuthenticationEnabled = true; // update user object
|
||||
});
|
||||
|
||||
it('cannot re-create secret', async function () {
|
||||
const [error] = await safe(users.setTwoFactorAuthenticationSecret(admin, auditSource));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('cannot re-enable 2fa', async function () {
|
||||
const totpToken = speakeasy.totp({ secret: twofa.secret, encoding: 'base32' });
|
||||
const [error] = await safe(users.enableTwoFactorAuthentication(admin, totpToken, auditSource));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('verify fails without 2fa', async function () {
|
||||
const [error] = await safe(users.verifyWithUsername(admin.username, admin.password, users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS);
|
||||
expect(error.message).to.be('A totpToken must be provided');
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.message, 'A totpToken must be provided');
|
||||
});
|
||||
|
||||
it('verify succeeds with relaxed 2fa', async function () {
|
||||
const verifiedUser = await users.verifyWithUsername(admin.username, admin.password, users.AP_WEBADMIN, { skipTotpCheck: true });
|
||||
expect(verifiedUser.id).to.be(admin.id);
|
||||
assert.equal(verifiedUser.id, admin.id);
|
||||
});
|
||||
|
||||
it('verify succeeds with relaxed 2fa but incorrect totp (totp is ignored)', async function () {
|
||||
const verifiedUser = await users.verifyWithUsername(admin.username, admin.password, users.AP_WEBADMIN, { totpToken: 'schlecht', skipTotpCheck: true });
|
||||
expect(verifiedUser.id).to.be(admin.id);
|
||||
assert.equal(verifiedUser.id, admin.id);
|
||||
});
|
||||
|
||||
it('verify succeeds with valid 2fa', async function () {
|
||||
const totpToken = speakeasy.totp({ secret: twofa.secret, encoding: 'base32' });
|
||||
const verifiedUser = await users.verifyWithUsername(admin.username, admin.password, users.AP_WEBADMIN, { totpToken });
|
||||
expect(verifiedUser.id).to.be(admin.id);
|
||||
assert.equal(verifiedUser.id, admin.id);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -449,7 +446,7 @@ describe('User', function () {
|
||||
it('verify fails for inactive user', async function () {
|
||||
await users.update(admin, { active: false }, auditSource);
|
||||
const [error] = await safe(users.verifyWithId(admin.id, admin.password, users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('verify succeeds for inactive user', async function () {
|
||||
@@ -463,16 +460,16 @@ describe('User', function () {
|
||||
|
||||
it('fails due to non existing user', async function () {
|
||||
const result = await users.get('randomid');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('succeeds', async function () {
|
||||
const result = await users.get(admin.id);
|
||||
expect(result.id).to.equal(admin.id);
|
||||
expect(result.email).to.equal(admin.email.toLowerCase());
|
||||
expect(result.fallbackEmail).to.equal(admin.fallbackEmail.toLowerCase());
|
||||
expect(result.username).to.equal(admin.username.toLowerCase());
|
||||
expect(result.displayName).to.equal(admin.displayName);
|
||||
assert.equal(result.id, admin.id);
|
||||
assert.equal(result.email, admin.email.toLowerCase());
|
||||
assert.equal(result.fallbackEmail, admin.fallbackEmail.toLowerCase());
|
||||
assert.equal(result.username, admin.username.toLowerCase());
|
||||
assert.equal(result.displayName, admin.displayName);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -481,14 +478,14 @@ describe('User', function () {
|
||||
|
||||
it('succeeds with no users', async function () {
|
||||
const activated = await users.isActivated();
|
||||
expect(activated).to.be(false);
|
||||
assert.equal(activated, false);
|
||||
});
|
||||
|
||||
it('create admin', createOwner);
|
||||
|
||||
it('succeeds with users', async function () {
|
||||
const activated = await users.isActivated();
|
||||
expect(activated).to.be(true);
|
||||
assert.equal(activated, true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -498,17 +495,17 @@ describe('User', function () {
|
||||
it('fails due to unknown user', async function () {
|
||||
const unknownUser = Object.assign({}, admin, { id: 'doesnotexist' });
|
||||
const [error] = await safe(users.setPassword(unknownUser, 'newpassword', auditSource));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('fails due to empty password', async function () {
|
||||
const [error] = await safe(users.setPassword(admin, '', auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('fails due to invalid password', async function () {
|
||||
const [error] = await safe(users.setPassword(admin, 'foobar', auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('succeeds', async function () {
|
||||
@@ -517,7 +514,7 @@ describe('User', function () {
|
||||
|
||||
it('actually changed the password (unable to login with old pasword)', async function () {
|
||||
const [error] = await safe(users.verifyWithId(admin.id, admin.password, users.AP_WEBADMIN, {}));
|
||||
expect(error.reason).to.equal(BoxError.INVALID_CREDENTIALS);
|
||||
assert.equal(error.reason, BoxError.INVALID_CREDENTIALS);
|
||||
});
|
||||
|
||||
it('actually changed the password (login with new password)', async function () {
|
||||
@@ -530,12 +527,12 @@ describe('User', function () {
|
||||
|
||||
it('fails due to unknown email', async function () {
|
||||
const [error] = await safe(users.sendPasswordResetByIdentifier('unknown@mail.com', auditSource));
|
||||
expect(error.reason).to.eql(BoxError.NOT_FOUND);
|
||||
assert.deepEqual(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('fails due to unknown username', async function () {
|
||||
const [error] = await safe(users.sendPasswordResetByIdentifier('unknown', auditSource));
|
||||
expect(error.reason).to.eql(BoxError.NOT_FOUND);
|
||||
assert.deepEqual(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('succeeds with email', async function () {
|
||||
@@ -556,24 +553,24 @@ describe('User', function () {
|
||||
|
||||
it('default language is empty', async function () {
|
||||
const result = await users.get(admin.id);
|
||||
expect(result.language).to.be('');
|
||||
assert.equal(result.language, '');
|
||||
});
|
||||
|
||||
it('cannot set bad language', async function () {
|
||||
const [error] = await safe(users.update(admin, { language: 'ta '}, auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can set language', async function () {
|
||||
await users.update(admin, { language: 'en' }, auditSource);
|
||||
const result = await users.get(admin.id);
|
||||
expect(result.language).to.be('en');
|
||||
assert.equal(result.language, 'en');
|
||||
});
|
||||
|
||||
it('can reset language', async function () {
|
||||
await users.update(admin, { language: '' }, auditSource);
|
||||
const result = await users.get(admin.id);
|
||||
expect(result.language).to.be('');
|
||||
assert.equal(result.language, '');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -582,24 +579,24 @@ describe('User', function () {
|
||||
|
||||
it('default avatar is empty', async function () {
|
||||
const result = await users.get(admin.id);
|
||||
expect(result.avatar).to.be(undefined); // should not be in 'get'
|
||||
assert.equal(result.avatar, undefined); // should not be in 'get'
|
||||
|
||||
const result2 = await users.getAvatar(result);
|
||||
expect(result2).to.be(null);
|
||||
assert.equal(result2, null);
|
||||
});
|
||||
|
||||
it('set avatar', async function () {
|
||||
await users.setAvatar(admin, Buffer.from('ABC'));
|
||||
|
||||
const avatar = await users.getAvatar(admin);
|
||||
expect(avatar).to.be.eql(Buffer.from('ABC'));
|
||||
assert.deepEqual(avatar, Buffer.from('ABC'));
|
||||
});
|
||||
|
||||
it('reset avatar', async function () {
|
||||
await users.setAvatar(admin, null);
|
||||
|
||||
const avatar = await users.getAvatar(admin);
|
||||
expect(avatar).to.be(null);
|
||||
assert.equal(avatar, null);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -610,7 +607,7 @@ describe('User', function () {
|
||||
|
||||
it('get link fails as alreayd been used', async function () {
|
||||
const [error] = await safe(users.getInviteLink(admin, auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_STATE);
|
||||
assert.equal(error.reason, BoxError.BAD_STATE);
|
||||
});
|
||||
|
||||
it('can get link', async function () {
|
||||
@@ -618,25 +615,25 @@ describe('User', function () {
|
||||
invitedUser = await users.get(userId);
|
||||
|
||||
const inviteLink = await users.getInviteLink(invitedUser, auditSource);
|
||||
expect(inviteLink).to.be.a('string');
|
||||
expect(inviteLink).to.contain(invitedUser.inviteToken);
|
||||
assert.equal(typeof inviteLink, 'string');
|
||||
assert.ok(inviteLink.includes(invitedUser.inviteToken));
|
||||
});
|
||||
|
||||
it('cannot send mail for already active user', async function () {
|
||||
const [error] = await safe(users.sendInviteEmail(admin, 'admin@mail.com', auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_STATE);
|
||||
assert.equal(error.reason, BoxError.BAD_STATE);
|
||||
});
|
||||
|
||||
it('cannot send mail with empty receipient', async function () {
|
||||
const [error] = await safe(users.sendInviteEmail(invitedUser, '', auditSource));
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('can send mail', async function () {
|
||||
await clearMailQueue();
|
||||
await users.sendInviteEmail(invitedUser, 'custom@mail.com', auditSource);
|
||||
const emails = await checkMails(1);
|
||||
expect(emails[0].to).to.equal('custom@mail.com');
|
||||
assert.equal(emails[0].to, 'custom@mail.com');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -646,7 +643,7 @@ describe('User', function () {
|
||||
it('fails for unknown user', async function () {
|
||||
const unknownUser = Object.assign({}, admin, { id: 'doesnotexist' });
|
||||
const [error] = await safe(users.del(unknownUser, auditSource));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('can remove valid user', async function () {
|
||||
@@ -665,7 +662,7 @@ describe('User', function () {
|
||||
];
|
||||
|
||||
for (const name of names) {
|
||||
expect(users.parseDisplayName(name.in)).to.eql(name.out);
|
||||
assert.deepEqual(users.parseDisplayName(name.in), name.out);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* global it, describe */
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import validator from '../validator.js';
|
||||
|
||||
describe('Validator', function () {
|
||||
@@ -14,7 +14,7 @@ describe('Validator', function () {
|
||||
];
|
||||
|
||||
for (const goodEmail of goodEmails) {
|
||||
it(`isEmail returns false ${goodEmail}`, () => expect(validator.isEmail(goodEmail)).to.be(true));
|
||||
it(`isEmail returns false ${goodEmail}`, () => assert.equal(validator.isEmail(goodEmail), true));
|
||||
}
|
||||
|
||||
const badEmails = [
|
||||
@@ -26,20 +26,20 @@ describe('Validator', function () {
|
||||
];
|
||||
|
||||
for (const badEmail of badEmails) {
|
||||
it(`isEmail returns false ${badEmail}`, () => expect(validator.isEmail(badEmail)).to.be(false));
|
||||
it(`isEmail returns false ${badEmail}`, () => assert.equal(validator.isEmail(badEmail), false));
|
||||
}
|
||||
|
||||
describe('isIsoDate', function () {
|
||||
it('returns true for valid ISO string', function () {
|
||||
expect(validator.isIsoDate('2024-01-15T10:30:00.000Z')).to.be(true);
|
||||
assert.equal(validator.isIsoDate('2024-01-15T10:30:00.000Z'), true);
|
||||
});
|
||||
|
||||
it('returns false for invalid string', function () {
|
||||
expect(validator.isIsoDate('not-a-date')).to.be(false);
|
||||
assert.equal(validator.isIsoDate('not-a-date'), false);
|
||||
});
|
||||
|
||||
it('returns false for empty string', function () {
|
||||
expect(validator.isIsoDate('')).to.be(false);
|
||||
assert.equal(validator.isIsoDate(''), false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+15
-18
@@ -1,16 +1,13 @@
|
||||
import { describe, it, before, after } from 'node:test';
|
||||
/* jslint node:true */
|
||||
|
||||
import BoxError from '../boxerror.js';
|
||||
import common from './common.js';
|
||||
import expect from 'expect.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import paths from '../paths.js';
|
||||
import safe from 'safetydance';
|
||||
import volumes from '../volumes.js';
|
||||
|
||||
/* global it:false */
|
||||
/* global describe:false */
|
||||
/* global before:false */
|
||||
/* global after:false */
|
||||
|
||||
describe('Volumes', function () {
|
||||
const { setup, cleanup, auditSource } = common;
|
||||
@@ -21,53 +18,53 @@ describe('Volumes', function () {
|
||||
it('cannot add bad name', async function () {
|
||||
const [error] = await safe(volumes.add({ name: 'music/is', hostPath: '/tmp/music', mountType: 'filesystem', mountOptions: {} }, auditSource));
|
||||
if (!error) throw new Error('Expecting bad field error');
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
it('cannot add bad path', async function () {
|
||||
const [error] = await safe(volumes.add({ name: 'music', hostPath: '/tmp/music', mountType: 'filesystem', mountOptions: {} }, auditSource));
|
||||
if (!error) throw new Error('Expecting bad field error');
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
|
||||
let volume;
|
||||
it('can add volume', async function () {
|
||||
const id = await volumes.add({ name: 'music', mountType: 'filesystem', mountOptions: { hostPath: '/mnt/cloudron-test-music' } }, auditSource);
|
||||
expect(id).to.be.a('string');
|
||||
assert.equal(typeof id, 'string');
|
||||
volume = { id, name: 'music', hostPath: '/mnt/cloudron-test-music' };
|
||||
});
|
||||
|
||||
it('cannot add duplicate path', async function () {
|
||||
const [error] = await safe(volumes.add({ name: 'music-dup', mountType: 'filesystem', mountOptions: { hostPath: '/mnt/cloudron-test-music' } }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('cannot add duplicate name', async function () {
|
||||
const [error] = await safe(volumes.add({ name: 'music', mountType: 'filesystem', mountOptions: { hostPath: '/mnt/cloudron-test-music2' } }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.ALREADY_EXISTS);
|
||||
assert.equal(error.reason, BoxError.ALREADY_EXISTS);
|
||||
});
|
||||
|
||||
it('can get volume', async function () {
|
||||
const result = await volumes.get(volume.id);
|
||||
expect(result.hostPath).to.be('/mnt/cloudron-test-music');
|
||||
assert.equal(result.hostPath, '/mnt/cloudron-test-music');
|
||||
});
|
||||
|
||||
it('cannot get random volume', async function () {
|
||||
const result = await volumes.get('randomvolume');
|
||||
expect(result).to.be(null);
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
it('can list volumes', async function () {
|
||||
const result = await volumes.list();
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result.length).to.be(1);
|
||||
expect(result[0].id).to.be(volume.id);
|
||||
expect(result[0].hostPath).to.be('/mnt/cloudron-test-music');
|
||||
assert.ok(Array.isArray(result));
|
||||
assert.equal(result.length, 1);
|
||||
assert.equal(result[0].id, volume.id);
|
||||
assert.equal(result[0].hostPath, '/mnt/cloudron-test-music');
|
||||
});
|
||||
|
||||
it('cannot del random volume', async function () {
|
||||
const [error] = await safe(volumes.del({ id: 'randomvolume' }, auditSource));
|
||||
expect(error.reason).to.be(BoxError.NOT_FOUND);
|
||||
assert.equal(error.reason, BoxError.NOT_FOUND);
|
||||
});
|
||||
|
||||
it('can del volume', async function () {
|
||||
@@ -92,7 +89,7 @@ describe('Volumes', function () {
|
||||
for (const p of badPaths) {
|
||||
it(`validateHostPath - ${p}`, function () {
|
||||
const error = volumes._validateHostPath(p);
|
||||
expect(error.reason).to.be(BoxError.BAD_FIELD);
|
||||
assert.equal(error.reason, BoxError.BAD_FIELD);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user