1
0
mirror of https://github.com/sasjs/server.git synced 2025-12-11 19:44:35 +00:00

feat: created api endpoint for adding empty folder in drive

This commit is contained in:
2022-07-20 16:43:43 +05:00
parent 177675bc89
commit 941917e508
4 changed files with 134 additions and 25 deletions

View File

@@ -230,7 +230,7 @@ components:
- fileTree - fileTree
type: object type: object
additionalProperties: false additionalProperties: false
UpdateFileResponse: FileFolderResponse:
properties: properties:
status: status:
type: string type: string
@@ -240,6 +240,16 @@ components:
- status - status
type: object type: object
additionalProperties: false additionalProperties: false
AddFolderPayload:
properties:
folderPath:
type: string
description: 'Location of folder'
example: /Public/someFolder
required:
- folderPath
type: object
additionalProperties: false
TreeNode: TreeNode:
properties: properties:
name: name:
@@ -839,7 +849,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/UpdateFileResponse' $ref: '#/components/schemas/FileFolderResponse'
examples: examples:
'Example 1': 'Example 1':
value: {status: success} value: {status: success}
@@ -848,7 +858,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/UpdateFileResponse' $ref: '#/components/schemas/FileFolderResponse'
examples: examples:
'Example 1': 'Example 1':
value: {status: failure, message: 'File request failed.'} value: {status: failure, message: 'File request failed.'}
@@ -861,7 +871,7 @@ paths:
bearerAuth: [] bearerAuth: []
parameters: parameters:
- -
description: 'Location of SAS program' description: 'Location of file'
in: query in: query
name: _filePath name: _filePath
required: false required: false
@@ -890,7 +900,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/UpdateFileResponse' $ref: '#/components/schemas/FileFolderResponse'
examples: examples:
'Example 1': 'Example 1':
value: {status: success} value: {status: success}
@@ -899,7 +909,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/UpdateFileResponse' $ref: '#/components/schemas/FileFolderResponse'
examples: examples:
'Example 1': 'Example 1':
value: {status: failure, message: 'File request failed.'} value: {status: failure, message: 'File request failed.'}
@@ -990,6 +1000,40 @@ paths:
schema: schema:
type: string type: string
example: /Public/somefolder/ example: /Public/somefolder/
post:
operationId: AddFolder
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/FileFolderResponse'
examples:
'Example 1':
value: {status: success}
'409':
description: 'Folder already exists'
content:
application/json:
schema:
$ref: '#/components/schemas/FileFolderResponse'
examples:
'Example 1':
value: {status: failure, message: 'Add folder request failed.'}
summary: 'Create an empty folder in SASjs Drive'
tags:
- Drive
security:
-
bearerAuth: []
parameters: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AddFolderPayload'
/SASjsApi/drive/filetree: /SASjsApi/drive/filetree:
get: get:
operationId: GetFileTree operationId: GetFileTree

View File

