2023-08-11 19:41:05 +05:30
'use strict' ;
exports = module . exports = {
getLocation ,
2023-08-13 10:29:24 +05:30
clearLocation ,
2023-08-12 21:47:24 +05:30
2023-08-17 13:02:36 +05:30
startPrepareLocation , // starts the task
prepareLocation , // the task to setup dns and cert
setupLocation , // initial setup from setup/restore
changeLocation , // only on dashboard change (post setup/restore)
2023-08-13 10:06:01 +05:30
2023-08-12 21:47:24 +05:30
getConfig ,
2023-08-16 11:34:41 +05:30
_setLocation : setLocation ,
2023-08-11 19:41:05 +05:30
} ;
2023-08-13 10:06:01 +05:30
const apps = require ( './apps.js' ) ,
appstore = require ( './appstore.js' ) ,
2025-08-14 11:17:38 +05:30
assert = require ( 'node:assert' ) ,
2023-08-13 10:06:01 +05:30
BoxError = require ( './boxerror.js' ) ,
2023-08-12 21:47:24 +05:30
branding = require ( './branding.js' ) ,
2023-08-11 19:41:05 +05:30
constants = require ( './constants.js' ) ,
2023-08-13 10:06:01 +05:30
debug = require ( 'debug' ) ( 'box:dashboard' ) ,
dns = require ( './dns.js' ) ,
2024-01-20 00:11:10 +01:00
externalLdap = require ( './externalldap.js' ) ,
eventlog = require ( './eventlog.js' ) ,
2023-08-17 10:44:07 +05:30
Location = require ( './location.js' ) ,
2023-08-12 21:47:24 +05:30
mailServer = require ( './mailserver.js' ) ,
2023-08-13 10:29:24 +05:30
platform = require ( './platform.js' ) ,
2023-08-13 10:06:01 +05:30
reverseProxy = require ( './reverseproxy.js' ) ,
safe = require ( 'safetydance' ) ,
2023-08-12 21:47:24 +05:30
settings = require ( './settings.js' ) ,
system = require ( './system.js' ) ,
2023-08-13 10:06:01 +05:30
tasks = require ( './tasks.js' ) ,
2024-06-12 10:27:59 +02:00
userDirectory = require ( './user-directory.js' ) ;
2023-08-11 19:41:05 +05:30
2023-08-13 10:29:24 +05:30
async function getLocation ( ) {
2023-08-17 10:44:07 +05:30
const domain = await settings . get ( settings . DASHBOARD _DOMAIN _KEY ) ;
const subdomain = await settings . get ( settings . DASHBOARD _SUBDOMAIN _KEY ) ;
return new Location ( subdomain , domain , Location . TYPE _DASHBOARD ) ;
2023-08-13 10:29:24 +05:30
}
2023-08-16 19:28:04 +05:30
async function setLocation ( subdomain , domain ) {
assert . strictEqual ( typeof subdomain , 'string' ) ;
2023-08-11 19:41:05 +05:30
assert . strictEqual ( typeof domain , 'string' ) ;
2023-08-16 19:28:04 +05:30
await settings . set ( settings . DASHBOARD _SUBDOMAIN _KEY , subdomain ) ;
2023-08-11 19:41:05 +05:30
await settings . set ( settings . DASHBOARD _DOMAIN _KEY , domain ) ;
2023-08-13 21:36:56 +05:30
debug ( ` setLocation: ${ domain || '<cleared>' } ` ) ;
2023-08-13 10:29:24 +05:30
}
2023-08-11 19:41:05 +05:30
2023-08-13 10:29:24 +05:30
async function clearLocation ( ) {
2023-08-16 19:28:04 +05:30
await setLocation ( '' , '' ) ;
2023-08-11 19:41:05 +05:30
}
2023-08-12 21:47:24 +05:30
async function getConfig ( ) {
const ubuntuVersion = await system . getUbuntuVersion ( ) ;
2025-07-09 18:28:55 +02:00
const kernelVersion = await system . getKernelVersion ( ) ;
2024-06-12 10:27:59 +02:00
const profileConfig = await userDirectory . getProfileConfig ( ) ;
2024-01-20 00:11:10 +01:00
const externalLdapConfig = await externalLdap . getConfig ( ) ;
2023-08-12 21:47:24 +05:30
const { fqdn : adminFqdn , domain : adminDomain } = await getLocation ( ) ;
// be picky about what we send out here since this is sent for 'normal' users as well
return {
apiServerOrigin : await appstore . getApiServerOrigin ( ) ,
webServerOrigin : await appstore . getWebServerOrigin ( ) ,
consoleServerOrigin : await appstore . getConsoleServerOrigin ( ) ,
adminDomain ,
adminFqdn ,
2023-09-12 18:03:36 +05:30
mailFqdn : ( await mailServer . getLocation ( ) ) . fqdn ,
2023-08-12 21:47:24 +05:30
version : constants . VERSION ,
ubuntuVersion ,
2025-07-09 18:28:55 +02:00
kernelVersion ,
2023-08-12 21:47:24 +05:30
isDemo : constants . DEMO ,
cloudronName : await branding . getCloudronName ( ) ,
footer : await branding . renderFooter ( ) ,
features : appstore . getFeatures ( ) ,
profileLocked : profileConfig . lockUserProfiles ,
mandatory2FA : profileConfig . mandatory2FA ,
2024-01-20 11:35:27 +01:00
external2FA : externalLdap . supports2FA ( externalLdapConfig ) ,
2024-01-20 00:11:10 +01:00
ldapGroupsSynced : externalLdapConfig . syncGroups
2023-08-12 21:47:24 +05:30
} ;
}
2023-08-13 10:06:01 +05:30
2023-08-14 09:40:31 +05:30
async function startPrepareLocation ( domain , auditSource ) {
2023-08-13 10:06:01 +05:30
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof auditSource , 'object' ) ;
2023-08-13 10:29:24 +05:30
debug ( ` prepareLocation: ${ domain } ` ) ;
2023-08-13 10:06:01 +05:30
2024-01-13 21:15:41 +01:00
if ( constants . DEMO ) throw new BoxError ( BoxError . BAD _STATE , 'Not allowed in demo mode' ) ;
2023-08-13 10:06:01 +05:30
const fqdn = dns . fqdn ( constants . DASHBOARD _SUBDOMAIN , domain ) ;
2025-06-10 12:54:08 +02:00
for ( const app of await apps . list ( ) ) {
const appName = ` ${ app . label || app . fqdn } ( ${ app . id } ) ` ;
if ( app . fqdn === fqdn ) throw new BoxError ( BoxError . BAD _STATE , ` Dashboard location conflicts with primary location of app ' ${ appName } ' ` ) ;
2025-06-10 13:01:40 +02:00
if ( app . secondaryDomains . some ( sd => sd . fqdn === fqdn ) ) throw new BoxError ( BoxError . BAD _STATE , ` Dashboard location conflicts with secondary location of app ' ${ appName } ' ` ) ;
2025-06-10 12:54:08 +02:00
if ( app . redirectDomains . some ( rd => rd . fqdn === fqdn ) ) throw new BoxError ( BoxError . BAD _STATE , ` Dashboard location conflicts with redirect location of app ' ${ appName } ' ` ) ;
if ( app . aliasDomains . some ( ad => ad . fqdn === fqdn ) ) throw new BoxError ( BoxError . BAD _STATE , ` Dashboard location conflicts with alias location of app ' ${ appName } ' ` ) ;
}
2023-08-13 10:06:01 +05:30
2023-08-14 09:40:31 +05:30
const taskId = await tasks . add ( tasks . TASK _PREPARE _DASHBOARD _LOCATION , [ constants . DASHBOARD _SUBDOMAIN , domain , auditSource ] ) ;
2025-06-17 18:54:12 +02:00
safe ( tasks . startTask ( taskId , { } ) , { debug } ) ; // background
2023-08-13 10:06:01 +05:30
return taskId ;
}
2023-08-14 09:40:31 +05:30
async function prepareLocation ( subdomain , domain , auditSource , progressCallback ) {
assert . strictEqual ( typeof subdomain , 'string' ) ;
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof auditSource , 'object' ) ;
assert . strictEqual ( typeof progressCallback , 'function' ) ;
const location = { subdomain , domain } ;
const fqdn = dns . fqdn ( subdomain , domain ) ;
progressCallback ( { percent : 20 , message : ` Updating DNS of ${ fqdn } ` } ) ;
await dns . registerLocations ( [ location ] , { overwriteDns : true } , progressCallback ) ;
progressCallback ( { percent : 40 , message : ` Waiting for DNS of ${ fqdn } ` } ) ;
await dns . waitForLocations ( [ location ] , progressCallback ) ;
progressCallback ( { percent : 60 , message : ` Getting certificate of ${ fqdn } ` } ) ;
await reverseProxy . ensureCertificate ( location , { } , auditSource ) ;
}
2023-08-16 19:28:04 +05:30
async function setupLocation ( subdomain , domain , auditSource ) {
assert . strictEqual ( typeof subdomain , 'string' ) ;
2023-08-13 10:06:01 +05:30
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof auditSource , 'object' ) ;
2023-08-13 21:36:56 +05:30
debug ( ` setupLocation: ${ domain } ` ) ;
2023-08-13 10:29:24 +05:30
2024-01-13 21:15:41 +01:00
if ( constants . DEMO ) throw new BoxError ( BoxError . BAD _STATE , 'Not allowed in demo mode' ) ;
2023-08-13 10:06:01 +05:30
2023-08-16 19:28:04 +05:30
await setLocation ( subdomain , domain ) ;
2024-04-27 11:10:24 +02:00
await platform . onDashboardLocationSet ( subdomain , domain ) ;
2023-08-17 13:02:36 +05:30
}
async function changeLocation ( subdomain , domain , auditSource ) {
assert . strictEqual ( typeof subdomain , 'string' ) ;
assert . strictEqual ( typeof domain , 'string' ) ;
assert . strictEqual ( typeof auditSource , 'object' ) ;
2023-09-29 09:26:22 +05:30
const oldLocation = await getLocation ( ) ;
2023-08-17 13:02:36 +05:30
await setupLocation ( subdomain , domain , auditSource ) ;
2023-08-14 14:20:20 +05:30
2023-08-17 13:02:36 +05:30
debug ( ` setupLocation: notifying appstore and platform of domain change to ${ domain } ` ) ;
2023-08-16 19:28:04 +05:30
await eventlog . add ( eventlog . ACTION _DASHBOARD _DOMAIN _UPDATE , auditSource , { subdomain , domain } ) ;
2023-08-16 11:34:41 +05:30
await safe ( appstore . updateCloudron ( { domain } ) , { debug } ) ;
await platform . onDashboardLocationChanged ( auditSource ) ;
2023-09-29 09:26:22 +05:30
2024-04-27 11:10:24 +02:00
await safe ( reverseProxy . removeDashboardConfig ( oldLocation . subdomain , oldLocation . domain ) , { debug } ) ;
2023-08-13 10:06:01 +05:30
}