mirror of
https://github.com/sasjs/server.git
synced 2025-12-10 19:34:34 +00:00
Compare commits
3 Commits
ea2ec97c1c
...
domain-che
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ed10109c1 | ||
|
|
ef9cca575f | ||
|
|
efbfd3f392 |
@@ -1,5 +1,6 @@
|
||||
MODE=[desktop|server] default considered as desktop
|
||||
CORS=[disable|enable] default considered as disable for server MODE & enable for desktop MODE
|
||||
ALLOWED_DOMAINS=<space separated urls, each starting with protocol `http` or `https`>
|
||||
WHITELIST=<space separated urls, each starting with protocol `http` or `https`>
|
||||
|
||||
PROTOCOL=[http|https] default considered as http
|
||||
|
||||
@@ -3,10 +3,21 @@ import cors from 'cors'
|
||||
import { CorsType } from '../utils'
|
||||
|
||||
export const configureCors = (app: Express) => {
|
||||
const { CORS } = process.env
|
||||
|
||||
if (CORS === CorsType.ENABLED) {
|
||||
const whiteList = getWhiteListed()
|
||||
|
||||
console.log('All CORS Requests are enabled for:', whiteList)
|
||||
app.use(cors({ credentials: true, origin: whiteList }))
|
||||
}
|
||||
}
|
||||
|
||||
export const getWhiteListed = (): string[] => {
|
||||
const whiteList: string[] = []
|
||||
const { CORS, WHITELIST } = process.env
|
||||
|
||||
if (CORS === CorsType.ENABLED) {
|
||||
const whiteList: string[] = []
|
||||
WHITELIST?.split(' ')
|
||||
?.filter((url) => !!url)
|
||||
.forEach((url) => {
|
||||
@@ -14,8 +25,6 @@ export const configureCors = (app: Express) => {
|
||||
// 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 }))
|
||||
}
|
||||
return whiteList
|
||||
}
|
||||
|
||||
29
api/src/app-modules/configureDomains.ts
Normal file
29
api/src/app-modules/configureDomains.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Express } from 'express'
|
||||
import { checkDomain } from '../middlewares'
|
||||
import { getWhiteListed } from './configureCors'
|
||||
|
||||
export const configureDomains = (app: Express) => {
|
||||
// const domains: string[] = []
|
||||
const domains = new Set<string>()
|
||||
const { ALLOWED_DOMAINS } = process.env
|
||||
|
||||
const allowedDomains = ALLOWED_DOMAINS?.trim().split(' ') ?? []
|
||||
|
||||
const whiteListed = getWhiteListed()
|
||||
|
||||
const combinedUrls = [...allowedDomains, ...whiteListed]
|
||||
combinedUrls
|
||||
.filter((domainName) => !!domainName)
|
||||
.forEach((url) => {
|
||||
try {
|
||||
const domain = new URL(url)
|
||||
domains.add(domain.hostname)
|
||||
} catch (_) {}
|
||||
})
|
||||
|
||||
if (domains.size) {
|
||||
process.allowedDomains = [...domains]
|
||||
console.log('Allowed Domain(s):', process.allowedDomains)
|
||||
app.use(checkDomain)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Express } from 'express'
|
||||
import { Express, CookieOptions } from 'express'
|
||||
import mongoose from 'mongoose'
|
||||
import session from 'express-session'
|
||||
import MongoStore from 'connect-mongo'
|
||||
|
||||
import { ModeType } from '../utils'
|
||||
import { cookieOptions } from '../app'
|
||||
import { ModeType, ProtocolType } from '../utils'
|
||||
|
||||
export const configureExpressSession = (app: Express) => {
|
||||
const { MODE } = process.env
|
||||
@@ -19,6 +18,15 @@ export const configureExpressSession = (app: Express) => {
|
||||
})
|
||||
}
|
||||
|
||||
const { PROTOCOL } = process.env
|
||||
const cookieOptions: CookieOptions = {
|
||||
secure: PROTOCOL === ProtocolType.HTTPS,
|
||||
httpOnly: true,
|
||||
sameSite: PROTOCOL === ProtocolType.HTTPS ? 'none' : undefined,
|
||||
maxAge: 24 * 60 * 60 * 1000, // 24 hours
|
||||
domain: 'sas.4gl.io'
|
||||
}
|
||||
|
||||
app.use(
|
||||
session({
|
||||
secret: process.secrets.SESSION_SECRET,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from './configureCors'
|
||||
export * from './configureDomains'
|
||||
export * from './configureExpressSession'
|
||||
export * from './configureLogger'
|
||||
export * from './configureSecurity'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import path from 'path'
|
||||
import express, { ErrorRequestHandler, CookieOptions } from 'express'
|
||||
import express, { ErrorRequestHandler } from 'express'
|
||||
import cookieParser from 'cookie-parser'
|
||||
import dotenv from 'dotenv'
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
getWebBuildFolder,
|
||||
instantiateLogger,
|
||||
loadAppStreamConfig,
|
||||
ProtocolType,
|
||||
ReturnCode,
|
||||
setProcessVariables,
|
||||
setupFolders,
|
||||
@@ -16,6 +15,7 @@ import {
|
||||
} from './utils'
|
||||
import {
|
||||
configureCors,
|
||||
configureDomains,
|
||||
configureExpressSession,
|
||||
configureLogger,
|
||||
configureSecurity
|
||||
@@ -29,15 +29,6 @@ if (verifyEnvVariables()) process.exit(ReturnCode.InvalidEnv)
|
||||
|
||||
const app = express()
|
||||
|
||||
const { PROTOCOL } = process.env
|
||||
|
||||
export const cookieOptions: CookieOptions = {
|
||||
secure: PROTOCOL === ProtocolType.HTTPS,
|
||||
httpOnly: true,
|
||||
sameSite: PROTOCOL === ProtocolType.HTTPS ? 'none' : undefined,
|
||||
maxAge: 24 * 60 * 60 * 1000 // 24 hours
|
||||
}
|
||||
|
||||
const onError: ErrorRequestHandler = (err, req, res, next) => {
|
||||
console.error(err.stack)
|
||||
res.status(500).send('Something broke!')
|
||||
@@ -58,6 +49,11 @@ export default setProcessVariables().then(async () => {
|
||||
***********************************/
|
||||
configureCors(app)
|
||||
|
||||
/***********************************
|
||||
* Allowed Domains *
|
||||
***********************************/
|
||||
configureDomains(app)
|
||||
|
||||
/***********************************
|
||||
* DB Connection & *
|
||||
* Express Sessions *
|
||||
|
||||
17
api/src/middlewares/checkDomain.ts
Normal file
17
api/src/middlewares/checkDomain.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { RequestHandler } from 'express'
|
||||
|
||||
export const checkDomain: RequestHandler = (req, res, next) => {
|
||||
const { allowedDomains } = process
|
||||
|
||||
// pass if no allowed domain is specified
|
||||
if (!allowedDomains.length) return next()
|
||||
|
||||
if (allowedDomains.includes(req.hostname)) return next()
|
||||
|
||||
console.log('allowedDomains', allowedDomains)
|
||||
console.log('hostname not allowed', req.hostname)
|
||||
res.writeHead(404, {
|
||||
'Content-Type': 'text/plain'
|
||||
})
|
||||
return res.end('Not found')
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from './authenticateToken'
|
||||
export * from './authorize'
|
||||
export * from './checkDomain'
|
||||
export * from './csrfProtection'
|
||||
export * from './desktop'
|
||||
export * from './verifyAdmin'
|
||||
|
||||
1
api/src/types/system/process.d.ts
vendored
1
api/src/types/system/process.d.ts
vendored
@@ -12,5 +12,6 @@ declare namespace NodeJS {
|
||||
logger: import('@sasjs/utils/logger').Logger
|
||||
runTimes: import('../../utils').RunTimeType[]
|
||||
secrets: import('../../model/Configuration').ConfigurationType
|
||||
allowedDomains: string[]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ const verifyRUN_TIMES = (): string[] => {
|
||||
return errors
|
||||
}
|
||||
|
||||
const verifyExecutablePaths = () => {
|
||||
const verifyExecutablePaths = (): string[] => {
|
||||
const errors: string[] = []
|
||||
const { RUN_TIMES, SAS_PATH, NODE_PATH, PYTHON_PATH, R_PATH, MODE } =
|
||||
process.env
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"target": "ES6",
|
||||
"module": "commonjs",
|
||||
"rootDir": "./",
|
||||
"outDir": "./build",
|
||||
|
||||
8105
web/package-lock.json
generated
8105
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -3,8 +3,8 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "webpack-dev-server --config webpack.dev.ts --hot",
|
||||
"build": "webpack --config webpack.prod.ts"
|
||||
"start": "vite serve --port 3000",
|
||||
"build": "vite build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.4.1",
|
||||
@@ -30,38 +30,21 @@
|
||||
"react-toastify": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.16.0",
|
||||
"@babel/node": "^7.16.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.16.0",
|
||||
"@babel/preset-env": "^7.16.4",
|
||||
"@babel/preset-react": "^7.16.0",
|
||||
"@babel/preset-typescript": "^7.16.0",
|
||||
"@types/dotenv-webpack": "^7.0.3",
|
||||
"@types/prismjs": "^1.16.6",
|
||||
"@types/react": "^17.0.37",
|
||||
"@types/react-copy-to-clipboard": "^5.0.2",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"@types/react-router-dom": "^5.3.1",
|
||||
"babel-loader": "^8.2.3",
|
||||
"babel-plugin-prismjs": "^2.1.0",
|
||||
"copy-webpack-plugin": "^10.0.0",
|
||||
"css-loader": "^6.5.1",
|
||||
"dotenv-webpack": "^7.1.0",
|
||||
"@vitejs/plugin-react": "^2.1.0",
|
||||
"eslint": "^8.5.0",
|
||||
"eslint-config-react-app": "^7.0.0",
|
||||
"eslint-webpack-plugin": "^3.1.1",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "5.5.0",
|
||||
"path": "0.12.7",
|
||||
"prettier": "^2.4.1",
|
||||
"sass": "^1.44.0",
|
||||
"sass-loader": "^12.3.0",
|
||||
"style-loader": "^3.3.1",
|
||||
"ts-loader": "^9.2.6",
|
||||
"typescript": "^4.5.2",
|
||||
"webpack": "5.64.3",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-dev-server": "4.7.4"
|
||||
"vite": "^3.1.4",
|
||||
"vite-plugin-env-compatible": "^1.1.1",
|
||||
"vite-plugin-html": "^3.2.0",
|
||||
"vite-plugin-monaco-editor": "^1.1.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
|
||||
@@ -35,5 +35,6 @@
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
<script type="module" src="/src/index.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
17
web/vite.config.js
Normal file
17
web/vite.config.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import { createHtmlPlugin } from 'vite-plugin-html'
|
||||
import envCompatible from 'vite-plugin-env-compatible'
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
outDir: './build'
|
||||
},
|
||||
plugins: [
|
||||
react(),
|
||||
createHtmlPlugin({
|
||||
template: './src/index.html'
|
||||
}),
|
||||
envCompatible({ prefix: '' })
|
||||
]
|
||||
})
|
||||
Reference in New Issue
Block a user