@@ -59,11 +59,19 @@ interface GetFileTreeResponse {
tree: TreeNode tree: TreeNode
} }
interface UpdateFileResponse { interface FileFolderResponse {
status: string status: string
message?: string message?: string
} }
interface AddFolderPayload {
/**
* Location of folder
* @example "/Public/someFolder"
*/
folderPath: string
}
const fileTreeExample = getTreeExample() const fileTreeExample = getTreeExample()
const successDeployResponse: DeployResponse = { const successDeployResponse: DeployResponse = {
@@ -141,6 +149,17 @@ export class DriveController {
return getFolder(_folderPath) return getFolder(_folderPath)
} }
/**
*
* @summary Delete file from SASjs Drive
* @query _filePath Location of file
* @example _filePath "/Public/somefolder/some.file"
*/
@Delete('/file')
public async deleteFile(@Query() _filePath: string) {
return deleteFile(_filePath)
}
/** /**
* *
* @summary Delete folder from SASjs Drive * @summary Delete folder from SASjs Drive
@@ -152,31 +171,20 @@ export class DriveController {
return deleteFolder(_folderPath) return deleteFolder(_folderPath)
} }
/**
*
* @summary Delete file from SASjs Drive
* @query _filePath Location of SAS program
* @example _filePath "/Public/somefolder/some.file"
*/
@Delete('/file')
public async deleteFile(@Query() _filePath: string) {
return deleteFile(_filePath)
}
/** /**
* It's optional to either provide `_filePath` in url as query parameter * It's optional to either provide `_filePath` in url as query parameter
* Or provide `filePath` in body as form field. * Or provide `filePath` in body as form field.
* But it's required to provide else API will respond with Bad Request. * But it's required to provide else API will respond with Bad Request.
* *
* @summary Create a file in SASjs Drive * @summary Create a file in SASjs Drive
* @param _filePath Location of SAS program * @param _filePath Location of file
* @example _filePath "/Public/somefolder/some.file.sas" * @example _filePath "/Public/somefolder/some.file.sas"
* *
*/ */
@Example<UpdateFileResponse>({ @Example<FileFolderResponse>({
status: 'success' status: 'success'
}) })
@Response<UpdateFileResponse>(403, 'File already exists', { @Response<FileFolderResponse>(403, 'File already exists', {
status: 'failure', status: 'failure',
message: 'File request failed.' message: 'File request failed.'
}) })
@@ -185,10 +193,28 @@ export class DriveController {
@UploadedFile() file: Express.Multer.File, @UploadedFile() file: Express.Multer.File,
@Query() _filePath?: string, @Query() _filePath?: string,
@FormField() filePath?: string @FormField() filePath?: string
): Promise<UpdateFileResponse> { ): Promise<FileFolderResponse> {
return saveFile((_filePath ?? filePath)!, file) return saveFile((_filePath ?? filePath)!, file)
} }
/**
* @summary Create an empty folder in SASjs Drive
*
*/
@Example<FileFolderResponse>({
status: 'success'
})
@Response<FileFolderResponse>(409, 'Folder already exists', {
status: 'failure',
message: 'Add folder request failed.'
})
@Post('/folder')
public async addFolder(
@Body() body: AddFolderPayload
): Promise<FileFolderResponse> {
return addFolder(body.folderPath)
}
/** /**
* It's optional to either provide `_filePath` in url as query parameter * It's optional to either provide `_filePath` in url as query parameter
* Or provide `filePath` in body as form field. * Or provide `filePath` in body as form field.
@@ -199,10 +225,10 @@ export class DriveController {
* @example _filePath "/Public/somefolder/some.file.sas" * @example _filePath "/Public/somefolder/some.file.sas"
* *
*/ */
@Example<UpdateFileResponse>({ @Example<FileFolderResponse>({
status: 'success' status: 'success'
}) })
@Response<UpdateFileResponse>(403, `File doesn't exist`, { @Response<FileFolderResponse>(403, `File doesn't exist`, {
status: 'failure', status: 'failure',
message: 'File request failed.' message: 'File request failed.'
}) })
@@ -211,7 +237,7 @@ export class DriveController {
@UploadedFile() file: Express.Multer.File, @UploadedFile() file: Express.Multer.File,
@Query() _filePath?: string, @Query() _filePath?: string,
@FormField() filePath?: string @FormField() filePath?: string
): Promise<UpdateFileResponse> { ): Promise<FileFolderResponse> {
return updateFile((_filePath ?? filePath)!, file) return updateFile((_filePath ?? filePath)!, file)
} }
@@ -372,6 +398,26 @@ const saveFile = async (
return { status: 'success' } return { status: 'success' }
} }
const addFolder = async (folderPath: string): Promise<FileFolderResponse> => {
const drivePath = getFilesFolder()
const folderPathFull = path
.join(drivePath, folderPath)
.replace(new RegExp('/', 'g'), path.sep)
if (!folderPathFull.includes(drivePath)) {
throw new Error('Cannot put folder outside drive.')
}
if (await folderExists(folderPathFull)) {
throw new Error('Folder already exists.')
}
await createFolder(folderPathFull)
return { status: 'success' }
}
const updateFile = async ( const updateFile = async (
filePath: string, filePath: string,
multerFile: Express.Multer.File multerFile: Express.Multer.File

View File

@@ -11,6 +11,7 @@ import {
extractName, extractName,
fileBodyValidation, fileBodyValidation,
fileParamValidation, fileParamValidation,
folderBodyValidation,
folderParamValidation, folderParamValidation,
isZipFile isZipFile
} from '../../utils' } from '../../utils'
@@ -190,6 +191,19 @@ driveRouter.post(
} }
) )
driveRouter.post('/folder', async (req, res) => {
const { error, value: body } = folderBodyValidation(req.body)
if (error) return res.status(400).send(error.details[0].message)
try {
const response = await controller.addFolder(body)
res.send(response)
} catch (err: any) {
res.status(403).send(err.toString())
}
})
driveRouter.patch( driveRouter.patch(
'/file', '/file',
(...arg) => multerSingle('file', arg), (...arg) => multerSingle('file', arg),

View File

@@ -143,6 +143,11 @@ export const folderParamValidation = (data: any): Joi.ValidationResult =>
_folderPath: Joi.string() _folderPath: Joi.string()
}).validate(data) }).validate(data)
export const folderBodyValidation = (data: any): Joi.ValidationResult =>
Joi.object({
folderPath: Joi.string()
}).validate(data)
export const runCodeValidation = (data: any): Joi.ValidationResult => export const runCodeValidation = (data: any): Joi.ValidationResult =>
Joi.object({ Joi.object({
code: Joi.string().required(), code: Joi.string().required(),