diff --git a/api/public/swagger.yaml b/api/public/swagger.yaml index 65b8c5a..83e67f2 100644 --- a/api/public/swagger.yaml +++ b/api/public/swagger.yaml @@ -982,6 +982,50 @@ paths: format: double type: number example: '6789' + /SASjsApi/run/code: + post: + operationId: RunSAS + responses: + '200': + description: Ok + content: + application/json: + schema: + type: string + description: 'Trigger a SAS program.' + summary: 'Run SAS Program, return raw content' + tags: + - RUN + security: + - + bearerAuth: [] + parameters: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RunSASPayload' + /SASjsApi/session: + get: + operationId: Session + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/UserResponse' + examples: + 'Example 1': + value: {id: 123, username: johnusername, displayName: John} + summary: 'Get session info (username).' + tags: + - Session + security: + - + bearerAuth: [] + parameters: [] /SASjsApi/stp/execute: get: operationId: ExecuteReturnRaw @@ -1037,50 +1081,6 @@ paths: application/json: schema: $ref: '#/components/schemas/ExecuteReturnJsonPayload' - /SASjsApi/stp/run: - post: - operationId: RunSAS - responses: - '200': - description: Ok - content: - application/json: - schema: - type: string - description: 'Trigger a SAS program.' - summary: 'Run SAS Program, return raw content' - tags: - - STP - security: - - - bearerAuth: [] - parameters: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/RunSASPayload' - /SASjsApi/session: - get: - operationId: Session - responses: - '200': - description: Ok - content: - application/json: - schema: - $ref: '#/components/schemas/UserResponse' - examples: - 'Example 1': - value: {id: 123, username: johnusername, displayName: John} - summary: 'Get session info (username).' - tags: - - Session - security: - - - bearerAuth: [] - parameters: [] servers: - url: / @@ -1106,3 +1106,6 @@ tags: - name: STP description: 'Operations about STP' + - + name: RUN + description: 'Execute SAS code' diff --git a/api/src/controllers/index.ts b/api/src/controllers/index.ts index 805cc3c..4522358 100644 --- a/api/src/controllers/index.ts +++ b/api/src/controllers/index.ts @@ -2,6 +2,7 @@ export * from './auth' export * from './client' export * from './drive' export * from './group' +export * from './run' +export * from './session' export * from './stp' export * from './user' -export * from './session' diff --git a/api/src/controllers/run.ts b/api/src/controllers/run.ts new file mode 100644 index 0000000..7adb695 --- /dev/null +++ b/api/src/controllers/run.ts @@ -0,0 +1,61 @@ +import express from 'express' +import { Request, Security, Route, Tags, Post, Body } from 'tsoa' +import { ExecutionController } from './internal' +import { PreProgramVars } from '../types' + +interface RunSASPayload { + /** + * Code of SAS program + * @example "* SAS Code HERE;" + */ + code: string +} + +@Security('bearerAuth') +@Route('SASjsApi/run') +@Tags('RUN') +export class RUNController { + /** + * Trigger a SAS program. + * @summary Run SAS Program, return raw content + */ + @Post('/code') + public async runSAS( + @Request() request: express.Request, + @Body() body: RunSASPayload + ): Promise { + return runSAS(request, body) + } +} + +const runSAS = async (req: any, { code }: RunSASPayload) => { + try { + const result = await new ExecutionController().executeProgram( + code, + getPreProgramVariables(req), + { ...req.query, _debug: 131 } + ) + + return result as string + } catch (err: any) { + throw { + code: 400, + status: 'failure', + message: 'Job execution failed.', + error: typeof err === 'object' ? err.toString() : err + } + } +} + +const getPreProgramVariables = (req: any): PreProgramVars => { + const host = req.get('host') + const protocol = req.protocol + '://' + const { user, accessToken } = req + return { + username: user.username, + userId: user.userId, + displayName: user.displayName, + serverUrl: protocol + host, + accessToken + } +} diff --git a/api/src/controllers/stp.ts b/api/src/controllers/stp.ts index d94ac25..b0f78ac 100644 --- a/api/src/controllers/stp.ts +++ b/api/src/controllers/stp.ts @@ -5,13 +5,6 @@ import { ExecutionController } from './internal' import { PreProgramVars } from '../types' import { getTmpFilesFolderPath, makeFilesNamesMap } from '../utils' -interface RunSASPayload { - /** - * Code of SAS program - * @example "* SAS Code HERE;" - */ - code: string -} interface ExecuteReturnJsonPayload { /** * Location of SAS program @@ -48,18 +41,6 @@ export class STPController { return executeReturnRaw(request, _program) } - /** - * Trigger a SAS program. - * @summary Run SAS Program, return raw content - */ - @Post('/run') - public async runSAS( - @Request() request: express.Request, - @Body() body: RunSASPayload - ): Promise { - return runSAS(request, body) - } - /** * Trigger a SAS program using it's location in the _program parameter. * Enable debugging using the _debug parameter. @@ -109,25 +90,6 @@ const executeReturnRaw = async ( } } -const runSAS = async (req: any, { code }: RunSASPayload) => { - try { - const result = await new ExecutionController().executeProgram( - code, - getPreProgramVariables(req), - req.query - ) - - return result as string - } catch (err: any) { - throw { - code: 400, - status: 'failure', - message: 'Job execution failed.', - error: typeof err === 'object' ? err.toString() : err - } - } -} - const executeReturnJson = async ( req: any, _program: string diff --git a/api/src/routes/api/index.ts b/api/src/routes/api/index.ts index b91715c..650b01c 100644 --- a/api/src/routes/api/index.ts +++ b/api/src/routes/api/index.ts @@ -11,6 +11,7 @@ import { import driveRouter from './drive' import stpRouter from './stp' +import runRouter from './run' import userRouter from './user' import groupRouter from './group' import clientRouter from './client' @@ -31,6 +32,7 @@ router.use( router.use('/drive', authenticateAccessToken, driveRouter) router.use('/group', desktopRestrict, groupRouter) router.use('/stp', authenticateAccessToken, stpRouter) +router.use('/run', authenticateAccessToken, runRouter) router.use('/user', desktopRestrict, userRouter) router.use( '/', diff --git a/api/src/routes/api/run.ts b/api/src/routes/api/run.ts new file mode 100644 index 0000000..e45ad64 --- /dev/null +++ b/api/src/routes/api/run.ts @@ -0,0 +1,25 @@ +import express from 'express' +import { runSASValidation } from '../../utils' +import { RUNController } from '../../controllers/' + +const runRouter = express.Router() + +const controller = new RUNController() + +runRouter.post('/code', async (req, res) => { + const { error, value: body } = runSASValidation(req.body) + if (error) return res.status(400).send(error.details[0].message) + + try { + const response = await controller.runSAS(req, body) + res.send(response) + } catch (err: any) { + const statusCode = err.code + + delete err.code + + res.status(statusCode).send(err) + } +}) + +export default runRouter diff --git a/api/src/routes/api/stp.ts b/api/src/routes/api/stp.ts index b00707d..1ca4a18 100644 --- a/api/src/routes/api/stp.ts +++ b/api/src/routes/api/stp.ts @@ -24,22 +24,6 @@ stpRouter.get('/execute', async (req, res) => { } }) -stpRouter.post('/run', async (req, res) => { - const { error, value: body } = runSASValidation(req.body) - if (error) return res.status(400).send(error.details[0].message) - - try { - const response = await controller.runSAS(req, body) - res.send(response) - } catch (err: any) { - const statusCode = err.code - - delete err.code - - res.status(statusCode).send(err) - } -}) - stpRouter.post( '/execute', fileUploadController.preuploadMiddleware, diff --git a/api/tsoa.json b/api/tsoa.json index b1b912b..842e35b 100644 --- a/api/tsoa.json +++ b/api/tsoa.json @@ -38,6 +38,10 @@ { "name": "STP", "description": "Operations about STP" + }, + { + "name": "RUN", + "description": "Execute SAS code" } ], "yaml": true, diff --git a/docker-compose.yml b/docker-compose.yml index f7368c7..7bce991 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,7 +43,7 @@ services: - ./web:/usr/server/web mongodb: - image: mongo:latest + image: mongo:5.0.4 ports: - 27017:27017 volumes: