mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-01-11 14:52:55 +01:00
Co-Authored-By: Eric Tuvesson <eric.tuvesson@gmail.com> Co-Authored-By: mikaeltellhed <2311083+mikaeltellhed@users.noreply.github.com> Co-Authored-By: kotte <14197736+mrtamagotchi@users.noreply.github.com> Co-Authored-By: Anders Larsson <64838990+anders-topp@users.noreply.github.com> Co-Authored-By: Johan <4934465+joolsus@users.noreply.github.com> Co-Authored-By: Tore Knudsen <18231882+torekndsn@users.noreply.github.com> Co-Authored-By: victoratndl <99176179+victoratndl@users.noreply.github.com>
199 lines
7.9 KiB
JavaScript
199 lines
7.9 KiB
JavaScript
/*
|
|
* Copyright (c) 2016-present, Parse, LLC
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the license found in the LICENSE file in
|
|
* the root directory of this source tree.
|
|
*/
|
|
// Command line tool for npm start
|
|
'use strict'
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const express = require('express');
|
|
const parseDashboard = require('./app');
|
|
const CLIHelper = require('./CLIHelper.js');
|
|
|
|
const program = require('commander');
|
|
program.option('--appId [appId]', 'the app Id of the app you would like to manage.');
|
|
program.option('--masterKey [masterKey]', 'the master key of the app you would like to manage.');
|
|
program.option('--serverURL [serverURL]', 'the server url of the app you would like to manage.');
|
|
program.option('--graphQLServerURL [graphQLServerURL]', 'the GraphQL server url of the app you would like to manage.');
|
|
program.option('--dev', 'Enable development mode. This will disable authentication and allow non HTTPS connections. DO NOT ENABLE IN PRODUCTION SERVERS');
|
|
program.option('--appName [appName]', 'the name of the app you would like to manage. Optional.');
|
|
program.option('--config [config]', 'the path to the configuration file');
|
|
program.option('--host [host]', 'the host to run parse-dashboard');
|
|
program.option('--port [port]', 'the port to run parse-dashboard');
|
|
program.option('--mountPath [mountPath]', 'the mount path to run parse-dashboard');
|
|
program.option('--allowInsecureHTTP [allowInsecureHTTP]', 'set this flag when you are running the dashboard behind an HTTPS load balancer or proxy with early SSL termination.');
|
|
program.option('--sslKey [sslKey]', 'the path to the SSL private key.');
|
|
program.option('--sslCert [sslCert]', 'the path to the SSL certificate.');
|
|
program.option('--trustProxy [trustProxy]', 'set this flag when you are behind a front-facing proxy, such as when hosting on Heroku. Uses X-Forwarded-* headers to determine the client\'s connection and IP address.');
|
|
program.option('--cookieSessionSecret [cookieSessionSecret]', 'set the cookie session secret, defaults to a random string. You should set that value if you want sessions to work across multiple server, or across restarts');
|
|
program.option('--createUser', 'helper tool to allow you to generate secure user passwords and secrets. Use this on trusted devices only.');
|
|
program.option('--createMFA', 'helper tool to allow you to generate multi-factor authentication secrets.');
|
|
|
|
program.parse(process.argv);
|
|
const options = program.opts();
|
|
|
|
for (const key in options) {
|
|
const func = CLIHelper[key];
|
|
if (func && typeof func === 'function') {
|
|
func();
|
|
return;
|
|
}
|
|
}
|
|
|
|
const host = options.host || process.env.HOST || '0.0.0.0';
|
|
const port = options.port || process.env.PORT || 4040;
|
|
const mountPath = options.mountPath || process.env.MOUNT_PATH || '/';
|
|
const allowInsecureHTTP = options.allowInsecureHTTP || process.env.PARSE_DASHBOARD_ALLOW_INSECURE_HTTP;
|
|
const cookieSessionSecret = options.cookieSessionSecret || process.env.PARSE_DASHBOARD_COOKIE_SESSION_SECRET;
|
|
const trustProxy = options.trustProxy || process.env.PARSE_DASHBOARD_TRUST_PROXY;
|
|
const dev = options.dev;
|
|
|
|
if (trustProxy && allowInsecureHTTP) {
|
|
console.log('Set only trustProxy *or* allowInsecureHTTP, not both. Only one is needed to handle being behind a proxy.');
|
|
process.exit(-1);
|
|
}
|
|
|
|
let explicitConfigFileProvided = !!options.config;
|
|
let configFile = null;
|
|
let configFromCLI = null;
|
|
let configServerURL = options.serverURL || process.env.PARSE_DASHBOARD_SERVER_URL;
|
|
let configGraphQLServerURL = options.graphQLServerURL || process.env.PARSE_DASHBOARD_GRAPHQL_SERVER_URL;
|
|
let configMasterKey = options.masterKey || process.env.PARSE_DASHBOARD_MASTER_KEY;
|
|
let configAppId = options.appId || process.env.PARSE_DASHBOARD_APP_ID;
|
|
let configAppName = options.appName || process.env.PARSE_DASHBOARD_APP_NAME;
|
|
let configUserId = options.userId || process.env.PARSE_DASHBOARD_USER_ID;
|
|
let configUserPassword = options.userPassword || process.env.PARSE_DASHBOARD_USER_PASSWORD;
|
|
let configSSLKey = options.sslKey || process.env.PARSE_DASHBOARD_SSL_KEY;
|
|
let configSSLCert = options.sslCert || process.env.PARSE_DASHBOARD_SSL_CERT;
|
|
|
|
function handleSIGs(server) {
|
|
const signals = {
|
|
'SIGINT': 2,
|
|
'SIGTERM': 15
|
|
};
|
|
function shutdown(signal, value) {
|
|
server.close(function () {
|
|
console.log('server stopped by ' + signal);
|
|
process.exit(128 + value);
|
|
});
|
|
}
|
|
Object.keys(signals).forEach(function (signal) {
|
|
process.on(signal, function () {
|
|
shutdown(signal, signals[signal]);
|
|
});
|
|
});
|
|
}
|
|
|
|
if (!options.config && !process.env.PARSE_DASHBOARD_CONFIG) {
|
|
if (configServerURL && configMasterKey && configAppId) {
|
|
configFromCLI = {
|
|
data: {
|
|
apps: [
|
|
{
|
|
appId: configAppId,
|
|
serverURL: configServerURL,
|
|
masterKey: configMasterKey,
|
|
appName: configAppName,
|
|
},
|
|
]
|
|
}
|
|
};
|
|
if (configGraphQLServerURL) {
|
|
configFromCLI.data.apps[0].graphQLServerURL = configGraphQLServerURL;
|
|
}
|
|
if (configUserId && configUserPassword) {
|
|
configFromCLI.data.users = [
|
|
{
|
|
user: configUserId,
|
|
pass: configUserPassword,
|
|
}
|
|
];
|
|
}
|
|
} else if (!configServerURL && !configMasterKey && !configAppName) {
|
|
configFile = path.join(__dirname, 'parse-dashboard-config.json');
|
|
}
|
|
} else if (!options.config && process.env.PARSE_DASHBOARD_CONFIG) {
|
|
configFromCLI = {
|
|
data: JSON.parse(process.env.PARSE_DASHBOARD_CONFIG)
|
|
};
|
|
} else {
|
|
configFile = options.config;
|
|
if (options.appId || options.serverURL || options.masterKey || options.appName || options.graphQLServerURL) {
|
|
console.log('You must provide either a config file or other CLI options (appName, appId, masterKey, serverURL, and graphQLServerURL); not both.');
|
|
process.exit(3);
|
|
}
|
|
}
|
|
|
|
let config = null;
|
|
let configFilePath = null;
|
|
if (configFile) {
|
|
try {
|
|
config = {
|
|
data: JSON.parse(fs.readFileSync(configFile, 'utf8'))
|
|
};
|
|
configFilePath = path.dirname(configFile);
|
|
} catch (error) {
|
|
if (error instanceof SyntaxError) {
|
|
console.log('Your config file contains invalid JSON. Exiting.');
|
|
process.exit(1);
|
|
} else if (error.code === 'ENOENT') {
|
|
if (explicitConfigFileProvided) {
|
|
console.log('Your config file is missing. Exiting.');
|
|
process.exit(2);
|
|
} else {
|
|
console.log('You must provide either a config file or required CLI options (app ID, Master Key, and server URL); not both.');
|
|
process.exit(3);
|
|
}
|
|
} else {
|
|
console.log('There was a problem with your config. Exiting.');
|
|
process.exit(-1);
|
|
}
|
|
}
|
|
} else if (configFromCLI) {
|
|
config = configFromCLI;
|
|
} else {
|
|
//Failed to load default config file.
|
|
console.log('You must provide either a config file or an app ID, Master Key, and server URL. See parse-dashboard --help for details.');
|
|
process.exit(4);
|
|
}
|
|
|
|
config.data.apps.forEach(app => {
|
|
if (!app.appName) {
|
|
app.appName = app.appId;
|
|
}
|
|
});
|
|
|
|
if (config.data.iconsFolder && configFilePath) {
|
|
config.data.iconsFolder = path.join(configFilePath, config.data.iconsFolder);
|
|
}
|
|
|
|
const app = express();
|
|
|
|
if (allowInsecureHTTP || trustProxy || dev) app.enable('trust proxy');
|
|
|
|
config.data.trustProxy = trustProxy;
|
|
let dashboardOptions = { allowInsecureHTTP, cookieSessionSecret, dev };
|
|
app.use(mountPath, parseDashboard(config.data, dashboardOptions));
|
|
let server;
|
|
if(!configSSLKey || !configSSLCert){
|
|
// Start the server.
|
|
server = app.listen(port, host, function () {
|
|
console.log(`The dashboard is now available at http://${server.address().address}:${server.address().port}${mountPath}`);
|
|
});
|
|
} else {
|
|
// Start the server using SSL.
|
|
var privateKey = fs.readFileSync(configSSLKey);
|
|
var certificate = fs.readFileSync(configSSLCert);
|
|
|
|
server = require('https').createServer({
|
|
key: privateKey,
|
|
cert: certificate
|
|
}, app).listen(port, host, function () {
|
|
console.log(`The dashboard is now available at https://${server.address().address}:${server.address().port}${mountPath}`);
|
|
});
|
|
}
|
|
handleSIGs(server);
|