1
0
mirror of https://github.com/sasjs/server.git synced 2025-12-11 03:34:35 +00:00
Files
server/api/src/app.ts
2022-05-06 11:40:12 +00:00

131 lines
3.6 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,
getWebBuildFolderPath,
loadAppStreamConfig,
setProcessVariables,
setupFolders
} from './utils'
import { getEnvCSPDirectives } from './utils/parseHelmetConfig'
dotenv.config()
const app = express()
app.use(cookieParser())
app.use(morgan('tiny'))
const { MODE, CORS, WHITELIST, PROTOCOL, HELMET_CSP_CONFIG_PATH, HELMET_COEP } =
process.env
export const cookieOptions = {
secure: PROTOCOL === 'https',
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000 // 24 hours
}
const cspConfigJson = getEnvCSPDirectives(HELMET_CSP_CONFIG_PATH)
const coepFlag =
HELMET_COEP === 'true' || HELMET_COEP === undefined ? true : false
/***********************************
* CSRF Protection *
***********************************/
export const csrfProtection = csrf({ cookie: cookieOptions })
/***********************************
* Handle security and origin *
***********************************/
app.use(
helmet({
contentSecurityPolicy: {
directives: {
...helmet.contentSecurityPolicy.getDefaultDirectives(),
...cspConfigJson
}
},
crossOriginEmbedderPolicy: coepFlag
})
)
/***********************************
* Enabling CORS *
***********************************/
if (MODE?.trim() !== 'server' || CORS?.trim() === 'enable') {
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?.trim() === 'server') {
// 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)
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: MongoStore.create({ clientPromise, collectionName: 'sessions' }),
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(getWebBuildFolderPath()))
app.use(onError)
return app
})