2018-01-29 15:47:26 -08:00
'use strict' ;
exports = module . exports = {
providerTokenAuth : providerTokenAuth ,
2018-12-11 15:29:47 -08:00
setup : setup ,
2018-01-29 15:47:26 -08:00
activate : activate ,
2018-12-15 15:27:16 -08:00
restore : restore ,
getStatus : getStatus
2018-01-29 15:47:26 -08:00
} ;
var assert = require ( 'assert' ) ,
2019-12-10 17:30:38 +01:00
appstore = require ( '../appstore.js' ) ,
2019-10-23 15:45:09 -07:00
auditSource = require ( '../auditsource.js' ) ,
BoxError = require ( '../boxerror.js' ) ,
2018-01-29 15:47:26 -08:00
debug = require ( 'debug' ) ( 'box:routes/setup' ) ,
HttpError = require ( 'connect-lastmile' ) . HttpError ,
HttpSuccess = require ( 'connect-lastmile' ) . HttpSuccess ,
2018-12-11 15:29:47 -08:00
provision = require ( '../provision.js' ) ,
2019-12-11 14:54:59 -08:00
request = require ( 'request' ) ,
settings = require ( '../settings.js' ) ;
2018-01-29 15:47:26 -08:00
function providerTokenAuth ( req , res , next ) {
assert . strictEqual ( typeof req . body , 'object' ) ;
2019-10-29 15:46:33 -07:00
if ( settings . provider ( ) === 'ami' ) {
2018-01-29 15:47:26 -08:00
if ( typeof req . body . providerToken !== 'string' || ! req . body . providerToken ) return next ( new HttpError ( 400 , 'providerToken must be a non empty string' ) ) ;
2019-12-11 14:54:59 -08:00
request . get ( 'http://169.254.169.254/latest/meta-data/instance-id' , { timeout : 30 * 1000 } , function ( error , result ) {
if ( error ) return next ( new HttpError ( 422 , ` Network error getting EC2 metadata: ${ error . message } ` ) ) ;
if ( result . statusCode !== 200 ) return next ( new HttpError ( 422 , ` Unable to get EC2 meta data. statusCode: ${ result . statusCode } ` ) ) ;
2018-01-29 15:47:26 -08:00
2019-12-11 14:54:59 -08:00
if ( result . body !== req . body . providerToken ) return next ( new HttpError ( 422 , 'Instance ID does not match' ) ) ;
2018-01-29 15:47:26 -08:00
next ( ) ;
} ) ;
} else {
next ( ) ;
}
}
2018-12-11 15:29:47 -08:00
function setup ( req , res , next ) {
2018-01-29 15:47:26 -08:00
assert . strictEqual ( typeof req . body , 'object' ) ;
2018-10-30 13:36:00 -07:00
if ( ! req . body . dnsConfig || typeof req . body . dnsConfig !== 'object' ) return next ( new HttpError ( 400 , 'dnsConfig is required' ) ) ;
2018-01-29 15:47:26 -08:00
2018-10-30 13:36:00 -07:00
const dnsConfig = req . body . dnsConfig ;
2018-01-29 15:47:26 -08:00
2018-10-30 13:36:00 -07:00
if ( typeof dnsConfig . provider !== 'string' || ! dnsConfig . provider ) return next ( new HttpError ( 400 , 'provider is required' ) ) ;
if ( typeof dnsConfig . domain !== 'string' || ! dnsConfig . domain ) return next ( new HttpError ( 400 , 'domain is required' ) ) ;
2018-01-31 17:42:26 +01:00
2018-10-30 13:36:00 -07:00
if ( 'zoneName' in dnsConfig && typeof dnsConfig . zoneName !== 'string' ) return next ( new HttpError ( 400 , 'zoneName must be a string' ) ) ;
if ( ! dnsConfig . config || typeof dnsConfig . config !== 'object' ) return next ( new HttpError ( 400 , 'config must be an object' ) ) ;
if ( 'tlsConfig' in dnsConfig && typeof dnsConfig . tlsConfig !== 'object' ) return next ( new HttpError ( 400 , 'tlsConfig must be an object' ) ) ;
if ( dnsConfig . tlsConfig && ( ! dnsConfig . tlsConfig . provider || typeof dnsConfig . tlsConfig . provider !== 'string' ) ) return next ( new HttpError ( 400 , 'tlsConfig.provider must be a string' ) ) ;
2019-10-29 20:12:37 -07:00
if ( 'sysinfoConfig' in req . body && typeof req . body . sysinfoConfig !== 'object' ) return next ( new HttpError ( 400 , 'sysinfoConfig must be an object' ) ) ;
2018-10-30 18:43:52 -07:00
2018-11-02 17:24:38 -07:00
// it can take sometime to setup DNS, register cloudron
req . clearTimeout ( ) ;
2019-11-11 11:05:34 -08:00
provision . setup ( dnsConfig , req . body . sysinfoConfig || { provider : 'generic' } , auditSource . fromRequest ( req ) , function ( error ) {
2019-10-24 18:05:14 -07:00
if ( error ) return next ( BoxError . toHttpError ( error ) ) ;
2018-01-29 15:47:26 -08:00
2019-05-22 10:41:34 -07:00
next ( new HttpSuccess ( 200 , { } ) ) ;
2019-12-10 17:30:38 +01:00
appstore . trackFinishedSetup ( dnsConfig . domain ) ;
2018-01-29 15:47:26 -08:00
} ) ;
}
function activate ( req , res , next ) {
assert . strictEqual ( typeof req . body , 'object' ) ;
if ( typeof req . body . username !== 'string' ) return next ( new HttpError ( 400 , 'username must be string' ) ) ;
if ( typeof req . body . password !== 'string' ) return next ( new HttpError ( 400 , 'password must be string' ) ) ;
if ( typeof req . body . email !== 'string' ) return next ( new HttpError ( 400 , 'email must be string' ) ) ;
if ( 'displayName' in req . body && typeof req . body . displayName !== 'string' ) return next ( new HttpError ( 400 , 'displayName must be string' ) ) ;
var username = req . body . username ;
var password = req . body . password ;
var email = req . body . email ;
var displayName = req . body . displayName || '' ;
var ip = req . headers [ 'x-forwarded-for' ] || req . connection . remoteAddress ;
debug ( 'activate: username:%s ip:%s' , username , ip ) ;
2019-03-25 15:07:06 -07:00
provision . activate ( username , password , email , displayName , ip , auditSource . fromRequest ( req ) , function ( error , info ) {
2019-10-24 18:05:14 -07:00
if ( error ) return next ( BoxError . toHttpError ( error ) ) ;
2018-01-29 15:47:26 -08:00
2019-05-08 15:27:29 -07:00
next ( new HttpSuccess ( 201 , info ) ) ;
2018-01-29 15:47:26 -08:00
} ) ;
}
function restore ( req , res , next ) {
assert . strictEqual ( typeof req . body , 'object' ) ;
if ( ! req . body . backupConfig || typeof req . body . backupConfig !== 'object' ) return next ( new HttpError ( 400 , 'backupConfig is required' ) ) ;
var backupConfig = req . body . backupConfig ;
if ( typeof backupConfig . provider !== 'string' ) return next ( new HttpError ( 400 , 'provider is required' ) ) ;
if ( 'key' in backupConfig && typeof backupConfig . key !== 'string' ) return next ( new HttpError ( 400 , 'key must be a string' ) ) ;
if ( typeof backupConfig . format !== 'string' ) return next ( new HttpError ( 400 , 'format must be a string' ) ) ;
if ( 'acceptSelfSignedCerts' in backupConfig && typeof backupConfig . acceptSelfSignedCerts !== 'boolean' ) return next ( new HttpError ( 400 , 'format must be a boolean' ) ) ;
if ( typeof req . body . backupId !== 'string' ) return next ( new HttpError ( 400 , 'backupId must be a string or null' ) ) ;
if ( typeof req . body . version !== 'string' ) return next ( new HttpError ( 400 , 'version must be a string' ) ) ;
2019-11-11 09:49:18 -08:00
if ( 'sysinfoConfig' in req . body && typeof req . body . sysinfoConfig !== 'object' ) return next ( new HttpError ( 400 , 'sysinfoConfig must be an object' ) ) ;
2019-11-11 11:05:34 -08:00
provision . restore ( backupConfig , req . body . backupId , req . body . version , req . body . sysinfoConfig || { provider : 'generic' } , auditSource . fromRequest ( req ) , function ( error ) {
2019-10-24 18:05:14 -07:00
if ( error ) return next ( BoxError . toHttpError ( error ) ) ;
2018-01-29 15:47:26 -08:00
2019-05-22 10:41:34 -07:00
next ( new HttpSuccess ( 200 , { } ) ) ;
2018-01-29 15:47:26 -08:00
} ) ;
}
2018-12-15 15:27:16 -08:00
function getStatus ( req , res , next ) {
provision . getStatus ( function ( error , status ) {
2019-10-24 18:05:14 -07:00
if ( error ) return next ( BoxError . toHttpError ( error ) ) ;
2018-12-15 15:27:16 -08:00
next ( new HttpSuccess ( 200 , status ) ) ;
2019-12-10 17:30:38 +01:00
// check if Cloudron is not in setup state nor activated and let appstore know of the attempt
if ( ! status . activated && ! status . setup . active && ! status . restore . active ) {
appstore . trackBeginSetup ( status . provider ) ;
}
2018-12-15 15:27:16 -08:00
} ) ;
}