From d278f8b4f2a867e68f12b8ac29be90bbd0aa3baf Mon Sep 17 00:00:00 2001 From: David Vitor Antonio Date: Mon, 12 Jun 2023 09:51:59 -0300 Subject: [PATCH] feat(channel-web): allow bot scoped upload config (#12675) * feat(channel-web): allow bot scoped upload config * update node-svm --- modules/channel-web/src/backend/api.ts | 115 +++++++++++++------------ modules/ndu/package.json | 2 +- modules/ndu/yarn.lock | 26 +++--- 3 files changed, 79 insertions(+), 64 deletions(-) diff --git a/modules/channel-web/src/backend/api.ts b/modules/channel-web/src/backend/api.ts index eb345c64c1..51c6eda358 100755 --- a/modules/channel-web/src/backend/api.ts +++ b/modules/channel-web/src/backend/api.ts @@ -52,57 +52,19 @@ const userIdIsValid = (userId: string): boolean => { return !hasBreakingConstraints && /[a-z0-9-_]+/i.test(userId) } -export default async (bp: typeof sdk, db: Database) => { - const asyncMiddleware = asyncMw(bp.logger) - const globalConfig = (await bp.config.getModuleConfig('channel-web')) as Config - - const diskStorage = multer.diskStorage({ - destination: globalConfig.fileUploadPath, - // @ts-ignore typing indicates that limits isn't supported - limits: { - files: 1, - fileSize: 5242880 // 5MB - }, - filename(req, file, cb) { - const userId = _.get(req, 'params.userId') || 'anonymous' - const ext = path.extname(file.originalname) - - cb(undefined, `${userId}_${new Date().getTime()}${ext}`) - } - }) - - let upload = multer({ storage: diskStorage }) - - if (globalConfig.uploadsUseS3) { - /* - You can override AWS's default settings here. Example: - { region: 'us-east-1', apiVersion: '2014-10-01', credentials: {...} } - */ - const awsConfig = { - region: globalConfig.uploadsS3Region, - credentials: { - accessKeyId: globalConfig.uploadsS3AWSAccessKey, - secretAccessKey: globalConfig.uploadsS3AWSAccessSecret - } - } - - if (!awsConfig.credentials.accessKeyId && !awsConfig.credentials.secretAccessKey) { - delete awsConfig.credentials - } - - if (!awsConfig.region) { - delete awsConfig.region - } - - // TODO use media service with a 's3' backend - const s3 = new aws.S3(awsConfig) - const s3Storage = multers3({ - s3, - bucket: globalConfig.uploadsS3Bucket || 'uploads', - contentType: multers3.AUTO_CONTENT_TYPE, - cacheControl: 'max-age=31536000', // one year caching - acl: 'public-read', - key(req, file, cb) { +const scopedUploadMiddlware = (bp: typeof sdk) => { + return async (req, res, next) => { + const { botId } = req.params + const config = (await bp.config.getModuleConfigForBot('channel-web', botId)) as Config + + const diskStorage = multer.diskStorage({ + destination: config.fileUploadPath, + // @ts-ignore typing indicates that limits isn't supported + limits: { + files: 1, + fileSize: 5242880 // 5MB + }, + filename(req, file, cb) { const userId = _.get(req, 'params.userId') || 'anonymous' const ext = path.extname(file.originalname) @@ -110,8 +72,55 @@ export default async (bp: typeof sdk, db: Database) => { } }) - upload = multer({ storage: s3Storage }) + let upload = multer({ storage: diskStorage }) + + if (config.uploadsUseS3) { + /* + You can override AWS's default settings here. Example: + { region: 'us-east-1', apiVersion: '2014-10-01', credentials: {...} } + */ + const awsConfig = { + region: config.uploadsS3Region, + credentials: { + accessKeyId: config.uploadsS3AWSAccessKey, + secretAccessKey: config.uploadsS3AWSAccessSecret + } + } + + if (!awsConfig.credentials.accessKeyId && !awsConfig.credentials.secretAccessKey) { + delete awsConfig.credentials + } + + if (!awsConfig.region) { + delete awsConfig.region + } + + // TODO use media service with a 's3' backend + const s3 = new aws.S3(awsConfig) + const s3Storage = multers3({ + s3, + bucket: config.uploadsS3Bucket || 'uploads', + contentType: multers3.AUTO_CONTENT_TYPE, + cacheControl: 'max-age=31536000', // one year caching + acl: 'public-read', + key(req, file, cb) { + const userId = _.get(req, 'params.userId') || 'anonymous' + const ext = path.extname(file.originalname) + + cb(undefined, `${userId}_${new Date().getTime()}${ext}`) + } + }) + + upload = multer({ storage: s3Storage }) + } + + return upload.single('file')(req, res, next) } +} + +export default async (bp: typeof sdk, db: Database) => { + const asyncMiddleware = asyncMw(bp.logger) + const scopedUpload = scopedUploadMiddlware(bp) const router = bp.http.createRouterForBot('channel-web', { checkAuthentication: false, enableJsonBodyParser: true }) const perBotCache = apicache.options({ @@ -244,7 +253,7 @@ export default async (bp: typeof sdk, db: Database) => { router.post( '/messages/files', - upload.single('file'), + scopedUpload, bp.http.extractExternalToken, assertUserInfo({ convoIdRequired: true }), asyncMiddleware(async (req: ChatRequest & any, res: Response) => { diff --git a/modules/ndu/package.json b/modules/ndu/package.json index 7e544197cf..c0023389c7 100644 --- a/modules/ndu/package.json +++ b/modules/ndu/package.json @@ -21,7 +21,7 @@ "moment": "^2.24.0", "ms": "^2.1.2", "nanoid": "^3.1.31", - "@botpress/node-svm": "0.0.3", + "@botpress/node-svm": "0.0.4", "seedrandom": "^3.0.5", "numeric": "^1.2.6" }, diff --git a/modules/ndu/yarn.lock b/modules/ndu/yarn.lock index e5db3ce880..38b959a5ac 100644 --- a/modules/ndu/yarn.lock +++ b/modules/ndu/yarn.lock @@ -2,13 +2,14 @@ # yarn lockfile v1 -"@botpress/node-svm@0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@botpress/node-svm/-/node-svm-0.0.3.tgz#f116e71d7334d121df85d368b241986a4d3da1a4" - integrity sha512-65ZAiWrNMeuZRLbCqqXDBk0txxphYTBRx1554UTF3Y/frGEuA7Zs8XNPTlLeBfcz16XFdRw99WERTYQbexjLwA== +"@botpress/node-svm@0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@botpress/node-svm/-/node-svm-0.0.4.tgz#483f6cd7f10a38ea6a4d9742d740794cf10a14ec" + integrity sha512-ItJIa6FWsGwV0WCZUxxY2HTuu414/6g6ZS4d8X0XWKFIoXhj/wapW6dDiGECnfFv1gXNDxW0Zp8zP4qeZcT4EQ== dependencies: - bluebird "^3.7.2" getos "^3.2.1" + lock "1.1.0" + yn "^4.0.0" async@^3.2.0: version "3.2.0" @@ -27,11 +28,6 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -bluebird@^3.7.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -133,6 +129,11 @@ joi@^13.6.0: isemail "3.x.x" topo "3.x.x" +lock@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/lock/-/lock-1.1.0.tgz#53157499d1653b136ca66451071fca615703fa55" + integrity sha512-NZQIJJL5Rb9lMJ0Yl1JoVr9GSdo4HTPsUEWsSFzB8dE8DSoiLCVavWZPi7Rnlv/o73u6I24S/XYc/NmG4l8EKA== + lodash@>=4.17.21, lodash@^4.17.21: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -217,3 +218,8 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +yn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-4.0.0.tgz#611480051ea43b510da1dfdbe177ed159f00a979" + integrity sha512-huWiiCS4TxKc4SfgmTwW1K7JmXPPAmuXWYy4j9qjQo4+27Kni8mGhAAi1cloRWmBe2EqcLgt3IGqQoRL/MtPgg==