mirror of
https://github.com/sasjs/server.git
synced 2026-01-14 17:30:05 +00:00
chore: code fixes API + web
This commit is contained in:
@@ -5,7 +5,7 @@ import {
|
|||||||
fetchLatestAutoExec,
|
fetchLatestAutoExec,
|
||||||
ModeType,
|
ModeType,
|
||||||
verifyTokenInDB,
|
verifyTokenInDB,
|
||||||
getAuthorizedRoutes
|
isAuthorizingRoute
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { desktopUser } from './desktop'
|
import { desktopUser } from './desktop'
|
||||||
import { authorize } from './authorize'
|
import { authorize } from './authorize'
|
||||||
@@ -21,9 +21,7 @@ export const authenticateAccessToken: RequestHandler = async (
|
|||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
|
|
||||||
const authorizedRoutes = getAuthorizedRoutes()
|
const nextFunction = isAuthorizingRoute(req)
|
||||||
const uri = req.baseUrl + req.path
|
|
||||||
const nextFunction = authorizedRoutes.includes(uri)
|
|
||||||
? () => authorize(req, res, next)
|
? () => authorize(req, res, next)
|
||||||
: next
|
: next
|
||||||
|
|
||||||
|
|||||||
@@ -2,35 +2,35 @@ import { RequestHandler } from 'express'
|
|||||||
import User from '../model/User'
|
import User from '../model/User'
|
||||||
import Permission from '../model/Permission'
|
import Permission from '../model/Permission'
|
||||||
import { PermissionSetting } from '../controllers/permission'
|
import { PermissionSetting } from '../controllers/permission'
|
||||||
|
import { getUri } from '../utils'
|
||||||
|
|
||||||
export const authorize: RequestHandler = async (req, res, next) => {
|
export const authorize: RequestHandler = async (req, res, next) => {
|
||||||
let permission
|
const { user } = req
|
||||||
const user = req.user || req.session.user
|
|
||||||
if (user) {
|
|
||||||
// no need to check for permissions when user is admin
|
|
||||||
if (user.isAdmin) return next()
|
|
||||||
|
|
||||||
const dbUser = await User.findOne({ id: user.userId })
|
|
||||||
if (!dbUser) return res.sendStatus(401)
|
|
||||||
|
|
||||||
const uri = req.baseUrl + req.path
|
|
||||||
|
|
||||||
// find permission w.r.t user
|
|
||||||
permission = await Permission.findOne({ uri, user: dbUser._id })
|
|
||||||
|
|
||||||
if (permission) {
|
|
||||||
if (permission.setting === PermissionSetting.grant) return next()
|
|
||||||
else res.sendStatus(401)
|
|
||||||
}
|
|
||||||
|
|
||||||
// find permission w.r.t user's groups
|
|
||||||
for (const group of dbUser.groups) {
|
|
||||||
permission = await Permission.findOne({ uri, group })
|
|
||||||
if (permission && permission.setting === PermissionSetting.grant)
|
|
||||||
return next()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
return res.sendStatus(401)
|
return res.sendStatus(401)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// no need to check for permissions when user is admin
|
||||||
|
if (user.isAdmin) return next()
|
||||||
|
|
||||||
|
const dbUser = await User.findOne({ id: user.userId })
|
||||||
|
if (!dbUser) return res.sendStatus(401)
|
||||||
|
|
||||||
|
const uri = getUri(req)
|
||||||
|
|
||||||
|
// find permission w.r.t user
|
||||||
|
const permission = await Permission.findOne({ uri, user: dbUser._id })
|
||||||
|
|
||||||
|
if (permission) {
|
||||||
|
if (permission.setting === PermissionSetting.grant) return next()
|
||||||
|
else return res.sendStatus(401)
|
||||||
|
}
|
||||||
|
|
||||||
|
// find permission w.r.t user's groups
|
||||||
|
for (const group of dbUser.groups) {
|
||||||
|
const groupPermission = await Permission.findOne({ uri, group })
|
||||||
|
if (groupPermission?.setting === PermissionSetting.grant) return next()
|
||||||
|
}
|
||||||
return res.sendStatus(401)
|
return res.sendStatus(401)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import express, { Request } from 'express'
|
import express, { Request } from 'express'
|
||||||
import { authorize } from '../../middlewares/authorize'
|
import { authenticateAccessToken } from '../../middlewares'
|
||||||
import { folderExists } from '@sasjs/utils'
|
import { folderExists } from '@sasjs/utils'
|
||||||
|
|
||||||
import { addEntryToAppStreamConfig, getFilesFolder } from '../../utils'
|
import { addEntryToAppStreamConfig, getFilesFolder } from '../../utils'
|
||||||
@@ -10,7 +10,7 @@ const appStreams: { [key: string]: string } = {}
|
|||||||
|
|
||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
router.get('/', authorize, async (req, res) => {
|
router.get('/', authenticateAccessToken, async (req, res) => {
|
||||||
const content = appStreamHtml(process.appStreamConfig)
|
const content = appStreamHtml(process.appStreamConfig)
|
||||||
|
|
||||||
res.cookie('XSRF-TOKEN', req.csrfToken())
|
res.cookie('XSRF-TOKEN', req.csrfToken())
|
||||||
@@ -67,7 +67,7 @@ export const publishAppStream = async (
|
|||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
router.get(`/*`, authorize, function (req: Request, res, next) {
|
router.get(`/*`, authenticateAccessToken, function (req: Request, res, next) {
|
||||||
const reqPath = req.path.replace(/^\//, '')
|
const reqPath = req.path.replace(/^\//, '')
|
||||||
|
|
||||||
// Redirecting to url with trailing slash for appStream base URL only
|
// Redirecting to url with trailing slash for appStream base URL only
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
export const getAuthorizedRoutes = () => {
|
import { Request } from 'express'
|
||||||
const streamingApps = Object.keys(process.appStreamConfig)
|
|
||||||
const streamingAppsRoutes = streamingApps.map((app) => `/AppStream/${app}`)
|
|
||||||
return [...StaticAuthorizedRoutes, ...streamingAppsRoutes]
|
|
||||||
}
|
|
||||||
|
|
||||||
const StaticAuthorizedRoutes = [
|
const StaticAuthorizedRoutes = [
|
||||||
'/AppStream',
|
'/AppStream',
|
||||||
@@ -15,3 +11,21 @@ const StaticAuthorizedRoutes = [
|
|||||||
'/SASjsApi/drive/fileTree',
|
'/SASjsApi/drive/fileTree',
|
||||||
'/SASjsApi/permission'
|
'/SASjsApi/permission'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export const getAuthorizedRoutes = () => {
|
||||||
|
const streamingApps = Object.keys(process.appStreamConfig)
|
||||||
|
const streamingAppsRoutes = streamingApps.map((app) => `/AppStream/${app}`)
|
||||||
|
return [...StaticAuthorizedRoutes, ...streamingAppsRoutes]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getUri = (req: Request) => {
|
||||||
|
const { baseUrl, path: reqPath } = req
|
||||||
|
|
||||||
|
const appStream = reqPath.split('/')[1]
|
||||||
|
|
||||||
|
// removing trailing slash of URLs
|
||||||
|
return (baseUrl + '/' + appStream).replace(/\/$/, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isAuthorizingRoute = (req: Request): boolean =>
|
||||||
|
getAuthorizedRoutes().includes(getUri(req))
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npx webpack-dev-server --config webpack.dev.ts --hot",
|
"start": "webpack-dev-server --config webpack.dev.ts --hot",
|
||||||
"build": "npx webpack --config webpack.prod.ts"
|
"build": "webpack --config webpack.prod.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.4.1",
|
"@emotion/react": "^11.4.1",
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const Login = () => {
|
|||||||
username,
|
username,
|
||||||
password
|
password
|
||||||
}).catch((err: any) => {
|
}).catch((err: any) => {
|
||||||
setErrorMessage(err.response.data)
|
setErrorMessage(err.response?.data || err.toString())
|
||||||
return {}
|
return {}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, Dispatch, SetStateAction } from 'react'
|
import React, { useState, Dispatch, SetStateAction, useEffect } from 'react'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Grid,
|
Grid,
|
||||||
@@ -38,6 +38,10 @@ const UpdatePermissionModal = ({
|
|||||||
}: UpdatePermissionModalProps) => {
|
}: UpdatePermissionModalProps) => {
|
||||||
const [permissionSetting, setPermissionSetting] = useState('Grant')
|
const [permissionSetting, setPermissionSetting] = useState('Grant')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (permission) setPermissionSetting(permission.setting)
|
||||||
|
}, [permission])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BootstrapDialog onClose={() => handleOpen(false)} open={open}>
|
<BootstrapDialog onClose={() => handleOpen(false)} open={open}>
|
||||||
<BootstrapDialogTitle
|
<BootstrapDialogTitle
|
||||||
|
|||||||
Reference in New Issue
Block a user