From 937fca8494c44620402d6c9f7ff168d1d76c5803 Mon Sep 17 00:00:00 2001 From: Roshni Naveena S Date: Fri, 25 Jul 2025 18:18:08 +0530 Subject: [PATCH 1/5] refactor: remove hardcoded regex in favor of CAP-native key parsing via req.params[1] --- lib/plugin.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/plugin.js b/lib/plugin.js index acfe93d8..2e9ecbcf 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -2,7 +2,6 @@ const cds = require("@sap/cds/lib") const LOG = cds.log("attachments") const { extname } = require("path") const DEBUG = LOG._debug ? LOG.debug : undefined -const attachmentIDRegex = /\/\w+\(.*ID=([0-9a-fA-F-]{36})/ cds.on(cds.version >= "8.6.0" ? "compile.to.edmx" : "loaded", unfoldModel); function unfoldModel (csn) { From 5eadef699dffa67899ff58046d7d6543005f8d44 Mon Sep 17 00:00:00 2001 From: Roshni Naveena S Date: Tue, 29 Jul 2025 11:56:56 +0530 Subject: [PATCH 2/5] fix: enhance nonDraftUpload to support arbitrary key names using req.params Rewrote the nonDraftUpload function to avoid assuming the key name is ID. It now uses req.params[1] to access the correct key-value pairs for the Attachments entity. This makes the non-draft upload logic fully compatible with entities using custom key names instead of hardcoded ID. --- lib/plugin.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/plugin.js b/lib/plugin.js index 2e9ecbcf..79bfa656 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -105,11 +105,20 @@ cds.once("served", async function registerPluginHandlers () { } async function nonDraftUpload(req, target) { - if (req?.content?.url?.endsWith("/content")) { - const attachmentID = req.content.url.match(attachmentIDRegex)[1]; - AttachmentsSrv.nonDraftHandler(target, { ID: attachmentID, content: req.content }); - } - } + try { + if (req?.content?.url?.endsWith("/content")) { + const attachmentID = req.params?.[1]?.ID; + if (!attachmentID) return req.reject(400, 'Missing attachment key in URL'); + await AttachmentsSrv.nonDraftHandler(target, { + ID: attachmentID, + content: req.content + }); + } + } catch (err) { + LOG.error('[NON_DRAFT_UPLOAD_ERROR]', err); + req.reject(500, 'Non-draft attachment upload failed.'); + } + } }) function validateAttachmentSize (req) { From fd0ca7e11b22623518e4f492d545c2522149a9d1 Mon Sep 17 00:00:00 2001 From: Roshni Naveena S Date: Tue, 29 Jul 2025 11:59:25 +0530 Subject: [PATCH 3/5] fix: refactor readAttachment to support dynamic keys using req.params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced the usage of hardcoded regex parsing in readAttachment with CAP’s req.params array to dynamically extract key values. --- lib/plugin.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/plugin.js b/lib/plugin.js index 79bfa656..0c1dcea0 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -99,7 +99,8 @@ cds.once("served", async function registerPluginHandlers () { async function readAttachment ([attachment], req) { if (!req?.req?.url?.endsWith("/content") || !attachment || attachment?.content) return - let keys = { ID: req.req.url.match(attachmentIDRegex)[1] } + const keys = req.params?.[1]; + if (!keys) return; let { target } = req attachment.content = await AttachmentsSrv.get(target, keys, req) //Dependency -> sending req object for usage in SDM plugin } From 1e93f87be3cfc31810805b57d87b69a81b9b956f Mon Sep 17 00:00:00 2001 From: Roshni Naveena S Date: Tue, 29 Jul 2025 12:01:16 +0530 Subject: [PATCH 4/5] fix: update validateAttachment to support key extraction via req.params instead of regex --- lib/plugin.js | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/plugin.js b/lib/plugin.js index 0c1dcea0..b0cf1b06 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -81,20 +81,21 @@ cds.once("served", async function registerPluginHandlers () { /* removing case condition for mediaType annotation as in our case binary value and metadata is stored in different database */ req?.query?.SELECT?.columns?.forEach((element) => { - if (element.as === 'content@odata.mediaContentType' && element.xpr) { - delete element.xpr - element.ref = ['mimeType'] - } - }) - - if (req?.req?.url?.endsWith("/content")) { - const attachmentID = req.req.url.match(attachmentIDRegex)[1] - const status = await AttachmentsSrv.getStatus(req.target, { ID: attachmentID }) - const scanEnabled = cds.env.requires?.attachments?.scan ?? true - if (scanEnabled && status !== 'Clean') { - req.reject(403, 'Unable to download the attachment as scan status is not clean.') - } + if (element.as === 'content@odata.mediaContentType' && element.xpr) { + delete element.xpr; + element.ref = ['mimeType']; } + }); + + if (req?.req?.url?.endsWith("/content")) { + const attachmentKey = req.params?.[1]; + if (!attachmentKey?.ID) return req.reject(400, 'Missing attachment key in request'); + const status = await AttachmentsSrv.getStatus(req.target, attachmentKey); + const scanEnabled = cds.env.requires?.attachments?.scan ?? true; + if (scanEnabled && status !== 'Clean') { + req.reject(403, 'Unable to download the attachment as scan status is not clean.'); + } + } } async function readAttachment ([attachment], req) { From 3329827c1e2dbdb23a0c56697fa73c4e811ca316 Mon Sep 17 00:00:00 2001 From: Roshni Naveena S Date: Tue, 29 Jul 2025 14:22:13 +0530 Subject: [PATCH 5/5] Update plugin.js --- lib/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plugin.js b/lib/plugin.js index b0cf1b06..1ad7b1c6 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -118,7 +118,7 @@ cds.once("served", async function registerPluginHandlers () { } } catch (err) { LOG.error('[NON_DRAFT_UPLOAD_ERROR]', err); - req.reject(500, 'Non-draft attachment upload failed.'); + throw Object.assign(new Error('Non-draft attachment upload failed.'), { statusCode: 500 }); } } })