@@ -34,11 +34,6 @@ module.exports = class AzureAttachmentsService extends require("./object-store")
3434 const creds = cds . env . requires ?. objectStore ?. credentials
3535
3636 if ( ! creds ) {
37- if ( Object . keys ( creds ) . includes ( 'access_key_id' ) ) {
38- throw new Error ( 'AWS S3 credentials found where Azure Blob Storage credentials expected, please check your service bindings.' )
39- } else if ( Object . keys ( creds ) . includes ( 'projectId' ) ) {
40- throw new Error ( 'Google Cloud Platform credentials found where Azure Blob Storage credentials expected, please check your service bindings.' )
41- }
4237 throw new Error ( "SAP Object Store instance is not bound." )
4338 }
4439
@@ -151,13 +146,12 @@ module.exports = class AzureAttachmentsService extends require("./object-store")
151146 /**
152147 * @inheritdoc
153148 */
154- async put ( attachments , data , isDraftEnabled , _content , req ) {
149+ async put ( attachments , data ) {
155150 const startTime = Date . now ( )
156151
157152 logConfig . processStep ( 'Starting file upload to Azure Blob Storage' , {
158153 attachmentEntity : attachments . name ,
159- isDraftEnabled,
160- tenant : req ?. tenant
154+ tenant : cds . context . tenant
161155 } )
162156
163157 try {
@@ -180,26 +174,26 @@ module.exports = class AzureAttachmentsService extends require("./object-store")
180174 filenames : data . map ( d => d . filename )
181175 } )
182176 return Promise . all (
183- data . map ( ( d ) => this . put ( attachments , d , isDraftEnabled , _content , req ) )
177+ data . map ( ( d ) => this . put ( attachments , d ) )
184178 )
185179 }
186180
187- const { content = _content , ...metadata } = data
181+ let { content : _content , ...metadata } = data
188182 const blobName = metadata . url
189183
190184 if ( ! blobName ) {
191185 logConfig . withSuggestion ( 'error' ,
192186 'File key/URL is required for Azure Blob Storage upload' , null ,
193187 'Ensure attachment data includes a valid URL/key' ,
194- { metadata : { ...metadata , content : ! ! content } } )
188+ { metadata : { ...metadata , content : ! ! _content } } )
195189 throw new Error ( 'File key is required for upload' )
196190 }
197191
198- if ( ! content ) {
192+ if ( ! _content ) {
199193 logConfig . withSuggestion ( 'error' ,
200194 'File content is required for Azure Blob Storage upload' , null ,
201195 'Ensure attachment data includes file content' ,
202- { key : blobName , hasContent : ! ! content } )
196+ { key : blobName , hasContent : ! ! _content } )
203197 throw new Error ( 'File content is required for upload' )
204198 }
205199
@@ -209,11 +203,31 @@ module.exports = class AzureAttachmentsService extends require("./object-store")
209203 containerName : this . containerName ,
210204 blobName,
211205 filename : metadata . filename ,
212- contentSize : content . length || content . size || 'unknown'
206+ contentSize : _content . length || _content . size || 'unknown'
213207 } )
214208
215- const stored = super . put ( attachments , metadata , null , isDraftEnabled )
216- await Promise . all ( [ stored , blobClient . uploadData ( content ) ] )
209+ // Handle different content types for update
210+ let contentLength
211+ const content = _content
212+ if ( Buffer . isBuffer ( content ) ) {
213+ contentLength = content . length
214+ } else if ( content && typeof content . length === 'number' ) {
215+ contentLength = content . length
216+ } else if ( content && typeof content . size === 'number' ) {
217+ contentLength = content . size
218+ } else {
219+ // Convert to buffer if needed
220+ const chunks = [ ]
221+ for await ( const chunk of content ) {
222+ chunks . push ( chunk )
223+ }
224+ _content = Buffer . concat ( chunks )
225+ contentLength = _content . length
226+ }
227+
228+ // The file upload has to be done first, so super.put can compute the hash
229+ await blobClient . upload ( _content , contentLength )
230+ await super . put ( attachments , metadata )
217231
218232 const duration = Date . now ( ) - startTime
219233 logConfig . debug ( 'File upload to Azure Blob Storage completed successfully' , {
@@ -317,68 +331,6 @@ module.exports = class AzureAttachmentsService extends require("./object-store")
317331 }
318332 }
319333
320- /**
321- * Registers attachment handlers for the given service and entity
322- * @param {import('@sap/cds').Request } req - The request object
323- * @param {import('express').NextFunction } next - The next middleware function
324- */
325- async updateContentHandler ( req , next ) {
326- logConfig . debug ( `[Azure] Uploading file using updateContentHandler for ${ req . target . name } ` )
327- // Check separate object store instances
328- if ( separateObjectStore ) {
329- const tenantID = cds . context . tenant
330- await this . createAzureClient ( tenantID )
331- }
332-
333- const targetID = req . data . ID || req . params [ 1 ] ?. ID || req . params [ 1 ]
334- if ( ! targetID ) {
335- req . reject ( 400 , "Missing ID in request" )
336- }
337-
338- if ( req ?. data ?. content ) {
339- const response = await SELECT . from ( req . target , { ID : targetID } ) . columns ( "url" )
340- if ( response ?. url ) {
341- const blobName = response . url
342- const blobClient = this . containerClient . getBlockBlobClient ( blobName )
343-
344- // Handle different content types for update
345- let contentLength
346- const content = req . data . content
347- if ( Buffer . isBuffer ( content ) ) {
348- contentLength = content . length
349- } else if ( content && typeof content . length === 'number' ) {
350- contentLength = content . length
351- } else if ( content && typeof content . size === 'number' ) {
352- contentLength = content . size
353- } else {
354- // Convert to buffer if needed
355- const chunks = [ ]
356- for await ( const chunk of content ) {
357- chunks . push ( chunk )
358- }
359- req . data . content = Buffer . concat ( chunks )
360- contentLength = req . data . content . length
361- }
362-
363- await blobClient . upload ( req . data . content , contentLength )
364-
365- const hash = await utils . computeHash ( await this . get ( req . target , { ID : targetID } ) )
366- await super . update ( req . target , { ID : targetID } , { hash } )
367-
368- const MalwareScanner = await cds . connect . to ( 'malwareScanner' )
369- await MalwareScanner . emit ( 'ScanFile' , { target : req . target . name , keys : { ID : targetID } } )
370-
371- logConfig . debug ( `[Azure] Uploaded file using updateContentHandler for ${ req . target . name } ` )
372- }
373- } else if ( req ?. data ?. note ) {
374- const key = { ID : targetID }
375- await super . update ( req . target , key , { note : req . data . note } )
376- logConfig . debug ( `[Azure] Updated file upload with note for ${ req . target . name } ` )
377- } else {
378- next ( )
379- }
380- }
381-
382334 /**
383335 * Deletes a file from Azure Blob Storage
384336 * @param {string } Key - The key of the file to delete
0 commit comments