2015-07-20 00:09:47 -07:00
'use strict' ;
exports = module . exports = {
get : get ,
getByHttpPort : getByHttpPort ,
2015-09-14 17:01:04 -07:00
getByContainerId : getByContainerId ,
2015-07-20 00:09:47 -07:00
add : add ,
exists : exists ,
del : del ,
update : update ,
getAll : getAll ,
getPortBindings : getPortBindings ,
2017-10-23 22:05:43 +02:00
delPortBinding : delPortBinding ,
2015-07-20 00:09:47 -07:00
setAddonConfig : setAddonConfig ,
getAddonConfig : getAddonConfig ,
getAddonConfigByAppId : getAddonConfigByAppId ,
2017-03-26 19:06:36 -07:00
getAddonConfigByName : getAddonConfigByName ,
2015-07-20 00:09:47 -07:00
unsetAddonConfig : unsetAddonConfig ,
unsetAddonConfigByAppId : unsetAddonConfigByAppId ,
2018-12-06 21:08:19 -08:00
getAppIdByAddonConfigValue : getAppIdByAddonConfigValue ,
2015-07-20 00:09:47 -07:00
setHealth : setHealth ,
2019-08-29 12:14:42 -07:00
setTask : setTask ,
2015-07-20 00:09:47 -07:00
getAppStoreIds : getAppStoreIds ,
2018-06-29 11:04:14 +02:00
// subdomain table types
SUBDOMAIN _TYPE _PRIMARY : 'primary' ,
SUBDOMAIN _TYPE _REDIRECT : 'redirect' ,
2015-07-20 00:09:47 -07:00
_clear : clear
} ;
var assert = require ( 'assert' ) ,
async = require ( 'async' ) ,
2019-10-24 11:13:48 -07:00
BoxError = require ( './boxerror.js' ) ,
2015-07-20 00:09:47 -07:00
database = require ( './database.js' ) ,
safe = require ( 'safetydance' ) ,
util = require ( 'util' ) ;
2019-08-30 09:45:43 -07:00
var APPS _FIELDS _PREFIXED = [ 'apps.id' , 'apps.appStoreId' , 'apps.installationState' , 'apps.errorJson' , 'apps.runState' ,
2018-06-29 22:25:34 +02:00
'apps.health' , 'apps.containerId' , 'apps.manifestJson' , 'apps.httpPort' , 'subdomains.subdomain AS location' , 'subdomains.domain' ,
2020-01-28 21:30:35 -08:00
'apps.accessRestrictionJson' , 'apps.memoryLimit' , 'apps.cpuShares' ,
2020-04-29 21:55:21 -07:00
'apps.label' , 'apps.tagsJson' , 'apps.taskId' , 'apps.reverseProxyConfigJson' , 'apps.serviceConfigJson' , 'apps.bindsJson' ,
2019-10-13 18:22:03 -07:00
'apps.sso' , 'apps.debugModeJson' , 'apps.enableBackup' ,
2019-11-14 21:43:14 -08:00
'apps.creationTime' , 'apps.updateTime' , 'apps.mailboxName' , 'apps.mailboxDomain' , 'apps.enableAutomaticUpdate' ,
2019-02-12 16:03:12 -08:00
'apps.dataDir' , 'apps.ts' , 'apps.healthTime' ] . join ( ',' ) ;
2015-07-20 00:09:47 -07:00
2018-08-12 22:08:19 -07:00
var PORT _BINDINGS _FIELDS = [ 'hostPort' , 'type' , 'environmentVariable' , 'appId' ] . join ( ',' ) ;
2015-07-20 00:09:47 -07:00
2018-08-24 10:39:59 -07:00
const SUBDOMAIN _FIELDS = [ 'appId' , 'domain' , 'subdomain' , 'type' ] . join ( ',' ) ;
2015-07-20 00:09:47 -07:00
function postProcess ( result ) {
assert . strictEqual ( typeof result , 'object' ) ;
assert ( result . manifestJson === null || typeof result . manifestJson === 'string' ) ;
result . manifest = safe . JSON . parse ( result . manifestJson ) ;
delete result . manifestJson ;
2019-03-22 07:48:31 -07:00
assert ( result . tagsJson === null || typeof result . tagsJson === 'string' ) ;
2019-04-15 14:42:17 +02:00
result . tags = safe . JSON . parse ( result . tagsJson ) || [ ] ;
2019-03-22 07:48:31 -07:00
delete result . tagsJson ;
2019-10-13 18:22:03 -07:00
assert ( result . reverseProxyConfigJson === null || typeof result . reverseProxyConfigJson === 'string' ) ;
result . reverseProxyConfig = safe . JSON . parse ( result . reverseProxyConfigJson ) || { } ;
delete result . reverseProxyConfigJson ;
2015-07-20 00:09:47 -07:00
assert ( result . hostPorts === null || typeof result . hostPorts === 'string' ) ;
assert ( result . environmentVariables === null || typeof result . environmentVariables === 'string' ) ;
result . portBindings = { } ;
2018-08-12 22:08:19 -07:00
let hostPorts = result . hostPorts === null ? [ ] : result . hostPorts . split ( ',' ) ;
let environmentVariables = result . environmentVariables === null ? [ ] : result . environmentVariables . split ( ',' ) ;
let portTypes = result . portTypes === null ? [ ] : result . portTypes . split ( ',' ) ;
2015-07-20 00:09:47 -07:00
delete result . hostPorts ;
delete result . environmentVariables ;
2018-08-12 22:08:19 -07:00
delete result . portTypes ;
2015-07-20 00:09:47 -07:00
2018-10-11 14:07:43 -07:00
for ( let i = 0 ; i < environmentVariables . length ; i ++ ) {
2018-08-12 22:08:19 -07:00
result . portBindings [ environmentVariables [ i ] ] = { hostPort : parseInt ( hostPorts [ i ] , 10 ) , type : portTypes [ i ] } ;
2015-07-20 00:09:47 -07:00
}
2015-10-13 12:29:40 +02:00
2015-10-16 15:11:54 +02:00
assert ( result . accessRestrictionJson === null || typeof result . accessRestrictionJson === 'string' ) ;
result . accessRestriction = safe . JSON . parse ( result . accessRestrictionJson ) ;
if ( result . accessRestriction && ! result . accessRestriction . users ) result . accessRestriction . users = [ ] ;
delete result . accessRestrictionJson ;
2016-07-15 11:08:11 +02:00
2016-11-11 10:53:41 +05:30
result . sso = ! ! result . sso ; // make it bool
2017-08-16 14:12:07 -07:00
result . enableBackup = ! ! result . enableBackup ; // make it bool
2018-12-07 09:03:28 -08:00
result . enableAutomaticUpdate = ! ! result . enableAutomaticUpdate ; // make it bool
2017-01-20 05:48:25 -08:00
assert ( result . debugModeJson === null || typeof result . debugModeJson === 'string' ) ;
result . debugMode = safe . JSON . parse ( result . debugModeJson ) ;
delete result . debugModeJson ;
2018-06-29 15:07:20 +02:00
2020-04-28 14:34:17 -07:00
assert ( result . serviceConfigJson === null || typeof result . serviceConfigJson === 'string' ) ;
result . serviceConfig = safe . JSON . parse ( result . serviceConfigJson ) || { } ;
delete result . serviceConfigJson ;
2020-04-29 21:55:21 -07:00
assert ( result . bindsJson === null || typeof result . bindsJson === 'string' ) ;
result . binds = safe . JSON . parse ( result . bindsJson ) || { } ;
delete result . bindsJson ;
2018-06-29 15:50:18 +02:00
result . alternateDomains = result . alternateDomains || [ ] ;
result . alternateDomains . forEach ( function ( d ) {
delete d . appId ;
delete d . type ;
} ) ;
2018-10-11 14:07:43 -07:00
let envNames = JSON . parse ( result . envNames ) , envValues = JSON . parse ( result . envValues ) ;
delete result . envNames ;
delete result . envValues ;
result . env = { } ;
for ( let i = 0 ; i < envNames . length ; i ++ ) { // NOTE: envNames is [ null ] when env of an app is empty
if ( envNames [ i ] ) result . env [ envNames [ i ] ] = envValues [ i ] ;
}
2018-12-20 14:33:29 -08:00
2019-09-23 09:13:43 -07:00
result . error = safe . JSON . parse ( result . errorJson ) ;
2019-08-30 09:45:43 -07:00
delete result . errorJson ;
2019-08-26 15:28:29 -07:00
result . taskId = result . taskId ? String ( result . taskId ) : null ;
2015-07-20 00:09:47 -07:00
}
function get ( id , callback ) {
assert . strictEqual ( typeof id , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
database . query ( 'SELECT ' + APPS _FIELDS _PREFIXED + ','
2018-10-11 14:07:43 -07:00
+ 'GROUP_CONCAT(CAST(appPortBindings.hostPort AS CHAR(6))) AS hostPorts, GROUP_CONCAT(appPortBindings.environmentVariable) AS environmentVariables, GROUP_CONCAT(appPortBindings.type) AS portTypes, '
2020-04-27 22:55:43 -07:00
+ 'JSON_ARRAYAGG(appEnvVars.name) AS envNames, JSON_ARRAYAGG(appEnvVars.value) AS envValues'
2018-06-29 11:04:14 +02:00
+ ' FROM apps'
+ ' LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId'
2018-10-11 14:07:43 -07:00
+ ' LEFT OUTER JOIN appEnvVars ON apps.id = appEnvVars.appId'
2018-08-12 22:08:19 -07:00
+ ' LEFT OUTER JOIN subdomains ON apps.id = subdomains.appId AND subdomains.type = ?'
2018-06-29 11:04:14 +02:00
+ ' WHERE apps.id = ? GROUP BY apps.id' , [ exports . SUBDOMAIN _TYPE _PRIMARY , id ] , function ( error , result ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2019-10-24 20:48:38 -07:00
if ( result . length === 0 ) return callback ( new BoxError ( BoxError . NOT _FOUND , 'App not found' ) ) ;
2015-07-20 00:09:47 -07:00
2018-08-24 10:39:59 -07:00
database . query ( 'SELECT ' + SUBDOMAIN _FIELDS + ' FROM subdomains WHERE appId = ? AND type = ?' , [ id , exports . SUBDOMAIN _TYPE _REDIRECT ] , function ( error , alternateDomains ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2018-06-29 15:50:18 +02:00
result [ 0 ] . alternateDomains = alternateDomains ;
2015-07-20 00:09:47 -07:00
2018-06-29 15:50:18 +02:00
postProcess ( result [ 0 ] ) ;
callback ( null , result [ 0 ] ) ;
2018-10-11 14:07:43 -07:00
} ) ;
2015-07-20 00:09:47 -07:00
} ) ;
}
function getByHttpPort ( httpPort , callback ) {
assert . strictEqual ( typeof httpPort , 'number' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
database . query ( 'SELECT ' + APPS _FIELDS _PREFIXED + ','
2018-10-11 14:07:43 -07:00
+ 'GROUP_CONCAT(CAST(appPortBindings.hostPort AS CHAR(6))) AS hostPorts, GROUP_CONCAT(appPortBindings.environmentVariable) AS environmentVariables, GROUP_CONCAT(appPortBindings.type) AS portTypes,'
2020-04-27 22:55:43 -07:00
+ 'JSON_ARRAYAGG(appEnvVars.name) AS envNames, JSON_ARRAYAGG(appEnvVars.value) AS envValues'
2018-06-29 11:04:14 +02:00
+ ' FROM apps'
+ ' LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId'
2018-10-11 14:07:43 -07:00
+ ' LEFT OUTER JOIN appEnvVars ON apps.id = appEnvVars.appId'
2018-08-12 22:08:19 -07:00
+ ' LEFT OUTER JOIN subdomains ON apps.id = subdomains.appId AND subdomains.type = ?'
2018-06-29 11:04:14 +02:00
+ ' WHERE httpPort = ? GROUP BY apps.id' , [ exports . SUBDOMAIN _TYPE _PRIMARY , httpPort ] , function ( error , result ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2019-10-24 20:48:38 -07:00
if ( result . length === 0 ) return callback ( new BoxError ( BoxError . NOT _FOUND , 'App not found' ) ) ;
2015-07-20 00:09:47 -07:00
2018-08-24 10:39:59 -07:00
database . query ( 'SELECT ' + SUBDOMAIN _FIELDS + ' FROM subdomains WHERE appId = ? AND type = ?' , [ result [ 0 ] . id , exports . SUBDOMAIN _TYPE _REDIRECT ] , function ( error , alternateDomains ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2018-06-29 15:50:18 +02:00
result [ 0 ] . alternateDomains = alternateDomains ;
postProcess ( result [ 0 ] ) ;
2015-07-20 00:09:47 -07:00
2018-06-29 15:50:18 +02:00
callback ( null , result [ 0 ] ) ;
} ) ;
2015-07-20 00:09:47 -07:00
} ) ;
}
2015-09-14 17:01:04 -07:00
function getByContainerId ( containerId , callback ) {
assert . strictEqual ( typeof containerId , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
database . query ( 'SELECT ' + APPS _FIELDS _PREFIXED + ','
2018-10-11 14:07:43 -07:00
+ 'GROUP_CONCAT(CAST(appPortBindings.hostPort AS CHAR(6))) AS hostPorts, GROUP_CONCAT(appPortBindings.environmentVariable) AS environmentVariables, GROUP_CONCAT(appPortBindings.type) AS portTypes,'
2020-04-27 22:55:43 -07:00
+ 'JSON_ARRAYAGG(appEnvVars.name) AS envNames, JSON_ARRAYAGG(appEnvVars.value) AS envValues'
2018-06-29 11:04:14 +02:00
+ ' FROM apps'
+ ' LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId'
2018-10-11 14:07:43 -07:00
+ ' LEFT OUTER JOIN appEnvVars ON apps.id = appEnvVars.appId'
2018-08-12 22:08:19 -07:00
+ ' LEFT OUTER JOIN subdomains ON apps.id = subdomains.appId AND subdomains.type = ?'
2018-06-29 11:04:14 +02:00
+ ' WHERE containerId = ? GROUP BY apps.id' , [ exports . SUBDOMAIN _TYPE _PRIMARY , containerId ] , function ( error , result ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2019-10-24 20:48:38 -07:00
if ( result . length === 0 ) return callback ( new BoxError ( BoxError . NOT _FOUND , 'App not found' ) ) ;
2015-09-14 17:01:04 -07:00
2018-08-24 10:39:59 -07:00
database . query ( 'SELECT ' + SUBDOMAIN _FIELDS + ' FROM subdomains WHERE appId = ? AND type = ?' , [ result [ 0 ] . id , exports . SUBDOMAIN _TYPE _REDIRECT ] , function ( error , alternateDomains ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2018-06-29 15:50:18 +02:00
result [ 0 ] . alternateDomains = alternateDomains ;
postProcess ( result [ 0 ] ) ;
2015-09-14 17:01:04 -07:00
2018-06-29 15:50:18 +02:00
callback ( null , result [ 0 ] ) ;
} ) ;
2015-09-14 17:01:04 -07:00
} ) ;
}
2015-07-20 00:09:47 -07:00
function getAll ( callback ) {
assert . strictEqual ( typeof callback , 'function' ) ;
database . query ( 'SELECT ' + APPS _FIELDS _PREFIXED + ','
2018-10-11 14:07:43 -07:00
+ 'GROUP_CONCAT(CAST(appPortBindings.hostPort AS CHAR(6))) AS hostPorts, GROUP_CONCAT(appPortBindings.environmentVariable) AS environmentVariables, GROUP_CONCAT(appPortBindings.type) AS portTypes,'
2020-04-27 22:55:43 -07:00
+ 'JSON_ARRAYAGG(appEnvVars.name) AS envNames, JSON_ARRAYAGG(appEnvVars.value) AS envValues'
2018-06-29 11:04:14 +02:00
+ ' FROM apps'
+ ' LEFT OUTER JOIN appPortBindings ON apps.id = appPortBindings.appId'
2018-10-11 14:07:43 -07:00
+ ' LEFT OUTER JOIN appEnvVars ON apps.id = appEnvVars.appId'
2018-08-12 22:08:19 -07:00
+ ' LEFT OUTER JOIN subdomains ON apps.id = subdomains.appId AND subdomains.type = ?'
2018-06-29 11:04:14 +02:00
+ ' GROUP BY apps.id ORDER BY apps.id' , [ exports . SUBDOMAIN _TYPE _PRIMARY ] , function ( error , results ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2015-07-20 00:09:47 -07:00
2018-08-24 10:39:59 -07:00
database . query ( 'SELECT ' + SUBDOMAIN _FIELDS + ' FROM subdomains WHERE type = ?' , [ exports . SUBDOMAIN _TYPE _REDIRECT ] , function ( error , alternateDomains ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2015-07-20 00:09:47 -07:00
2018-06-29 15:50:18 +02:00
alternateDomains . forEach ( function ( d ) {
var domain = results . find ( function ( a ) { return d . appId === a . id ; } ) ;
if ( ! domain ) return ;
domain . alternateDomains = domain . alternateDomains || [ ] ;
domain . alternateDomains . push ( d ) ;
} ) ;
results . forEach ( postProcess ) ;
callback ( null , results ) ;
} ) ;
2015-07-20 00:09:47 -07:00
} ) ;
}
2019-07-02 20:22:17 -07:00
function add ( id , appStoreId , manifest , location , domain , portBindings , data , callback ) {
2015-07-20 00:09:47 -07:00
assert . strictEqual ( typeof id , 'string' ) ;
assert . strictEqual ( typeof appStoreId , 'string' ) ;
assert ( manifest && typeof manifest === 'object' ) ;
assert . strictEqual ( typeof manifest . version , 'string' ) ;
assert . strictEqual ( typeof location , 'string' ) ;
2017-11-02 22:16:42 +01:00
assert . strictEqual ( typeof domain , 'string' ) ;
2015-07-20 00:09:47 -07:00
assert . strictEqual ( typeof portBindings , 'object' ) ;
2016-06-17 16:43:35 -05:00
assert ( data && typeof data === 'object' ) ;
2015-07-20 00:09:47 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
portBindings = portBindings || { } ;
var manifestJson = JSON . stringify ( manifest ) ;
2016-06-17 16:43:35 -05:00
2019-03-22 07:48:31 -07:00
const accessRestriction = data . accessRestriction || null ;
const accessRestrictionJson = JSON . stringify ( accessRestriction ) ;
const memoryLimit = data . memoryLimit || 0 ;
2020-01-28 21:30:35 -08:00
const cpuShares = data . cpuShares || 512 ;
2019-09-23 17:23:38 -07:00
const installationState = data . installationState ;
const runState = data . runState ;
2019-03-22 07:48:31 -07:00
const sso = 'sso' in data ? data . sso : null ;
const debugModeJson = data . debugMode ? JSON . stringify ( data . debugMode ) : null ;
const env = data . env || { } ;
const label = data . label || null ;
const tagsJson = data . tags ? JSON . stringify ( data . tags ) : null ;
2019-03-22 14:26:25 -07:00
const mailboxName = data . mailboxName || null ;
2019-11-14 21:43:14 -08:00
const mailboxDomain = data . mailboxDomain || null ;
2019-11-05 13:58:02 -08:00
const reverseProxyConfigJson = data . reverseProxyConfig ? JSON . stringify ( data . reverseProxyConfig ) : null ;
2015-07-20 00:09:47 -07:00
2017-02-08 23:50:26 +01:00
var queries = [ ] ;
2018-06-29 11:04:14 +02:00
2015-07-20 00:09:47 -07:00
queries . push ( {
2020-01-28 21:30:35 -08:00
query : 'INSERT INTO apps (id, appStoreId, manifestJson, installationState, runState, accessRestrictionJson, memoryLimit, cpuShares, '
2019-11-14 21:43:14 -08:00
+ 'sso, debugModeJson, mailboxName, mailboxDomain, label, tagsJson, reverseProxyConfigJson) '
2020-01-28 21:30:35 -08:00
+ ' VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' ,
args : [ id , appStoreId , manifestJson , installationState , runState , accessRestrictionJson , memoryLimit , cpuShares ,
2019-11-14 21:43:14 -08:00
sso , debugModeJson , mailboxName , mailboxDomain , label , tagsJson , reverseProxyConfigJson ]
2015-07-20 00:09:47 -07:00
} ) ;
2018-06-29 11:04:14 +02:00
queries . push ( {
query : 'INSERT INTO subdomains (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)' ,
args : [ id , domain , location , exports . SUBDOMAIN _TYPE _PRIMARY ]
} ) ;
2015-07-20 00:09:47 -07:00
Object . keys ( portBindings ) . forEach ( function ( env ) {
queries . push ( {
2018-08-12 22:08:19 -07:00
query : 'INSERT INTO appPortBindings (environmentVariable, hostPort, type, appId) VALUES (?, ?, ?, ?)' ,
args : [ env , portBindings [ env ] . hostPort , portBindings [ env ] . type , id ]
2015-07-20 00:09:47 -07:00
} ) ;
} ) ;
2018-10-11 14:07:43 -07:00
Object . keys ( env ) . forEach ( function ( name ) {
queries . push ( {
query : 'INSERT INTO appEnvVars (appId, name, value) VALUES (?, ?, ?)' ,
args : [ id , name , env [ name ] ]
} ) ;
} ) ;
2018-06-29 15:50:18 +02:00
if ( data . alternateDomains ) {
data . alternateDomains . forEach ( function ( d ) {
queries . push ( {
query : 'INSERT INTO subdomains (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)' ,
args : [ id , d . domain , d . subdomain , exports . SUBDOMAIN _TYPE _REDIRECT ]
} ) ;
} ) ;
}
2015-07-20 00:09:47 -07:00
database . transaction ( queries , function ( error ) {
2019-10-24 11:13:48 -07:00
if ( error && error . code === 'ER_DUP_ENTRY' ) return callback ( new BoxError ( BoxError . ALREADY _EXISTS , error . message ) ) ;
if ( error && error . code === 'ER_NO_REFERENCED_ROW_2' ) return callback ( new BoxError ( BoxError . NOT _FOUND , 'no such domain' ) ) ;
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2015-07-20 00:09:47 -07:00
callback ( null ) ;
} ) ;
}
function exists ( id , callback ) {
assert . strictEqual ( typeof id , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
database . query ( 'SELECT 1 FROM apps WHERE id=?' , [ id ] , function ( error , result ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2015-07-20 00:09:47 -07:00
return callback ( null , result . length !== 0 ) ;
} ) ;
}
function getPortBindings ( id , callback ) {
assert . strictEqual ( typeof id , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
database . query ( 'SELECT ' + PORT _BINDINGS _FIELDS + ' FROM appPortBindings WHERE appId = ?' , [ id ] , function ( error , results ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2015-07-20 00:09:47 -07:00
var portBindings = { } ;
for ( var i = 0 ; i < results . length ; i ++ ) {
2018-08-12 22:08:19 -07:00
portBindings [ results [ i ] . environmentVariable ] = { hostPort : results [ i ] . hostPort , type : results [ i ] . type } ;
2015-07-20 00:09:47 -07:00
}
callback ( null , portBindings ) ;
} ) ;
}
2018-08-12 22:08:19 -07:00
function delPortBinding ( hostPort , type , callback ) {
2017-10-23 22:05:43 +02:00
assert . strictEqual ( typeof hostPort , 'number' ) ;
2018-08-12 22:08:19 -07:00
assert . strictEqual ( typeof type , 'string' ) ;
2017-10-23 22:05:43 +02:00
assert . strictEqual ( typeof callback , 'function' ) ;
2018-08-12 22:08:19 -07:00
database . query ( 'DELETE FROM appPortBindings WHERE hostPort=? AND type=?' , [ hostPort , type ] , function ( error , result ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2019-10-24 20:48:38 -07:00
if ( result . affectedRows !== 1 ) return callback ( new BoxError ( BoxError . NOT _FOUND , 'App not found' ) ) ;
2017-10-23 22:05:43 +02:00
callback ( null ) ;
} ) ;
}
2015-07-20 00:09:47 -07:00
function del ( id , callback ) {
assert . strictEqual ( typeof id , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
var queries = [
2018-06-29 11:04:14 +02:00
{ query : 'DELETE FROM subdomains WHERE appId = ?' , args : [ id ] } ,
2015-07-20 00:09:47 -07:00
{ query : 'DELETE FROM appPortBindings WHERE appId = ?' , args : [ id ] } ,
2018-10-11 14:07:43 -07:00
{ query : 'DELETE FROM appEnvVars WHERE appId = ?' , args : [ id ] } ,
2020-01-31 15:28:42 -08:00
{ query : 'DELETE FROM appPasswords WHERE identifier = ?' , args : [ id ] } ,
2015-07-20 00:09:47 -07:00
{ query : 'DELETE FROM apps WHERE id = ?' , args : [ id ] }
] ;
database . transaction ( queries , function ( error , results ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2020-04-27 22:55:43 -07:00
if ( results [ 4 ] . affectedRows !== 1 ) return callback ( new BoxError ( BoxError . NOT _FOUND , 'App not found' ) ) ;
2015-07-20 00:09:47 -07:00
callback ( null ) ;
} ) ;
}
function clear ( callback ) {
assert . strictEqual ( typeof callback , 'function' ) ;
async . series ( [
2018-06-29 11:04:14 +02:00
database . query . bind ( null , 'DELETE FROM subdomains' ) ,
2015-07-20 00:09:47 -07:00
database . query . bind ( null , 'DELETE FROM appPortBindings' ) ,
database . query . bind ( null , 'DELETE FROM appAddonConfigs' ) ,
2018-10-11 14:07:43 -07:00
database . query . bind ( null , 'DELETE FROM appEnvVars' ) ,
2015-07-20 00:09:47 -07:00
database . query . bind ( null , 'DELETE FROM apps' )
] , function ( error ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2015-07-20 00:09:47 -07:00
return callback ( null ) ;
} ) ;
}
function update ( id , app , callback ) {
updateWithConstraints ( id , app , '' , callback ) ;
}
function updateWithConstraints ( id , app , constraints , callback ) {
assert . strictEqual ( typeof id , 'string' ) ;
assert . strictEqual ( typeof app , 'object' ) ;
assert . strictEqual ( typeof constraints , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
assert ( ! ( 'portBindings' in app ) || typeof app . portBindings === 'object' ) ;
2016-02-18 17:28:00 +01:00
assert ( ! ( 'accessRestriction' in app ) || typeof app . accessRestriction === 'object' || app . accessRestriction === '' ) ;
2018-06-29 16:50:09 +02:00
assert ( ! ( 'alternateDomains' in app ) || Array . isArray ( app . alternateDomains ) ) ;
2019-04-11 17:18:11 +02:00
assert ( ! ( 'tags' in app ) || Array . isArray ( app . tags ) ) ;
2018-10-11 14:07:43 -07:00
assert ( ! ( 'env' in app ) || typeof app . env === 'object' ) ;
2015-07-20 00:09:47 -07:00
var queries = [ ] ;
if ( 'portBindings' in app ) {
var portBindings = app . portBindings || { } ;
// replace entries by app id
queries . push ( { query : 'DELETE FROM appPortBindings WHERE appId = ?' , args : [ id ] } ) ;
Object . keys ( portBindings ) . forEach ( function ( env ) {
2018-08-12 22:08:19 -07:00
var values = [ portBindings [ env ] . hostPort , portBindings [ env ] . type , env , id ] ;
queries . push ( { query : 'INSERT INTO appPortBindings (hostPort, type, environmentVariable, appId) VALUES(?, ?, ?, ?)' , args : values } ) ;
2015-07-20 00:09:47 -07:00
} ) ;
}
2018-10-11 14:07:43 -07:00
if ( 'env' in app ) {
queries . push ( { query : 'DELETE FROM appEnvVars WHERE appId = ?' , args : [ id ] } ) ;
Object . keys ( app . env ) . forEach ( function ( name ) {
queries . push ( {
query : 'INSERT INTO appEnvVars (appId, name, value) VALUES (?, ?, ?)' ,
args : [ id , name , app . env [ name ] ]
} ) ;
} ) ;
}
2018-12-11 12:10:22 -08:00
if ( 'location' in app && 'domain' in app ) { // must be updated together as they are unique together
queries . push ( { query : 'UPDATE subdomains SET subdomain = ?, domain = ? WHERE appId = ? AND type = ?' , args : [ app . location , app . domain , id , exports . SUBDOMAIN _TYPE _PRIMARY ] } ) ;
2018-06-29 11:04:14 +02:00
}
2018-06-29 15:03:36 +02:00
if ( 'alternateDomains' in app ) {
queries . push ( { query : 'DELETE FROM subdomains WHERE appId = ? AND type = ?' , args : [ id , exports . SUBDOMAIN _TYPE _REDIRECT ] } ) ;
app . alternateDomains . forEach ( function ( d ) {
queries . push ( { query : 'INSERT INTO subdomains (appId, domain, subdomain, type) VALUES (?, ?, ?, ?)' , args : [ id , d . domain , d . subdomain , exports . SUBDOMAIN _TYPE _REDIRECT ] } ) ;
} ) ;
}
2015-07-20 00:09:47 -07:00
var fields = [ ] , values = [ ] ;
for ( var p in app ) {
2020-04-29 21:55:21 -07:00
if ( p === 'manifest' || p === 'tags' || p === 'accessRestriction' || p === 'debugMode' || p === 'error' || p === 'reverseProxyConfig' || p === 'serviceConfig' || p === 'binds' ) {
2017-10-12 17:46:15 -07:00
fields . push ( ` ${ p } Json = ? ` ) ;
2017-01-20 09:40:11 -08:00
values . push ( JSON . stringify ( app [ p ] ) ) ;
2020-04-27 22:55:43 -07:00
} else if ( p !== 'portBindings' && p !== 'location' && p !== 'domain' && p !== 'alternateDomains' && p !== 'env' ) {
2015-07-20 00:09:47 -07:00
fields . push ( p + ' = ?' ) ;
values . push ( app [ p ] ) ;
}
}
if ( values . length !== 0 ) {
values . push ( id ) ;
queries . push ( { query : 'UPDATE apps SET ' + fields . join ( ', ' ) + ' WHERE id = ? ' + constraints , args : values } ) ;
}
database . transaction ( queries , function ( error , results ) {
2019-10-24 11:13:48 -07:00
if ( error && error . code === 'ER_DUP_ENTRY' ) return callback ( new BoxError ( BoxError . ALREADY _EXISTS , error . message ) ) ;
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2019-10-24 20:48:38 -07:00
if ( results [ results . length - 1 ] . affectedRows !== 1 ) return callback ( new BoxError ( BoxError . NOT _FOUND , 'App not found' ) ) ;
2015-07-20 00:09:47 -07:00
return callback ( null ) ;
} ) ;
}
2019-02-12 16:03:12 -08:00
function setHealth ( appId , health , healthTime , callback ) {
2015-07-20 00:09:47 -07:00
assert . strictEqual ( typeof appId , 'string' ) ;
assert . strictEqual ( typeof health , 'string' ) ;
2019-02-12 16:03:12 -08:00
assert ( util . isDate ( healthTime ) ) ;
2015-07-20 00:09:47 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
2019-02-12 16:03:12 -08:00
var values = { health , healthTime } ;
2015-07-20 00:09:47 -07:00
2019-08-30 12:57:59 -07:00
updateWithConstraints ( appId , values , '' , callback ) ;
2015-07-20 00:09:47 -07:00
}
2019-09-24 20:29:01 -07:00
function setTask ( appId , values , options , callback ) {
2015-07-20 00:09:47 -07:00
assert . strictEqual ( typeof appId , 'string' ) ;
2019-08-29 09:10:39 -07:00
assert . strictEqual ( typeof values , 'object' ) ;
2019-09-24 20:29:01 -07:00
assert . strictEqual ( typeof options , 'object' ) ;
2019-08-29 09:10:39 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
2015-07-20 00:09:47 -07:00
2019-09-24 20:29:01 -07:00
if ( ! options . requireNullTaskId ) return updateWithConstraints ( appId , values , '' , callback ) ;
if ( options . requiredState === null ) {
2019-09-23 13:32:52 -07:00
updateWithConstraints ( appId , values , 'AND taskId IS NULL' , callback ) ;
2019-09-21 19:45:55 -07:00
} else {
2019-09-24 20:29:01 -07:00
updateWithConstraints ( appId , values , ` AND taskId IS NULL AND installationState = " ${ options . requiredState } " ` , callback ) ;
2019-09-21 19:45:55 -07:00
}
2015-07-20 00:09:47 -07:00
}
function getAppStoreIds ( callback ) {
assert . strictEqual ( typeof callback , 'function' ) ;
database . query ( 'SELECT id, appStoreId FROM apps' , function ( error , results ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2015-07-20 00:09:47 -07:00
callback ( null , results ) ;
} ) ;
}
function setAddonConfig ( appId , addonId , env , callback ) {
assert . strictEqual ( typeof appId , 'string' ) ;
assert . strictEqual ( typeof addonId , 'string' ) ;
assert ( util . isArray ( env ) ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
unsetAddonConfig ( appId , addonId , function ( error ) {
if ( error ) return callback ( error ) ;
if ( env . length === 0 ) return callback ( null ) ;
2017-03-25 14:14:57 -07:00
var query = 'INSERT INTO appAddonConfigs(appId, addonId, name, value) VALUES ' ;
2015-07-20 00:09:47 -07:00
var args = [ ] , queryArgs = [ ] ;
for ( var i = 0 ; i < env . length ; i ++ ) {
2017-03-25 14:14:57 -07:00
args . push ( appId , addonId , env [ i ] . name , env [ i ] . value ) ;
queryArgs . push ( '(?, ?, ?, ?)' ) ;
2015-07-20 00:09:47 -07:00
}
database . query ( query + queryArgs . join ( ',' ) , args , function ( error ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2015-07-20 00:09:47 -07:00
return callback ( null ) ;
} ) ;
} ) ;
}
function unsetAddonConfig ( appId , addonId , callback ) {
assert . strictEqual ( typeof appId , 'string' ) ;
assert . strictEqual ( typeof addonId , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
database . query ( 'DELETE FROM appAddonConfigs WHERE appId = ? AND addonId = ?' , [ appId , addonId ] , function ( error ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2015-07-20 00:09:47 -07:00
callback ( null ) ;
} ) ;
}
function unsetAddonConfigByAppId ( appId , callback ) {
assert . strictEqual ( typeof appId , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
database . query ( 'DELETE FROM appAddonConfigs WHERE appId = ?' , [ appId ] , function ( error ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2015-07-20 00:09:47 -07:00
callback ( null ) ;
} ) ;
}
function getAddonConfig ( appId , addonId , callback ) {
assert . strictEqual ( typeof appId , 'string' ) ;
assert . strictEqual ( typeof addonId , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
2017-03-25 14:14:57 -07:00
database . query ( 'SELECT name, value FROM appAddonConfigs WHERE appId = ? AND addonId = ?' , [ appId , addonId ] , function ( error , results ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2015-07-20 00:09:47 -07:00
2017-03-25 14:14:57 -07:00
callback ( null , results ) ;
2015-07-20 00:09:47 -07:00
} ) ;
}
function getAddonConfigByAppId ( appId , callback ) {
assert . strictEqual ( typeof appId , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
2017-03-25 14:14:57 -07:00
database . query ( 'SELECT name, value FROM appAddonConfigs WHERE appId = ?' , [ appId ] , function ( error , results ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2015-07-20 00:09:47 -07:00
2017-03-25 14:14:57 -07:00
callback ( null , results ) ;
2015-07-20 00:09:47 -07:00
} ) ;
}
2017-03-26 19:06:36 -07:00
2019-06-17 11:13:59 -07:00
function getAppIdByAddonConfigValue ( addonId , namePattern , value , callback ) {
2018-12-06 21:08:19 -08:00
assert . strictEqual ( typeof addonId , 'string' ) ;
2019-06-17 11:13:59 -07:00
assert . strictEqual ( typeof namePattern , 'string' ) ;
2018-12-06 21:08:19 -08:00
assert . strictEqual ( typeof value , 'string' ) ;
assert . strictEqual ( typeof callback , 'function' ) ;
2019-06-17 11:13:59 -07:00
database . query ( 'SELECT appId FROM appAddonConfigs WHERE addonId = ? AND name LIKE ? AND value = ?' , [ addonId , namePattern , value ] , function ( error , results ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2019-10-24 20:48:38 -07:00
if ( results . length === 0 ) return callback ( new BoxError ( BoxError . NOT _FOUND , 'App not found' ) ) ;
2018-12-06 21:08:19 -08:00
callback ( null , results [ 0 ] . appId ) ;
} ) ;
}
2019-06-20 11:57:32 -07:00
function getAddonConfigByName ( appId , addonId , namePattern , callback ) {
2017-03-26 19:06:36 -07:00
assert . strictEqual ( typeof appId , 'string' ) ;
assert . strictEqual ( typeof addonId , 'string' ) ;
2019-06-20 11:57:32 -07:00
assert . strictEqual ( typeof namePattern , 'string' ) ;
2017-03-26 19:06:36 -07:00
assert . strictEqual ( typeof callback , 'function' ) ;
2019-06-20 11:57:32 -07:00
database . query ( 'SELECT value FROM appAddonConfigs WHERE appId = ? AND addonId = ? AND name LIKE ?' , [ appId , addonId , namePattern ] , function ( error , results ) {
2019-10-24 11:13:48 -07:00
if ( error ) return callback ( new BoxError ( BoxError . DATABASE _ERROR , error ) ) ;
2019-10-24 20:48:38 -07:00
if ( results . length === 0 ) return callback ( new BoxError ( BoxError . NOT _FOUND , 'App not found' ) ) ;
2017-03-26 19:06:36 -07:00
callback ( null , results [ 0 ] . value ) ;
} ) ;
}