From 2c259fe1de95d84e6929e311aaa6b895e66b42a3 Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Fri, 27 May 2022 17:01:14 +0500 Subject: [PATCH 1/2] fix(web): ability to use get/patch User API in desktop mode. --- api/src/controllers/code.ts | 5 ++- api/src/controllers/user.ts | 28 +++++++++++++++++ api/src/middlewares/authenticateToken.ts | 11 +++++-- api/src/middlewares/desktop.ts | 40 ++++++++++++++++++------ api/src/utils/desktopAutoExec.ts | 8 +++++ api/src/utils/index.ts | 1 + 6 files changed, 79 insertions(+), 14 deletions(-) create mode 100644 api/src/utils/desktopAutoExec.ts diff --git a/api/src/controllers/code.ts b/api/src/controllers/code.ts index a102330..a4b1d74 100644 --- a/api/src/controllers/code.ts +++ b/api/src/controllers/code.ts @@ -3,12 +3,11 @@ import { Request, Security, Route, Tags, Post, Body } from 'tsoa' import { ExecuteReturnJson, ExecutionController } from './internal' import { ExecuteReturnJsonResponse } from '.' import { - getDesktopUserAutoExecPath, getPreProgramVariables, + getUserAutoExec, ModeType, parseLogToArray } from '../utils' -import { readFile } from '@sasjs/utils' interface ExecuteSASCodePayload { /** @@ -43,7 +42,7 @@ const executeSASCode = async ( const userAutoExec = process.env.MODE === ModeType.Server ? user?.autoExec - : await readFile(getDesktopUserAutoExecPath()) + : await getUserAutoExec() try { const { webout, log, httpHeaders } = diff --git a/api/src/controllers/user.ts b/api/src/controllers/user.ts index 0c43b3a..cfbce9d 100644 --- a/api/src/controllers/user.ts +++ b/api/src/controllers/user.ts @@ -14,8 +14,10 @@ import { Hidden, Request } from 'tsoa' +import { desktopUser } from '../middlewares' import User, { UserPayload } from '../model/User' +import { getUserAutoExec, updateUserAutoExec, ModeType } from '../utils' export interface UserResponse { id: number @@ -86,6 +88,10 @@ export class UserController { @Request() req: express.Request, @Path() userId: number ): Promise { + const { MODE } = process.env + + if (MODE === ModeType.Desktop) return getDesktopAutoExec() + const { user } = req const getAutoExec = user!.isAdmin || user!.userId == userId return getUser(userId, getAutoExec) @@ -108,6 +114,11 @@ export class UserController { @Path() userId: number, @Body() body: UserPayload ): Promise { + const { MODE } = process.env + + if (MODE === ModeType.Desktop) + return updateDesktopAutoExec(body.autoExec ?? '') + return updateUser(userId, body) } @@ -181,6 +192,14 @@ const getUser = async ( } } +const getDesktopAutoExec = async () => { + return { + ...desktopUser, + id: desktopUser.userId, + autoExec: await getUserAutoExec() + } +} + const updateUser = async ( id: number, data: Partial @@ -216,6 +235,15 @@ const updateUser = async ( } } +const updateDesktopAutoExec = async (autoExec: string) => { + await updateUserAutoExec(autoExec) + return { + ...desktopUser, + id: desktopUser.userId, + autoExec + } +} + const deleteUser = async ( id: number, isAdmin: boolean, diff --git a/api/src/middlewares/authenticateToken.ts b/api/src/middlewares/authenticateToken.ts index 032972f..ced94f9 100644 --- a/api/src/middlewares/authenticateToken.ts +++ b/api/src/middlewares/authenticateToken.ts @@ -1,15 +1,22 @@ import { RequestHandler, Request, Response, NextFunction } from 'express' import jwt from 'jsonwebtoken' import { csrfProtection } from '../app' -import { fetchLatestAutoExec, verifyTokenInDB } from '../utils' +import { fetchLatestAutoExec, ModeType, verifyTokenInDB } from '../utils' +import { desktopUser } from './desktop' export const authenticateAccessToken: RequestHandler = async ( req, res, next ) => { + const { MODE } = process.env + if (MODE === ModeType.Server) { + req.user = desktopUser + return next() + } + // if request is coming from web and has valid session - // we can validate the request and check for CSRF Token + // it can be validated. if (req.session?.loggedIn) { if (req.session.user) { const user = await fetchLatestAutoExec(req.session.user) diff --git a/api/src/middlewares/desktop.ts b/api/src/middlewares/desktop.ts index 8a6f80f..ed94c87 100644 --- a/api/src/middlewares/desktop.ts +++ b/api/src/middlewares/desktop.ts @@ -1,20 +1,42 @@ -import { RequestHandler } from 'express' +import { RequestHandler, Request } from 'express' +import { RequestUser } from '../types' +import { ModeType } from '../utils' + +const regexUser = /^\/SASjsApi\/user\/[0-9]*$/ // /SASjsApi/user/1 + +const allowedInDesktopMode: { [key: string]: RegExp[] } = { + GET: [regexUser], + PATCH: [regexUser] +} + +const reqAllowedInDesktopMode = (request: Request): boolean => { + const { method, originalUrl: url } = request + + return !!allowedInDesktopMode[method]?.find((urlRegex) => urlRegex.test(url)) +} export const desktopRestrict: RequestHandler = (req, res, next) => { const { MODE } = process.env - if (MODE?.trim() !== 'server') - return res.status(403).send('Not Allowed while in Desktop Mode.') + + if (MODE === ModeType.Desktop) { + if (!reqAllowedInDesktopMode(req)) + return res.status(403).send('Not Allowed while in Desktop Mode.') + } next() } export const desktopUsername: RequestHandler = (req, res, next) => { const { MODE } = process.env - if (MODE?.trim() !== 'server') - return res.status(200).send({ - userId: 12345, - username: 'DESKTOPusername', - displayName: 'DESKTOP User' - }) + if (MODE === ModeType.Desktop) return res.status(200).send(desktopUser) next() } + +export const desktopUser: RequestUser = { + userId: 12345, + clientId: 'desktop_app', + username: 'DESKTOPusername', + displayName: 'DESKTOP User', + isAdmin: true, + isActive: true +} diff --git a/api/src/utils/desktopAutoExec.ts b/api/src/utils/desktopAutoExec.ts new file mode 100644 index 0000000..e68159c --- /dev/null +++ b/api/src/utils/desktopAutoExec.ts @@ -0,0 +1,8 @@ +import { createFile, readFile } from '@sasjs/utils' +import { getDesktopUserAutoExecPath } from './file' + +export const getUserAutoExec = async (): Promise => + readFile(getDesktopUserAutoExecPath()) + +export const updateUserAutoExec = async (autoExecContent: string) => + createFile(getDesktopUserAutoExecPath(), autoExecContent) diff --git a/api/src/utils/index.ts b/api/src/utils/index.ts index 16980ec..4bb2022 100644 --- a/api/src/utils/index.ts +++ b/api/src/utils/index.ts @@ -1,6 +1,7 @@ export * from './appStreamConfig' export * from './connectDB' export * from './copySASjsCore' +export * from './desktopAutoExec' export * from './extractHeaders' export * from './file' export * from './generateAccessToken' From 0470239ef1f7e99ffe6336b856145aafe48d9301 Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Fri, 27 May 2022 17:35:58 +0500 Subject: [PATCH 2/2] chore: quick fix --- api/src/middlewares/authenticateToken.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/middlewares/authenticateToken.ts b/api/src/middlewares/authenticateToken.ts index ced94f9..90c7027 100644 --- a/api/src/middlewares/authenticateToken.ts +++ b/api/src/middlewares/authenticateToken.ts @@ -10,7 +10,7 @@ export const authenticateAccessToken: RequestHandler = async ( next ) => { const { MODE } = process.env - if (MODE === ModeType.Server) { + if (MODE === ModeType.Desktop) { req.user = desktopUser return next() }