mirror of
https://github.com/sasjs/server.git
synced 2025-12-10 19:34:34 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8065727b9b | ||
|
|
e1223ec3f8 | ||
|
|
1f89279264 |
@@ -2,6 +2,13 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||||
|
|
||||||
|
### [0.0.69](https://github.com/sasjs/server/compare/v0.0.68...v0.0.69) (2022-05-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **upload:** appStream uses CSRF + Session authentication ([1f89279](https://github.com/sasjs/server/commit/1f8927926405887f3d134c0a1dd6452ffa33876e))
|
||||||
|
|
||||||
### [0.0.68](https://github.com/sasjs/server/compare/v0.0.67...v0.0.68) (2022-05-02)
|
### [0.0.68](https://github.com/sasjs/server/compare/v0.0.67...v0.0.68) (2022-05-02)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
49
api/public/app-streams-script.js
Normal file
49
api/public/app-streams-script.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
const inputElement = document.getElementById('fileId')
|
||||||
|
|
||||||
|
document.getElementById('uploadButton').addEventListener('click', function () {
|
||||||
|
inputElement.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
inputElement.addEventListener(
|
||||||
|
'change',
|
||||||
|
function () {
|
||||||
|
const fileList = this.files /* now you can work with the file list */
|
||||||
|
|
||||||
|
updateFileUploadMessage('Requesting ...')
|
||||||
|
|
||||||
|
const file = fileList[0]
|
||||||
|
const formData = new FormData()
|
||||||
|
|
||||||
|
formData.append('file', file)
|
||||||
|
|
||||||
|
axios
|
||||||
|
.post('/SASjsApi/drive/deploy/upload', formData)
|
||||||
|
.then((res) => res.data)
|
||||||
|
.then((data) => {
|
||||||
|
return (
|
||||||
|
data.message +
|
||||||
|
'\nstreamServiceName: ' +
|
||||||
|
data.streamServiceName +
|
||||||
|
'\nrefreshing page once alert box closes.'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.then((message) => {
|
||||||
|
alert(message)
|
||||||
|
location.reload()
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
alert(error.response.data)
|
||||||
|
resetFileUpload()
|
||||||
|
updateFileUploadMessage('Upload New App')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
function updateFileUploadMessage(message) {
|
||||||
|
document.getElementById('uploadMessage').innerHTML = message
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetFileUpload() {
|
||||||
|
inputElement.value = null
|
||||||
|
}
|
||||||
3
api/public/axios.min.js
vendored
Normal file
3
api/public/axios.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -41,7 +41,16 @@ export const csrfProtection = csrf({ cookie: cookieOptions })
|
|||||||
/***********************************
|
/***********************************
|
||||||
* Handle security and origin *
|
* Handle security and origin *
|
||||||
***********************************/
|
***********************************/
|
||||||
app.use(helmet())
|
app.use(
|
||||||
|
helmet({
|
||||||
|
contentSecurityPolicy: {
|
||||||
|
directives: {
|
||||||
|
...helmet.contentSecurityPolicy.getDefaultDirectives(),
|
||||||
|
'script-src': ["'self'", "'unsafe-inline'"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
* Enabling CORS *
|
* Enabling CORS *
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ export class WebController {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Get('/')
|
@Get('/')
|
||||||
public async home(@Request() req: express.Request) {
|
public async home() {
|
||||||
return home(req)
|
return home()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,16 +44,13 @@ export class WebController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const home = async (req: express.Request) => {
|
const home = async () => {
|
||||||
const indexHtmlPath = path.join(getWebBuildFolderPath(), 'index.html')
|
const indexHtmlPath = path.join(getWebBuildFolderPath(), 'index.html')
|
||||||
|
|
||||||
// Attention! Cannot use fileExists here,
|
// Attention! Cannot use fileExists here,
|
||||||
// due to limitation after building executable
|
// due to limitation after building executable
|
||||||
const content = await readFile(indexHtmlPath)
|
const content = await readFile(indexHtmlPath)
|
||||||
|
|
||||||
req.res?.cookie('XSRF-TOKEN', req.csrfToken())
|
|
||||||
req.res?.setHeader('Content-Type', 'text/html')
|
|
||||||
|
|
||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { AppStreamConfig } from '../../types'
|
import { AppStreamConfig } from '../../types'
|
||||||
import { script } from './script'
|
|
||||||
import { style } from './style'
|
import { style } from './style'
|
||||||
|
|
||||||
const defaultAppLogo = '/sasjs-logo.svg'
|
const defaultAppLogo = '/sasjs-logo.svg'
|
||||||
@@ -39,6 +38,7 @@ export const appStreamHtml = (appStreamConfig: AppStreamConfig) => `
|
|||||||
<span id="uploadMessage">Upload New App</span>
|
<span id="uploadMessage">Upload New App</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
${script}
|
<script src="/axios.min.js"></script>
|
||||||
|
<script src="/app-streams-script.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>`
|
</html>`
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ import { appStreamHtml } from './appStreamHtml'
|
|||||||
|
|
||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
router.get('/', async (_, res) => {
|
router.get('/', async (req, res) => {
|
||||||
const content = appStreamHtml(process.appStreamConfig)
|
const content = appStreamHtml(process.appStreamConfig)
|
||||||
|
|
||||||
|
res.cookie('XSRF-TOKEN', req.csrfToken())
|
||||||
|
|
||||||
return res.send(content)
|
return res.send(content)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
export const script = `<script>
|
|
||||||
const inputElement = document.getElementById('fileId')
|
|
||||||
|
|
||||||
document
|
|
||||||
.getElementById('uploadButton')
|
|
||||||
.addEventListener('click', function () {
|
|
||||||
inputElement.click()
|
|
||||||
})
|
|
||||||
|
|
||||||
inputElement.addEventListener(
|
|
||||||
'change',
|
|
||||||
function () {
|
|
||||||
const fileList = this.files /* now you can work with the file list */
|
|
||||||
|
|
||||||
updateFileUploadMessage('Requesting ...')
|
|
||||||
|
|
||||||
const file = fileList[0]
|
|
||||||
const formData = new FormData()
|
|
||||||
|
|
||||||
formData.append('file', file)
|
|
||||||
fetch('/SASjsApi/drive/deploy/upload', {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData
|
|
||||||
})
|
|
||||||
.then(async (res) => {
|
|
||||||
const { status, ok } = res
|
|
||||||
if (status === 200 && ok) {
|
|
||||||
const data = await res.json()
|
|
||||||
return (
|
|
||||||
data.message +
|
|
||||||
'\\nstreamServiceName: ' +
|
|
||||||
data.streamServiceName +
|
|
||||||
'\\nrefreshing page once alert box closes.'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
throw await res.text()
|
|
||||||
})
|
|
||||||
.then((message) => {
|
|
||||||
alert(message)
|
|
||||||
location.reload()
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
alert(error)
|
|
||||||
resetFileUpload()
|
|
||||||
updateFileUploadMessage('Upload New App')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
false
|
|
||||||
)
|
|
||||||
|
|
||||||
function updateFileUploadMessage(message) {
|
|
||||||
document.getElementById('uploadMessage').innerHTML = message
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetFileUpload() {
|
|
||||||
inputElement.value = null
|
|
||||||
}
|
|
||||||
</script>`
|
|
||||||
@@ -4,14 +4,16 @@ import webRouter from './web'
|
|||||||
import apiRouter from './api'
|
import apiRouter from './api'
|
||||||
import appStreamRouter from './appStream'
|
import appStreamRouter from './appStream'
|
||||||
|
|
||||||
|
import { csrfProtection } from '../app'
|
||||||
|
|
||||||
export const setupRoutes = (app: Express) => {
|
export const setupRoutes = (app: Express) => {
|
||||||
app.use('/SASjsApi', apiRouter)
|
app.use('/SASjsApi', apiRouter)
|
||||||
|
|
||||||
app.use('/AppStream', function (req, res, next) {
|
app.use('/AppStream', csrfProtection, function (req, res, next) {
|
||||||
// this needs to be a function to hook on
|
// this needs to be a function to hook on
|
||||||
// whatever the current router is
|
// whatever the current router is
|
||||||
appStreamRouter(req, res, next)
|
appStreamRouter(req, res, next)
|
||||||
})
|
})
|
||||||
|
|
||||||
app.use('/', webRouter)
|
app.use('/', csrfProtection, webRouter)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import express from 'express'
|
import express from 'express'
|
||||||
import { csrfProtection } from '../../app'
|
|
||||||
import webRouter from './web'
|
import webRouter from './web'
|
||||||
|
|
||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
router.use(csrfProtection)
|
|
||||||
|
|
||||||
router.use('/', webRouter)
|
router.use('/', webRouter)
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ const controller = new WebController()
|
|||||||
|
|
||||||
webRouter.get('/', async (req, res) => {
|
webRouter.get('/', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const response = await controller.home(req)
|
const response = await controller.home()
|
||||||
|
|
||||||
|
res.cookie('XSRF-TOKEN', req.csrfToken())
|
||||||
|
|
||||||
return res.send(response)
|
return res.send(response)
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return res.send('Web Build is not present')
|
return res.send('Web Build is not present')
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"version": "0.0.68",
|
"version": "0.0.69",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"version": "0.0.68",
|
"version": "0.0.69",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "^2.3.1",
|
"prettier": "^2.3.1",
|
||||||
"standard-version": "^9.3.2"
|
"standard-version": "^9.3.2"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"version": "0.0.68",
|
"version": "0.0.69",
|
||||||
"description": "NodeJS wrapper for calling the SAS binary executable",
|
"description": "NodeJS wrapper for calling the SAS binary executable",
|
||||||
"repository": "https://github.com/sasjs/server",
|
"repository": "https://github.com/sasjs/server",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Reference in New Issue
Block a user