1
0
mirror of https://github.com/sasjs/server.git synced 2026-01-09 15:30:05 +00:00

feat(api): added autoexec + major type setting changes

This commit is contained in:
Saad Jutt
2022-05-24 21:12:32 +05:00
parent 1fed5ea6ac
commit 2a7223ad7d
26 changed files with 227 additions and 99 deletions

View File

@@ -1,7 +1,6 @@
import express from 'express'
import { Request, Security, Route, Tags, Post, Body } from 'tsoa'
import { ExecuteReturnJson, ExecutionController } from './internal'
import { PreProgramVars } from '../types'
import { ExecuteReturnJsonResponse } from '.'
import { getPreProgramVariables, parseLogToArray } from '../utils'
@@ -30,14 +29,18 @@ export class CodeController {
}
}
const executeSASCode = async (req: any, { code }: ExecuteSASCodePayload) => {
const executeSASCode = async (
req: express.Request,
{ code }: ExecuteSASCodePayload
) => {
const { user } = req
try {
const { webout, log, httpHeaders } =
(await new ExecutionController().executeProgram(
code,
getPreProgramVariables(req),
{ ...req.query, _debug: 131 },
undefined,
{ userAutoExec: user?.autoExec },
true
)) as ExecuteReturnJson

View File

@@ -119,6 +119,10 @@ filename _webout "${weboutPath}" mod;
/* dynamic user-provided vars */
${preProgramVarStatments}
/* user auto exec starts */
${otherArgs?.userAutoExec}
/* user auto exec ends */
/* actual job code */
${program}`

View File

@@ -1,14 +1,15 @@
import { Request, RequestHandler } from 'express'
import multer from 'multer'
import { uuidv4 } from '@sasjs/utils'
import { getSessionController } from '.'
export class FileUploadController {
private storage = multer.diskStorage({
destination: function (req: any, file: any, cb: any) {
destination: function (req: Request, file: any, cb: any) {
//Sending the intercepted files to the sessions subfolder
cb(null, req.sasSession.path)
cb(null, req.sasSession?.path)
},
filename: function (req: any, file: any, cb: any) {
filename: function (req: Request, file: any, cb: any) {
//req_file prefix + unique hash added to sas request files
cb(null, `req_file_${uuidv4().replace(/-/gm, '')}`)
}
@@ -18,7 +19,7 @@ export class FileUploadController {
//It will intercept request and generate unique uuid to be used as a subfolder name
//that will store the files uploaded
public preUploadMiddleware = async (req: any, res: any, next: any) => {
public preUploadMiddleware: RequestHandler = async (req, res, next) => {
let session
const sessionController = getSessionController()

View File

@@ -23,8 +23,8 @@ export class SessionController {
}
}
const session = (req: any) => ({
id: req.user.userId,
username: req.user.username,
displayName: req.user.displayName
const session = (req: express.Request) => ({
id: req.user!.userId,
username: req.user!.username,
displayName: req.user!.displayName
})

View File

@@ -26,6 +26,7 @@ import {
makeFilesNamesMap,
parseLogToArray
} from '../utils'
import { MulterFile } from '../types/Upload'
interface ExecuteReturnJsonPayload {
/**
@@ -167,7 +168,7 @@ const executeReturnRaw = async (
}
const executeReturnJson = async (
req: any,
req: express.Request,
_program: string
): Promise<ExecuteReturnJsonResponse> => {
const sasCodePath =
@@ -175,7 +176,9 @@ const executeReturnJson = async (
.join(getFilesFolder(), _program)
.replace(new RegExp('/', 'g'), path.sep) + '.sas'
const filesNamesMap = req.files?.length ? makeFilesNamesMap(req.files) : null
const filesNamesMap = req.files?.length
? makeFilesNamesMap(req.files as MulterFile[])
: null
try {
const { webout, log, httpHeaders } =

View File

@@ -1,3 +1,4 @@
import express from 'express'
import {
Security,
Route,
@@ -10,7 +11,8 @@ import {
Patch,
Delete,
Body,
Hidden
Hidden,
Request
} from 'tsoa'
import User, { UserPayload } from '../model/User'
@@ -27,6 +29,7 @@ interface UserDetailsResponse {
username: string
isActive: boolean
isAdmin: boolean
autoExec?: string
}
@Security('bearerAuth')
@@ -73,13 +76,19 @@ export class UserController {
}
/**
* Only Admin or user itself will get user autoExec code.
* @summary Get user properties - such as group memberships, userName, displayName.
* @param userId The user's identifier
* @example userId 1234
*/
@Get('{userId}')
public async getUser(@Path() userId: number): Promise<UserDetailsResponse> {
return getUser(userId)
public async getUser(
@Request() req: express.Request,
@Path() userId: number
): Promise<UserDetailsResponse> {
const { user } = req
const getAutoExec = user!.isAdmin || user!.userId == userId
return getUser(userId, getAutoExec)
}
/**
@@ -123,7 +132,7 @@ const getAllUsers = async (): Promise<UserResponse[]> =>
.exec()
const createUser = async (data: UserPayload): Promise<UserDetailsResponse> => {
const { displayName, username, password, isAdmin, isActive } = data
const { displayName, username, password, isAdmin, isActive, autoExec } = data
// Checking if user is already in the database
const usernameExist = await User.findOne({ username })
@@ -138,7 +147,8 @@ const createUser = async (data: UserPayload): Promise<UserDetailsResponse> => {
username,
password: hashPassword,
isAdmin,
isActive
isActive,
autoExec
})
const savedUser = await user.save()
@@ -148,38 +158,42 @@ const createUser = async (data: UserPayload): Promise<UserDetailsResponse> => {
displayName: savedUser.displayName,
username: savedUser.username,
isActive: savedUser.isActive,
isAdmin: savedUser.isAdmin
isAdmin: savedUser.isAdmin,
autoExec: savedUser.autoExec
}
}
const getUser = async (id: number): Promise<UserDetailsResponse> => {
const getUser = async (
id: number,
getAutoExec: boolean
): Promise<UserDetailsResponse> => {
const user = await User.findOne({ id })
.select({
_id: 0,
id: 1,
username: 1,
displayName: 1,
isAdmin: 1,
isActive: 1
})
.exec()
if (!user) throw new Error('User is not found.')
return user
return {
id: user.id,
displayName: user.displayName,
username: user.username,
isActive: user.isActive,
isAdmin: user.isAdmin,
autoExec: getAutoExec ? user.autoExec : undefined
}
}
const updateUser = async (
id: number,
data: UserPayload
data: Partial<UserPayload>
): Promise<UserDetailsResponse> => {
const { displayName, username, password, isAdmin, isActive } = data
const { displayName, username, password, isAdmin, isActive, autoExec } = data
const params: any = { displayName, isAdmin, isActive }
const params: any = { displayName, isAdmin, isActive, autoExec }
if (username) {
// Checking if user is already in the database
const usernameExist = await User.findOne({ username })
if (usernameExist?.id != id) throw new Error('Username already exists.')
if (usernameExist && usernameExist.id != id)
throw new Error('Username already exists.')
params.username = username
}
@@ -189,18 +203,17 @@ const updateUser = async (
}
const updatedUser = await User.findOneAndUpdate({ id }, params, { new: true })
.select({
_id: 0,
id: 1,
username: 1,
displayName: 1,
isAdmin: 1,
isActive: 1
})
.exec()
if (!updatedUser) throw new Error('Unable to update user')
return updatedUser
if (!updatedUser) throw new Error(`Unable to find user with id: ${id}`)
return {
id: updatedUser.id,
username: updatedUser.username,
displayName: updatedUser.displayName,
isAdmin: updatedUser.isAdmin,
isActive: updatedUser.isActive,
autoExec: updatedUser.autoExec
}
}
const deleteUser = async (

View File

@@ -90,7 +90,8 @@ const login = async (
username: user.username,
displayName: user.displayName,
isAdmin: user.isAdmin,
isActive: user.isActive
isActive: user.isActive,
autoExec: user.autoExec
}
return {