UNPKG

sqlpad

Version:

Web app. Write SQL and visualize the results. Supports Postgres, MySQL, SQL Server, Crate, Vertica and SAP HANA.

161 lines (140 loc) 5.09 kB
const fs = require('fs'); const path = require('path'); const express = require('express'); const helmet = require('helmet'); const session = require('express-session'); const FileStore = require('session-file-store')(session); const config = require('./lib/config'); const baseUrl = config.get('baseUrl'); const googleClientId = config.get('googleClientId'); const googleClientSecret = config.get('googleClientSecret'); const publicUrl = config.get('publicUrl'); const dbPath = config.get('dbPath'); const debug = config.get('debug'); const cookieName = config.get('cookieName'); const cookieSecret = config.get('cookieSecret'); const sessionMinutes = config.get('sessionMinutes'); const samlEntryPoint = config.get('samlEntryPoint'); const samlIssuer = config.get('samlIssuer'); const samlCallbackUrl = config.get('samlCallbackUrl'); const samlCert = config.get('samlCert'); const samlAuthContext = config.get('samlAuthContext'); /* Express setup ============================================================================= */ const bodyParser = require('body-parser'); const favicon = require('serve-favicon'); const morgan = require('morgan'); const passport = require('passport'); const errorhandler = require('errorhandler'); const app = express(); // Default helmet protections, minus frameguard (becaue of sqlpad iframe embed), adding referrerPolicy app.use(helmet.dnsPrefetchControl()); app.use(helmet.hidePoweredBy()); app.use(helmet.hsts({})); app.use(helmet.ieNoOpen()); app.use(helmet.noSniff()); app.use(helmet.xssFilter()); app.use(helmet.referrerPolicy({ policy: 'same-origin' })); app.set('env', debug ? 'development' : 'production'); if (debug) { app.use(errorhandler()); } app.use(favicon(path.join(__dirname, '/public/favicon.ico'))); app.use(bodyParser.json()); app.use( bodyParser.urlencoded({ extended: true }) ); app.use( session({ store: new FileStore({ path: path.join(dbPath, '/sessions') }), saveUninitialized: false, resave: true, rolling: true, cookie: { maxAge: 1000 * 60 * sessionMinutes }, secret: cookieSecret, name: cookieName }) ); app.use(passport.initialize()); app.use(passport.session()); app.use(baseUrl, express.static(path.join(__dirname, 'public'))); if (debug) { app.use(morgan('dev')); } /* Passport setup ============================================================================= */ require('./middleware/passport.js'); /* Routes ============================================================================= */ const routers = [ require('./routes/drivers.js'), require('./routes/users.js'), require('./routes/forgot-password.js'), require('./routes/password-reset.js'), require('./routes/connections.js'), require('./routes/test-connection.js'), require('./routes/queries.js'), require('./routes/query-result.js'), require('./routes/download-results.js'), // streams result download to browser require('./routes/schema-info.js'), require('./routes/tags.js'), require('./routes/format-sql.js'), require('./routes/signup-signin-signout.js') ]; if (googleClientId && googleClientSecret && publicUrl) { if (debug) { console.log('Enabling Google authentication Strategy.'); } routers.push(require('./routes/oauth.js')); } if ( samlEntryPoint && samlIssuer && samlCallbackUrl && samlCert && samlAuthContext ) { if (debug) { console.log('Enabling SAML authentication Strategy.'); } routers.push(require('./routes/saml.js')); } // Add all core routes to the baseUrl except for the */api/app route routers.forEach(function(router) { app.use(baseUrl, router); }); // Add '*/api/app' route last and without baseUrl app.use(require('./routes/app.js')); // For any missing api route, return a 404 // NOTE - this cannot be a general catch-all because it might be a valid non-api route from a front-end perspective app.use(baseUrl + '/api/', function(req, res) { console.log('reached catch all api route'); res.sendStatus(404); }); // Anything else should render the client-side app // Client-side routing will take care of things from here // Because index.html will be served via static plugin, // we need to rename it to something else and switch out the URLs to consider the baseUrl const indexPath = path.join(__dirname, 'public/index.html'); const indexTemplatePath = path.join(__dirname, 'public/index-template.html'); if (fs.existsSync(indexPath)) { fs.renameSync(indexPath, indexTemplatePath); } if (fs.existsSync(indexTemplatePath)) { const html = fs.readFileSync(indexTemplatePath, 'utf8'); const baseUrlHtml = html .replace(/="\/stylesheets/g, `="${baseUrl}/stylesheets`) .replace(/="\/javascripts/g, `="${baseUrl}/javascripts`) .replace(/="\/images/g, `="${baseUrl}/images`) .replace(/="\/fonts/g, `="${baseUrl}/fonts`) .replace(/="\/static/g, `="${baseUrl}/static`); app.use((req, res) => res.send(baseUrlHtml)); } else { console.error('\nNO FRONT END TEMPLATE DETECTED'); console.error('If not running in dev mode please report this issue.\n'); } module.exports = app;