From 0b759a5594f8bf97b0034e2c5109f58d64c67d3c Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Tue, 5 Jul 2022 02:34:33 +0500 Subject: [PATCH] chore: code fixes API + web --- api/src/middlewares/authenticateToken.ts | 6 +-- api/src/middlewares/authorize.ts | 50 +++++++++---------- api/src/routes/appStream/index.ts | 6 +-- api/src/utils/getAuthorizedRoutes.ts | 24 +++++++-- web/package.json | 4 +- web/src/components/login.tsx | 2 +- .../Settings/updatePermissionModal.tsx | 6 ++- 7 files changed, 57 insertions(+), 41 deletions(-) diff --git a/api/src/middlewares/authenticateToken.ts b/api/src/middlewares/authenticateToken.ts index e368384..b53b83c 100644 --- a/api/src/middlewares/authenticateToken.ts +++ b/api/src/middlewares/authenticateToken.ts @@ -5,7 +5,7 @@ import { fetchLatestAutoExec, ModeType, verifyTokenInDB, - getAuthorizedRoutes + isAuthorizingRoute } from '../utils' import { desktopUser } from './desktop' import { authorize } from './authorize' @@ -21,9 +21,7 @@ export const authenticateAccessToken: RequestHandler = async ( return next() } - const authorizedRoutes = getAuthorizedRoutes() - const uri = req.baseUrl + req.path - const nextFunction = authorizedRoutes.includes(uri) + const nextFunction = isAuthorizingRoute(req) ? () => authorize(req, res, next) : next diff --git a/api/src/middlewares/authorize.ts b/api/src/middlewares/authorize.ts index 124b332..20c85fa 100644 --- a/api/src/middlewares/authorize.ts +++ b/api/src/middlewares/authorize.ts @@ -2,35 +2,35 @@ import { RequestHandler } from 'express' import User from '../model/User' import Permission from '../model/Permission' import { PermissionSetting } from '../controllers/permission' +import { getUri } from '../utils' export const authorize: RequestHandler = async (req, res, next) => { - let permission - 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() - } + const { user } = req + if (!user) { 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) } diff --git a/api/src/routes/appStream/index.ts b/api/src/routes/appStream/index.ts index 1152644..ca2e279 100644 --- a/api/src/routes/appStream/index.ts +++ b/api/src/routes/appStream/index.ts @@ -1,6 +1,6 @@ import path from 'path' import express, { Request } from 'express' -import { authorize } from '../../middlewares/authorize' +import { authenticateAccessToken } from '../../middlewares' import { folderExists } from '@sasjs/utils' import { addEntryToAppStreamConfig, getFilesFolder } from '../../utils' @@ -10,7 +10,7 @@ const appStreams: { [key: string]: string } = {} const router = express.Router() -router.get('/', authorize, async (req, res) => { +router.get('/', authenticateAccessToken, async (req, res) => { const content = appStreamHtml(process.appStreamConfig) res.cookie('XSRF-TOKEN', req.csrfToken()) @@ -67,7 +67,7 @@ export const publishAppStream = async ( return {} } -router.get(`/*`, authorize, function (req: Request, res, next) { +router.get(`/*`, authenticateAccessToken, function (req: Request, res, next) { const reqPath = req.path.replace(/^\//, '') // Redirecting to url with trailing slash for appStream base URL only diff --git a/api/src/utils/getAuthorizedRoutes.ts b/api/src/utils/getAuthorizedRoutes.ts index 7d63b9f..aafe4c4 100644 --- a/api/src/utils/getAuthorizedRoutes.ts +++ b/api/src/utils/getAuthorizedRoutes.ts @@ -1,8 +1,4 @@ -export const getAuthorizedRoutes = () => { - const streamingApps = Object.keys(process.appStreamConfig) - const streamingAppsRoutes = streamingApps.map((app) => `/AppStream/${app}`) - return [...StaticAuthorizedRoutes, ...streamingAppsRoutes] -} +import { Request } from 'express' const StaticAuthorizedRoutes = [ '/AppStream', @@ -15,3 +11,21 @@ const StaticAuthorizedRoutes = [ '/SASjsApi/drive/fileTree', '/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)) diff --git a/web/package.json b/web/package.json index a3a5898..8f6681d 100644 --- a/web/package.json +++ b/web/package.json @@ -3,8 +3,8 @@ "version": "0.1.0", "private": true, "scripts": { - "start": "npx webpack-dev-server --config webpack.dev.ts --hot", - "build": "npx webpack --config webpack.prod.ts" + "start": "webpack-dev-server --config webpack.dev.ts --hot", + "build": "webpack --config webpack.prod.ts" }, "dependencies": { "@emotion/react": "^11.4.1", diff --git a/web/src/components/login.tsx b/web/src/components/login.tsx index 706a714..c679a8d 100644 --- a/web/src/components/login.tsx +++ b/web/src/components/login.tsx @@ -22,7 +22,7 @@ const Login = () => { username, password }).catch((err: any) => { - setErrorMessage(err.response.data) + setErrorMessage(err.response?.data || err.toString()) return {} }) diff --git a/web/src/containers/Settings/updatePermissionModal.tsx b/web/src/containers/Settings/updatePermissionModal.tsx index 796017d..55d92de 100644 --- a/web/src/containers/Settings/updatePermissionModal.tsx +++ b/web/src/containers/Settings/updatePermissionModal.tsx @@ -1,4 +1,4 @@ -import React, { useState, Dispatch, SetStateAction } from 'react' +import React, { useState, Dispatch, SetStateAction, useEffect } from 'react' import { Button, Grid, @@ -38,6 +38,10 @@ const UpdatePermissionModal = ({ }: UpdatePermissionModalProps) => { const [permissionSetting, setPermissionSetting] = useState('Grant') + useEffect(() => { + if (permission) setPermissionSetting(permission.setting) + }, [permission]) + return ( handleOpen(false)} open={open}>