1
0
mirror of https://github.com/sasjs/server.git synced 2025-12-12 20:04:36 +00:00

Compare commits

..

7 Commits

Author SHA1 Message Date
semantic-release-bot
73c81a45dc chore(release): 0.3.3 [skip ci]
## [0.3.3](https://github.com/sasjs/server/compare/v0.3.2...v0.3.3) (2022-05-30)

### Bug Fixes

* usage of autoexec API in DESKTOP mode ([12d424a](12d424acce))
2022-05-30 12:18:45 +00:00
Saad Jutt
12d424acce fix: usage of autoexec API in DESKTOP mode 2022-05-30 17:12:17 +05:00
Saad Jutt
414fb19de3 chore: code changes 2022-05-30 00:32:05 +05:00
semantic-release-bot
cfddf1fb0c chore(release): 0.3.2 [skip ci]
## [0.3.2](https://github.com/sasjs/server/compare/v0.3.1...v0.3.2) (2022-05-27)

### Bug Fixes

* **web:** ability to use get/patch User API in desktop mode. ([2c259fe](2c259fe1de))
2022-05-27 19:43:00 +00:00
Muhammad Saad
1f483b1afc Merge pull request #180 from sasjs/desktop-autoexec
fix(web): ability to use get/patch User API in desktop mode.
2022-05-27 12:39:17 -07:00
Saad Jutt
0470239ef1 chore: quick fix 2022-05-27 17:35:58 +05:00
Saad Jutt
2c259fe1de fix(web): ability to use get/patch User API in desktop mode. 2022-05-27 17:01:14 +05:00
11 changed files with 101 additions and 27 deletions

View File

@@ -1,3 +1,17 @@
## [0.3.3](https://github.com/sasjs/server/compare/v0.3.2...v0.3.3) (2022-05-30)
### Bug Fixes
* usage of autoexec API in DESKTOP mode ([12d424a](https://github.com/sasjs/server/commit/12d424acce8108a6f53aefbac01fddcdc5efb48f))
## [0.3.2](https://github.com/sasjs/server/compare/v0.3.1...v0.3.2) (2022-05-27)
### Bug Fixes
* **web:** ability to use get/patch User API in desktop mode. ([2c259fe](https://github.com/sasjs/server/commit/2c259fe1de95d84e6929e311aaa6b895e66b42a3))
## [0.3.1](https://github.com/sasjs/server/compare/v0.3.0...v0.3.1) (2022-05-26) ## [0.3.1](https://github.com/sasjs/server/compare/v0.3.0...v0.3.1) (2022-05-26)

View File

@@ -96,7 +96,7 @@
}, },
"nodemonConfig": { "nodemonConfig": {
"ignore": [ "ignore": [
"tmp/**/*" "sasjs_root/**/*"
] ]
} }
} }

View File

