2026-02-14 09:53:14 +01:00
import apps from '../apps.js' ;
2026-02-14 15:43:24 +01:00
import appstore from '../appstore.js' ;
import backupSites from '../backupsites.js' ;
2026-02-14 09:53:14 +01:00
import constants from '../constants.js' ;
2026-02-14 15:43:24 +01:00
import cron from '../cron.js' ;
import dashboard from '../dashboard.js' ;
import database from '../database.js' ;
import domains from '../domains.js' ;
2026-02-14 09:53:14 +01:00
import expect from 'expect.js' ;
import fs from 'node:fs' ;
import locks from '../locks.js' ;
2026-02-14 15:43:24 +01:00
import mailer from '../mailer.js' ;
import mailServer from '../mailserver.js' ;
2026-02-14 09:53:14 +01:00
import nock from 'nock' ;
import path from 'node:path' ;
2026-02-14 15:43:24 +01:00
import settings from '../settings.js' ;
2026-02-14 09:53:14 +01:00
import tasks from '../tasks.js' ;
import timers from 'timers/promises' ;
2026-02-14 15:43:24 +01:00
import users from '../users.js' ;
2021-06-03 12:20:44 -07:00
2021-08-13 15:49:59 -07:00
const manifest = {
2021-06-03 12:20:44 -07:00
'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' ,
2021-12-06 17:43:50 -08:00
'manifestVersion' : 2 ,
2021-06-03 12:20:44 -07:00
'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' : { }
}
} ;
2022-11-23 14:36:57 +01:00
// copied from the proxy app CloudronManifest.json
const proxyAppManifest = {
2023-05-14 10:53:50 +02:00
'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'
2022-11-23 14:36:57 +01:00
} ;
2021-08-13 10:41:10 -07:00
const domain = {
2021-06-03 12:20:44 -07:00
domain : 'example.com' ,
zoneName : 'example.com' ,
2021-06-03 16:16:04 -07:00
provider : 'noop' ,
config : { } ,
2021-06-03 12:20:44 -07:00
fallbackCertificate : null ,
2021-06-03 16:16:04 -07:00
tlsConfig : { provider : 'fallback' } ,
2021-06-03 12:20:44 -07:00
wellKnown : null
} ;
2021-08-20 09:19:44 -07:00
Object . freeze ( domain ) ;
2021-06-03 12:20:44 -07:00
2021-08-13 10:41:10 -07:00
const auditSource = { ip : '1.2.3.4' } ;
2021-06-03 12:20:44 -07:00
2021-08-13 10:41:10 -07:00
const admin = {
2021-06-28 15:15:28 -07:00
id : null ,
2021-07-20 09:05:21 -07:00
username : 'testadmin' ,
2021-06-03 12:20:44 -07:00
password : 'secret123' ,
email : 'admin@me.com' ,
2021-10-26 22:50:02 +02:00
fallbackEmail : 'admin@external.com' ,
2021-06-03 12:20:44 -07:00
salt : 'morton' ,
createdAt : 'sometime back' ,
resetToken : '' ,
2021-07-20 09:05:21 -07:00
displayName : 'Administrator' ,
2021-07-09 17:09:10 +02:00
groupIds : [ ] ,
2021-06-03 12:20:44 -07:00
role : 'owner' ,
2021-07-09 17:09:10 +02:00
source : '' ,
2025-06-08 12:42:13 +02:00
avatar : null ,
2021-07-19 12:43:30 -07:00
active : true ,
2021-06-03 12:20:44 -07:00
} ;
2021-08-13 10:41:10 -07:00
const user = {
2021-07-20 09:05:21 -07:00
id : null ,
username : 'user' ,
2021-07-07 12:59:17 -07:00
password : '123secret' ,
2021-07-20 09:05:21 -07:00
email : 'user@me.com' ,
2021-10-26 22:50:02 +02:00
fallbackEmail : 'user@external.com' ,
2021-06-28 15:15:28 -07:00
role : 'user' ,
salt : 'morton' ,
createdAt : 'sometime back' ,
2021-07-20 09:05:21 -07:00
resetToken : '' ,
2021-07-09 17:09:10 +02:00
groupIds : [ ] ,
2021-07-20 09:05:21 -07:00
displayName : 'Normal User' ,
2021-06-28 15:15:28 -07:00
source : '' ,
2025-06-08 12:42:13 +02:00
avatar : null ,
2021-07-19 12:43:30 -07:00
active : true ,
2021-06-28 15:15:28 -07:00
} ;
2021-08-13 10:41:10 -07:00
const app = {
2021-06-03 12:20:44 -07:00
id : 'appid' ,
appStoreId : 'appStoreId' ,
installationState : apps . ISTATE _PENDING _INSTALL ,
runState : 'running' ,
2022-01-16 12:32:12 -08:00
subdomain : 'applocation' ,
2021-08-13 10:41:10 -07:00
domain : domain . domain ,
fqdn : domain . domain + '.' + 'applocation' ,
2021-08-13 15:49:59 -07:00
manifest ,
2021-06-03 12:20:44 -07:00
containerId : 'someid' ,
2024-07-16 22:21:36 +02:00
portBindings : { } ,
2021-06-03 12:20:44 -07:00
accessRestriction : null ,
memoryLimit : 0 ,
2021-08-13 10:41:10 -07:00
mailboxDomain : domain . domain ,
2022-01-14 22:40:51 -08:00
secondaryDomains : [ ] ,
2022-01-14 22:29:47 -08:00
redirectDomains : [ ] ,
2021-06-03 12:20:44 -07:00
aliasDomains : [ ]
} ;
2021-08-20 09:19:44 -07:00
Object . freeze ( app ) ;
2017-09-29 09:56:01 -07:00
2022-11-23 14:36:57 +01:00
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' ,
2024-06-10 10:53:00 +02:00
manifest : proxyAppManifest ,
2022-11-23 14:36:57 +01:00
containerId : '' ,
2024-07-16 22:21:36 +02:00
portBindings : { } ,
2022-11-23 14:36:57 +01:00
accessRestriction : null ,
memoryLimit : 0 ,
mailboxDomain : domain . domain ,
secondaryDomains : [ ] ,
redirectDomains : [ ] ,
aliasDomains : [ ]
} ;
Object . freeze ( proxyApp ) ;
2026-02-14 09:53:14 +01:00
const mockApiServerOrigin = 'http://localhost:6060' ;
const dashboardDomain = domain . domain ;
const dashboardFqdn = ` my. ${ domain . domain } ` ;
const appstoreToken = 'atoken' ;
const serverUrl = ` http://localhost: ${ constants . PORT } ` ;
2017-09-29 09:56:01 -07:00
function createTree ( root , obj ) {
2022-11-06 11:48:56 +01:00
fs . rmSync ( root , { recursive : true , force : true } ) ;
2020-06-11 08:27:48 -07:00
fs . mkdirSync ( root , { recursive : true } ) ;
2017-09-29 09:56:01 -07:00
function createSubTree ( tree , curpath ) {
2022-04-14 20:30:00 -05:00
for ( const key in tree ) {
2017-09-29 09:56:01 -07:00
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 ) ;
}
2021-08-20 09:19:44 -07:00
async function databaseSetup ( ) {
2021-06-03 12:20:44 -07:00
nock . cleanAll ( ) ;
2021-08-20 09:19:44 -07:00
await database . initialize ( ) ;
await database . _clear ( ) ;
2026-02-14 09:53:14 +01:00
await appstore . _setApiServerOrigin ( mockApiServerOrigin ) ;
await dashboard . _setLocation ( constants . DASHBOARD _SUBDOMAIN , dashboardDomain ) ;
2025-07-25 07:44:25 +02:00
// duplicated here since we clear the database
2025-09-22 17:59:26 +02:00
await backupSites . addDefault ( auditSource ) ;
2021-08-13 17:22:28 -07:00
}
2021-08-20 09:19:44 -07:00
async function domainSetup ( ) {
2021-08-13 17:22:28 -07:00
nock . cleanAll ( ) ;
2021-08-20 09:19:44 -07:00
await databaseSetup ( ) ;
2023-08-16 19:28:04 +05:30
await mailServer . setLocation ( constants . DASHBOARD _SUBDOMAIN , domain . domain ) ; // default mail location. do this before we add the domain for upserting mail DNS
2021-08-20 09:19:44 -07:00
await domains . add ( domain . domain , domain , auditSource ) ;
2021-07-19 12:43:30 -07:00
}
2022-11-22 21:38:22 +01:00
async function setup ( ) {
await domainSetup ( ) ;
const ownerId = await users . createOwner ( admin . email , admin . username , admin . password , admin . displayName , auditSource ) ;
admin . id = ownerId ;
2026-02-06 18:45:40 +01:00
await apps . add ( app . id , app . appStoreId , '' , app . manifest , app . subdomain , app . domain , app . portBindings , app ) ;
2026-02-14 09:53:14 +01:00
await settings . _set ( settings . APPSTORE _API _TOKEN _KEY , appstoreToken ) ; // appstore token
2022-11-22 21:38:22 +01:00
const userId = await users . add ( user . email , user , auditSource ) ;
user . id = userId ;
await tasks . stopAllTasks ( ) ;
2024-12-07 14:35:45 +01:00
await locks . releaseAll ( ) ;
2021-06-03 12:20:44 -07:00
}
2021-08-20 09:19:44 -07:00
async function cleanup ( ) {
2021-06-03 12:20:44 -07:00
nock . cleanAll ( ) ;
2026-02-14 09:53:14 +01:00
mailer . clearMailQueue ( ) ;
2021-06-03 12:20:44 -07:00
2024-01-23 10:24:48 +01:00
await cron . stopJobs ( ) ;
2021-08-20 09:19:44 -07:00
await database . _clear ( ) ;
await database . uninitialize ( ) ;
2021-06-03 12:20:44 -07:00
}
2021-07-19 12:43:30 -07:00
2021-08-13 14:43:08 -07:00
function clearMailQueue ( ) {
2026-02-14 09:53:14 +01:00
mailer . clearMailQueue ( ) ;
2021-08-13 14:43:08 -07:00
}
async function checkMails ( number ) {
2023-05-14 10:53:50 +02:00
await timers . setTimeout ( 1000 ) ;
2021-08-13 14:43:08 -07:00
expect ( mailer . _mailQueue . length ) . to . equal ( number ) ;
2026-02-14 09:53:14 +01:00
const emails = [ ... mailer . _mailQueue ] ; // copy before clearing
2021-08-13 14:43:08 -07:00
clearMailQueue ( ) ;
2021-10-28 11:18:31 +02:00
// return for further investigation
return emails ;
2021-08-13 14:43:08 -07:00
}
2025-07-25 07:44:25 +02:00
2025-09-12 09:48:37 +02:00
async function getDefaultBackupSite ( ) {
2025-09-29 14:44:42 +02:00
const result = await backupSites . list ( ) ;
2025-07-25 07:44:25 +02:00
return result [ 0 ] ;
}
2026-02-14 15:43:24 +01:00
export default {
createTree ,
domainSetup ,
databaseSetup ,
setup ,
cleanup ,
checkMails ,
clearMailQueue ,
getDefaultBackupSite ,
mockApiServerOrigin ,
dashboardDomain ,
dashboardFqdn ,
app ,
proxyApp ,
admin ,
auditSource ,
domain , // the domain object,
manifest ,
user ,
appstoreToken ,
serverUrl ,
} ;