1
0
mirror of https://github.com/sasjs/server.git synced 2025-12-10 19:34:34 +00:00
Files
server/api/src/app.ts
2022-05-25 10:44:57 +05:00

157 lines
4.0 KiB
TypeScript

import path from 'path'
import express, { ErrorRequestHandler } from 'express'
import csrf from 'csurf'
import session from 'express-session'
import MongoStore from 'connect-mongo'
import morgan from 'morgan'
import cookieParser from 'cookie-parser'
import dotenv from 'dotenv'
import cors from 'cors'
import helmet from 'helmet'
import {
connectDB,
copySASjsCore,
CorsType,
getWebBuildFolder,
HelmetCoepType,
instantiateLogger,
loadAppStreamConfig,
ModeType,
ProtocolType,
ReturnCode,
setProcessVariables,
setupFolders,
verifyEnvVariables
} from './utils'
import { getEnvCSPDirectives } from './utils/parseHelmetConfig'
dotenv.config()
instantiateLogger()
if (verifyEnvVariables()) process.exit(ReturnCode.InvalidEnv)
const app = express()
app.use(cookieParser())
const {
MODE,
CORS,
WHITELIST,
PROTOCOL,
HELMET_CSP_CONFIG_PATH,
HELMET_COEP,
LOG_FORMAT_MORGAN
} = process.env
app.use(morgan(LOG_FORMAT_MORGAN as string))
export const cookieOptions = {
secure: PROTOCOL === ProtocolType.HTTPS,
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000 // 24 hours
}
const cspConfigJson: { [key: string]: string[] | null } = getEnvCSPDirectives(
HELMET_CSP_CONFIG_PATH
)
if (PROTOCOL === ProtocolType.HTTP)
cspConfigJson['upgrade-insecure-requests'] = null
/***********************************
* CSRF Protection *
***********************************/
export const csrfProtection = csrf({ cookie: cookieOptions })
/***********************************
* Handle security and origin *
***********************************/
app.use(
helmet({
contentSecurityPolicy: {
directives: {
...helmet.contentSecurityPolicy.getDefaultDirectives(),
...cspConfigJson
}
},
crossOriginEmbedderPolicy: HELMET_COEP === HelmetCoepType.TRUE
})
)
/***********************************
* Enabling CORS *
***********************************/
if (CORS === CorsType.ENABLED) {
const whiteList: string[] = []
WHITELIST?.split(' ')
?.filter((url) => !!url)
.forEach((url) => {
if (url.startsWith('http'))
// removing trailing slash of URLs listing for CORS
whiteList.push(url.replace(/\/$/, ''))
})
console.log('All CORS Requests are enabled for:', whiteList)
app.use(cors({ credentials: true, origin: whiteList }))
}
/***********************************
* DB Connection & *
* Express Sessions *
* With Mongo Store *
***********************************/
if (MODE === ModeType.Server) {
let store: MongoStore | undefined
// NOTE: when exporting app.js as agent for supertest
// we should exclude connecting to the real database
if (process.env.NODE_ENV !== 'test') {
const clientPromise = connectDB().then((conn) => conn!.getClient() as any)
store = MongoStore.create({ clientPromise, collectionName: 'sessions' })
}
app.use(
session({
secret: process.env.SESSION_SECRET as string,
saveUninitialized: false, // don't create session until something stored
resave: false, //don't save session if unmodified
store,
cookie: cookieOptions
})
)
}
app.use(express.json({ limit: '100mb' }))
app.use(express.static(path.join(__dirname, '../public')))
const onError: ErrorRequestHandler = (err, req, res, next) => {
if (err.code === 'EBADCSRFTOKEN')
return res.status(400).send('Invalid CSRF token!')
console.error(err.stack)
res.status(500).send('Something broke!')
}
export default setProcessVariables().then(async () => {
await setupFolders()
await copySASjsCore()
// loading these modules after setting up variables due to
// multer's usage of process var process.driveLoc
const { setupRoutes } = await import('./routes/setupRoutes')
setupRoutes(app)
await loadAppStreamConfig()
// should be served after setting up web route
// index.html needs to be injected with some js script.
app.use(express.static(getWebBuildFolder()))
app.use(onError)
return app
})