@@ -3,12 +3,11 @@ import { Request, Security, Route, Tags, Post, Body } from 'tsoa'
import { ExecuteReturnJson, ExecutionController } from './internal' import { ExecuteReturnJson, ExecutionController } from './internal'
import { ExecuteReturnJsonResponse } from '.' import { ExecuteReturnJsonResponse } from '.'
import { import {
getDesktopUserAutoExecPath,
getPreProgramVariables, getPreProgramVariables,
getUserAutoExec,
ModeType, ModeType,
parseLogToArray parseLogToArray
} from '../utils' } from '../utils'
import { readFile } from '@sasjs/utils'
interface ExecuteSASCodePayload { interface ExecuteSASCodePayload {
/** /**
@@ -43,7 +42,7 @@ const executeSASCode = async (
const userAutoExec = const userAutoExec =
process.env.MODE === ModeType.Server process.env.MODE === ModeType.Server
? user?.autoExec ? user?.autoExec
: await readFile(getDesktopUserAutoExecPath()) : await getUserAutoExec()
try { try {
const { webout, log, httpHeaders } = const { webout, log, httpHeaders } =

View File

@@ -14,8 +14,10 @@ import {
Hidden, Hidden,
Request Request
} from 'tsoa' } from 'tsoa'
import { desktopUser } from '../middlewares'
import User, { UserPayload } from '../model/User' import User, { UserPayload } from '../model/User'
import { getUserAutoExec, updateUserAutoExec, ModeType } from '../utils'
export interface UserResponse { export interface UserResponse {
id: number id: number
@@ -86,6 +88,10 @@ export class UserController {
@Request() req: express.Request, @Request() req: express.Request,
@Path() userId: number @Path() userId: number
): Promise<UserDetailsResponse> { ): Promise<UserDetailsResponse> {
const { MODE } = process.env
if (MODE === ModeType.Desktop) return getDesktopAutoExec()
const { user } = req const { user } = req
const getAutoExec = user!.isAdmin || user!.userId == userId const getAutoExec = user!.isAdmin || user!.userId == userId
return getUser(userId, getAutoExec) return getUser(userId, getAutoExec)
@@ -108,6 +114,11 @@ export class UserController {
@Path() userId: number, @Path() userId: number,
@Body() body: UserPayload @Body() body: UserPayload
): Promise<UserDetailsResponse> { ): Promise<UserDetailsResponse> {
const { MODE } = process.env
if (MODE === ModeType.Desktop)
return updateDesktopAutoExec(body.autoExec ?? '')
return updateUser(userId, body) 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 ( const updateUser = async (
id: number, id: number,
data: Partial<UserPayload> data: Partial<UserPayload>
@@ -216,6 +235,15 @@ const updateUser = async (
} }
} }
const updateDesktopAutoExec = async (autoExec: string) => {
await updateUserAutoExec(autoExec)
return {
...desktopUser,
id: desktopUser.userId,
autoExec
}
}
const deleteUser = async ( const deleteUser = async (
id: number, id: number,
isAdmin: boolean, isAdmin: boolean,

View File

@@ -1,15 +1,22 @@
import { RequestHandler, Request, Response, NextFunction } from 'express' import { RequestHandler, Request, Response, NextFunction } from 'express'
import jwt from 'jsonwebtoken' import jwt from 'jsonwebtoken'
import { csrfProtection } from '../app' import { csrfProtection } from '../app'
import { fetchLatestAutoExec, verifyTokenInDB } from '../utils' import { fetchLatestAutoExec, ModeType, verifyTokenInDB } from '../utils'
import { desktopUser } from './desktop'
export const authenticateAccessToken: RequestHandler = async ( export const authenticateAccessToken: RequestHandler = async (
req, req,
res, res,
next next
) => { ) => {
const { MODE } = process.env
if (MODE === ModeType.Desktop) {
req.user = desktopUser
return next()
}
// if request is coming from web and has valid session // 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?.loggedIn) {
if (req.session.user) { if (req.session.user) {
const user = await fetchLatestAutoExec(req.session.user) const user = await fetchLatestAutoExec(req.session.user)

View File

@@ -1,20 +1,36 @@
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) => { export const desktopRestrict: RequestHandler = (req, res, next) => {
const { MODE } = process.env const { MODE } = process.env
if (MODE?.trim() !== 'server')
if (MODE === ModeType.Desktop) {
if (!reqAllowedInDesktopMode(req))
return res.status(403).send('Not Allowed while in Desktop Mode.') return res.status(403).send('Not Allowed while in Desktop Mode.')
}
next() next()
} }
export const desktopUsername: RequestHandler = (req, res, next) => {
const { MODE } = process.env export const desktopUser: RequestUser = {
if (MODE?.trim() !== 'server')
return res.status(200).send({
userId: 12345, userId: 12345,
clientId: 'desktop_app',
username: 'DESKTOPusername', username: 'DESKTOPusername',
displayName: 'DESKTOP User' displayName: 'DESKTOP User',
}) isAdmin: true,
isActive: true
next()
} }

View File

@@ -5,7 +5,6 @@ import swaggerUi from 'swagger-ui-express'
import { import {
authenticateAccessToken, authenticateAccessToken,
desktopRestrict, desktopRestrict,
desktopUsername,
verifyAdmin verifyAdmin
} from '../../middlewares' } from '../../middlewares'
@@ -22,7 +21,7 @@ import sessionRouter from './session'
const router = express.Router() const router = express.Router()
router.use('/info', infoRouter) router.use('/info', infoRouter)
router.use('/session', desktopUsername, authenticateAccessToken, sessionRouter) router.use('/session', authenticateAccessToken, sessionRouter)
router.use('/auth', desktopRestrict, authRouter) router.use('/auth', desktopRestrict, authRouter)
router.use( router.use(
'/client', '/client',

View File

@@ -47,10 +47,11 @@ stpRouter.post(
query?._program query?._program
) )
if (response instanceof Buffer) { // TODO: investigate if this code is required
res.writeHead(200, (req as any).sasHeaders) // if (response instanceof Buffer) {
return res.end(response) // res.writeHead(200, (req as any).sasHeaders)
} // return res.end(response)
// }
res.send(response) res.send(response)
} catch (err: any) { } catch (err: any) {

View File

@@ -1,6 +1,6 @@
import express from 'express' import express from 'express'
import { WebController } from '../../controllers/web' import { WebController } from '../../controllers/web'
import { authenticateAccessToken } from '../../middlewares' import { authenticateAccessToken, desktopRestrict } from '../../middlewares'
import { authorizeValidation, loginWebValidation } from '../../utils' import { authorizeValidation, loginWebValidation } from '../../utils'
const webRouter = express.Router() const webRouter = express.Router()
@@ -19,7 +19,7 @@ webRouter.get('/', async (req, res) => {
} }
}) })
webRouter.post('/SASLogon/login', async (req, res) => { webRouter.post('/SASLogon/login', desktopRestrict, async (req, res) => {
const { error, value: body } = loginWebValidation(req.body) const { error, value: body } = loginWebValidation(req.body)
if (error) return res.status(400).send(error.details[0].message) if (error) return res.status(400).send(error.details[0].message)
@@ -33,6 +33,7 @@ webRouter.post('/SASLogon/login', async (req, res) => {
webRouter.post( webRouter.post(
'/SASLogon/authorize', '/SASLogon/authorize',
desktopRestrict,
authenticateAccessToken, authenticateAccessToken,
async (req, res) => { async (req, res) => {
const { error, value: body } = authorizeValidation(req.body) const { error, value: body } = authorizeValidation(req.body)
@@ -47,7 +48,7 @@ webRouter.post(
} }
) )
webRouter.get('/logout', async (req, res) => { webRouter.get('/logout', desktopRestrict, async (req, res) => {
try { try {
await controller.logout(req) await controller.logout(req)
res.status(200).send('OK!') res.status(200).send('OK!')

View File

@@ -0,0 +1,8 @@
import { createFile, readFile } from '@sasjs/utils'
import { getDesktopUserAutoExecPath } from './file'
export const getUserAutoExec = async (): Promise<string> =>
readFile(getDesktopUserAutoExecPath())
export const updateUserAutoExec = async (autoExecContent: string) =>
createFile(getDesktopUserAutoExecPath(), autoExecContent)

View File

@@ -1,6 +1,7 @@
export * from './appStreamConfig' export * from './appStreamConfig'
export * from './connectDB' export * from './connectDB'
export * from './copySASjsCore' export * from './copySASjsCore'
export * from './desktopAutoExec'
export * from './extractHeaders' export * from './extractHeaders'
export * from './file' export * from './file'
export * from './generateAccessToken' export * from './generateAccessToken'