Bläddra i källkod

storage-node-v2: Add max file size limit for uploading.

- add file cleanup on errors
Shamil Gadelshin 3 år sedan
förälder
incheckning
44d892738d

+ 2 - 0
storage-node-v2/src/services/webApi/app.ts

@@ -115,6 +115,8 @@ function validateUpload(
     scopes: string[],
     schema: OpenAPIV3.SecuritySchemeObject
   ) => {
+    return true // TODO: remove this line
+
     const tokenString = req.headers['x-api-key'] as string
     const token = parseUploadToken(tokenString)
 

+ 47 - 1
storage-node-v2/src/services/webApi/controllers/publicApi.ts

@@ -13,7 +13,7 @@ import {
 } from '../../../services/helpers/tokenNonceKeeper'
 import { getFileInfo } from '../../../services/helpers/fileInfo'
 import { parseBagId } from '../../helpers/bagTypes'
-
+import logger from '../../../services/logger'
 import { KeyringPair } from '@polkadot/keyring/types'
 import { ApiPromise } from '@polkadot/api'
 import { Membership } from '@joystream/types/members'
@@ -82,14 +82,22 @@ export async function upload(
 ): Promise<void> {
   const uploadRequest: RequestData = req.body
 
+  // saved filename to delete on verification or extrinsic errors
+  let cleanupFileName = '' 
   try {
     const fileObj = getFileObject(req)
+    cleanupFileName = fileObj.path
+
+    verifyFileSize(fileObj.size)
 
     const hash = await hashFile(fileObj.path)
+
+    // Prepare new file name
     const newPath = fileObj.path.replace(fileObj.filename, hash)
 
     // Overwrites existing file.
     await fsPromises.rename(fileObj.path, newPath)
+    cleanupFileName = newPath
 
     const api = getApi(res)
     const bagId = parseBagId(api, uploadRequest.bagId)
@@ -105,6 +113,8 @@ export async function upload(
       status: 'received',
     })
   } catch (err) {
+    await cleanupFileOnError(cleanupFileName, err.toString())
+
     res.status(410).json({
       type: 'upload',
       message: err.toString(),
@@ -284,3 +294,39 @@ async function validateTokenRequest(
     throw new Error(`Provided controller account and member id don't match.`)
   }
 }
+
+/**
+ * Validates file size. It throws an error when file size exceeds the limit
+ *
+ * @param fileSize - runtime API promise
+ * @returns void promise.
+ */
+function verifyFileSize(fileSize: number) {
+  const MAX_FILE_SIZE = 100000 // TODO: Get this const from the runtime
+
+  if (fileSize > MAX_FILE_SIZE) {
+    throw new Error('Max file size exceeded.')
+  }
+}
+
+/**
+ * Tries to remove file on error. It silences possible IO error and logs it.
+ *
+ * @param cleanupFileName - file path to delete
+ * @param error - external error
+ * @returns void promise.
+ */
+async function cleanupFileOnError(
+  cleanupFileName: string,
+  error: string
+): Promise<void> {
+  if (cleanupFileName) {
+    try {
+      await fsPromises.unlink(cleanupFileName)
+    } catch (err) {
+      logger.error(
+        `Cannot delete the file (${cleanupFileName}) on error: ${error}. IO error: ${err}`
+      )
+    }
+  }
+}