'use strict'; const apps = require('../apps.js'), constants = require('../constants.js'), database = require('../database.js'), domains = require('../domains.js'), expect = require('expect.js'), fs = require('fs'), mailer = require('../mailer.js'), nock = require('nock'), path = require('path'), paths = require('../paths.js'), settings = require('../settings.js'), tasks = require('../tasks.js'), timers = require('timers/promises'), users = require('../users.js'); const manifest = { 'id': 'io.cloudron.test', 'author': 'The Presidents Of the United States Of America', 'title': 'test title', 'description': 'test description', 'tagline': 'test rocks', 'website': 'http://test.cloudron.io', 'contactEmail': 'test@cloudron.io', 'version': '0.1.0', 'manifestVersion': 2, 'dockerImage': 'cloudron/test:25.2.0', 'healthCheckPath': '/', 'httpPort': 7777, 'tcpPorts': { 'ECHO_SERVER_PORT': { 'title': 'Echo Server Port', 'description': 'Echo server', 'containerPort': 7778 } }, 'addons': { 'oauth': { }, 'redis': { }, 'mysql': { }, 'postgresql': { } } }; // copied from the proxy app CloudronManifest.json const proxyAppManifest = { 'id': 'io.cloudron.builtin.appproxy', 'title': 'App Proxy', 'author': 'Cloudron Team', 'version': '1.0.0', 'upstreamVersion': '1.0.0', 'description': 'file://DESCRIPTION.md', 'tagline': 'Proxy an app through Cloudron', 'tags': [ 'proxy', 'external' ], 'healthCheckPath': '/', 'httpPort': 3000, 'minBoxVersion': '7.3.0', 'dockerImage': 'istobeignored', 'manifestVersion': 2, 'multiDomain': true, 'website': 'https://cloudron.io', 'documentationUrl': 'https://docs.cloudron.io/dashboard/#app-proxy', 'forumUrl': 'https://forum.cloudron.io', 'contactEmail': 'support@cloudron.io', 'icon': 'file://logo.png', 'addons': {}, 'mediaLinks': [ 'https://screenshots.cloudron.io/io.cloudron.builtin.appproxy/diagram.png' ], 'changelog': 'file://CHANGELOG.md' }; const domain = { domain: 'example.com', zoneName: 'example.com', provider: 'noop', config: {}, fallbackCertificate: null, tlsConfig: { provider: 'fallback' }, wellKnown: null }; Object.freeze(domain); const auditSource = { ip: '1.2.3.4' }; const admin = { id: null, username: 'testadmin', password: 'secret123', email: 'admin@me.com', fallbackEmail: 'admin@external.com', salt: 'morton', createdAt: 'sometime back', resetToken: '', displayName: 'Administrator', groupIds: [], role: 'owner', source: '', avatar: constants.AVATAR_GRAVATAR, active: true, }; const user = { id: null, username: 'user', password: '123secret', email: 'user@me.com', fallbackEmail: 'user@external.com', role: 'user', salt: 'morton', createdAt: 'sometime back', resetToken: '', groupIds: [], displayName: 'Normal User', source: '', avatar: constants.AVATAR_NONE, active: true, }; const app = { id: 'appid', appStoreId: 'appStoreId', installationState: apps.ISTATE_PENDING_INSTALL, runState: 'running', subdomain: 'applocation', domain: domain.domain, fqdn: domain.domain + '.' + 'applocation', manifest, containerId: 'someid', portBindings: null, accessRestriction: null, memoryLimit: 0, mailboxDomain: domain.domain, secondaryDomains: [], redirectDomains: [], aliasDomains: [] }; Object.freeze(app); const proxyApp = { id: 'proxyapptestid', appStoreId: proxyAppManifest.id, installationState: apps.ISTATE_PENDING_INSTALL, runState: 'running', subdomain: 'proxylocation', upstreamUri: 'http://1.2.3.4:80', domain: domain.domain, fqdn: domain.domain + '.' + 'proxylocation', manifest, containerId: '', portBindings: null, accessRestriction: null, memoryLimit: 0, mailboxDomain: domain.domain, secondaryDomains: [], redirectDomains: [], aliasDomains: [] }; Object.freeze(proxyApp); exports = module.exports = { createTree, domainSetup, databaseSetup, setup, cleanup, checkMails, clearMailQueue, mockApiServerOrigin: 'http://localhost:6060', dashboardDomain: domain.domain, dashboardFqdn: `my.${domain.domain}`, app, proxyApp, admin, auditSource, domain, // the domain object manifest, user, appstoreToken: 'atoken', serverUrl: `http://localhost:${constants.PORT}`, }; function createTree(root, obj) { fs.rmSync(root, { recursive: true, force: true }); fs.mkdirSync(root, { recursive: true }); function createSubTree(tree, curpath) { for (const key in tree) { if (typeof tree[key] === 'string') { if (key.startsWith('link:')) { fs.symlinkSync(tree[key], path.join(curpath, key.slice(5))); } else { fs.writeFileSync(path.join(curpath, key), tree[key], 'utf8'); } } else { fs.mkdirSync(path.join(curpath, key)); createSubTree(tree[key], path.join(curpath, key)); } } } createSubTree(obj, root); } async function databaseSetup() { nock.cleanAll(); await database.initialize(); await database._clear(); await settings._setApiServerOrigin(exports.mockApiServerOrigin); await settings.setDashboardLocation(exports.dashboardDomain, exports.dashboardFqdn); await settings.initCache(); } async function domainSetup() { nock.cleanAll(); await databaseSetup(); await settings.setMailLocation(domain.domain, `${constants.DASHBOARD_SUBDOMAIN}.${domain.domain}`); // default mail location. do this before we add the domain for upserting mail DNS await domains.add(domain.domain, domain, auditSource); } async function setup() { await fs.promises.rm(paths.DISK_USAGE_FILE, { force: true }); await domainSetup(); const ownerId = await users.createOwner(admin.email, admin.username, admin.password, admin.displayName, auditSource); admin.id = ownerId; await apps.add(app.id, app.appStoreId, app.manifest, app.subdomain, app.domain, app.portBindings, app); await settings._set(settings.APPSTORE_API_TOKEN_KEY, exports.appstoreToken); // appstore token const userId = await users.add(user.email, user, auditSource); user.id = userId; await tasks.stopAllTasks(); } async function cleanup() { nock.cleanAll(); mailer._mailQueue = []; await database._clear(); await database.uninitialize(); } function clearMailQueue() { mailer._mailQueue = []; } async function checkMails(number) { await timers.setTimeout(1000); expect(mailer._mailQueue.length).to.equal(number); const emails = mailer._mailQueue; clearMailQueue(); // return for further investigation return emails; }