11import { v4 as uuidv4 } from 'uuid' ;
22import S3Policy from 's3-policy-v4' ;
3- import s3 from '@auth0/s3' ;
3+ import {
4+ S3Client ,
5+ HeadObjectCommand ,
6+ CopyObjectCommand ,
7+ ListObjectsCommand ,
8+ DeleteObjectsCommand
9+ } from '@aws-sdk/client-s3' ;
410import mongoose from 'mongoose' ;
511import { getProjectsForUserId } from './project.controller' ;
612import User from '../models/user' ;
713
814const { ObjectId } = mongoose . Types ;
915
10- const client = s3 . createClient ( {
11- maxAsyncS3 : 20 ,
12- s3RetryCount : 3 ,
13- s3RetryDelay : 1000 ,
14- multipartUploadThreshold : 20971520 , // this is the default (20 MB)
15- multipartUploadSize : 15728640 , // this is the default (15 MB)
16- s3Options : {
17- accessKeyId : `${ process . env . AWS_ACCESS_KEY } ` ,
18- secretAccessKey : `${ process . env . AWS_SECRET_KEY } ` ,
19- region : `${ process . env . AWS_REGION } `
20- }
16+ const s3Client = new S3Client ( {
17+ credentials : {
18+ accessKeyId : process . env . AWS_ACCESS_KEY ,
19+ secretAccessKey : process . env . AWS_SECRET_KEY
20+ } ,
21+ region : process . env . AWS_REGION
2122} ) ;
2223
2324const s3Bucket =
@@ -39,34 +40,34 @@ export function getObjectKey(url) {
3940 return objectKey ;
4041}
4142
42- export function deleteObjectsFromS3 ( keyList , callback ) {
43- const keys = keyList . map ( ( key ) => { return { Key : key } ; } ) ; // eslint-disable-line
44- if ( keyList . length > 0 ) {
43+ export async function deleteObjectsFromS3 ( keyList , callback ) {
44+ const objectsToDelete = keyList . map ( ( key ) => ( { Key : key } ) ) ;
45+
46+ if ( objectsToDelete . length > 0 ) {
4547 const params = {
46- Bucket : `${ process . env . S3_BUCKET } ` ,
47- Delete : {
48- Objects : keys
49- }
48+ Bucket : process . env . S3_BUCKET ,
49+ Delete : { Objects : objectsToDelete }
5050 } ;
51- const del = client . deleteObjects ( params ) ;
52- del . on ( 'end' , ( ) => {
51+
52+ try {
53+ await s3Client . send ( new DeleteObjectsCommand ( params ) ) ;
5354 if ( callback ) {
5455 callback ( ) ;
5556 }
56- } ) ;
57+ } catch ( error ) {
58+ console . error ( 'Error deleting objects from S3: ' , error ) ;
59+ if ( callback ) {
60+ callback ( error ) ;
61+ }
62+ }
5763 } else if ( callback ) {
5864 callback ( ) ;
5965 }
6066}
6167
6268export function deleteObjectFromS3 ( req , res ) {
6369 const { objectKey, userId } = req . params ;
64- let fullObjectKey ;
65- if ( userId ) {
66- fullObjectKey = `${ userId } /${ objectKey } ` ;
67- } else {
68- fullObjectKey = objectKey ;
69- }
70+ const fullObjectKey = userId ? `${ userId } /${ objectKey } ` : objectKey ;
7071 deleteObjectsFromS3 ( [ fullObjectKey ] , ( ) => {
7172 res . json ( { success : true } ) ;
7273 } ) ;
@@ -96,143 +97,120 @@ export function signS3(req, res) {
9697 res . json ( policy ) ;
9798}
9899
99- export function copyObjectInS3 ( url , userId ) {
100- return new Promise ( ( resolve , reject ) => {
101- const objectKey = getObjectKey ( url ) ;
102- const fileExtension = getExtension ( objectKey ) ;
103- const newFilename = uuidv4 ( ) + fileExtension ;
104- const headParams = {
105- Bucket : `${ process . env . S3_BUCKET } ` ,
106- Key : `${ objectKey } `
107- } ;
108- client . s3 . headObject ( headParams , ( headErr ) => {
109- if ( headErr ) {
110- reject (
111- new Error (
112- `Object with key ${ process . env . S3_BUCKET } /${ objectKey } does not exist.`
113- )
114- ) ;
115- return ;
116- }
117- const params = {
118- Bucket : `${ process . env . S3_BUCKET } ` ,
119- CopySource : `${ process . env . S3_BUCKET } /${ objectKey } ` ,
120- Key : `${ userId } /${ newFilename } ` ,
121- ACL : 'public-read'
122- } ;
123- const copy = client . copyObject ( params ) ;
124- copy . on ( 'err' , ( err ) => {
125- reject ( err ) ;
126- } ) ;
127- copy . on ( 'end' , ( data ) => {
128- resolve ( `${ s3Bucket } ${ userId } /${ newFilename } ` ) ;
129- } ) ;
130- } ) ;
131- } ) ;
100+ export async function copyObjectInS3 ( url , userId ) {
101+ const objectKey = getObjectKey ( url ) ;
102+ const fileExtension = getExtension ( objectKey ) ;
103+ const newFilename = uuidv4 ( ) + fileExtension ;
104+ const headParams = {
105+ Bucket : process . env . S3_BUCKET ,
106+ Key : objectKey
107+ } ;
108+
109+ await s3Client . send ( new HeadObjectCommand ( headParams ) ) ;
110+
111+ const params = {
112+ Bucket : process . env . S3_BUCKET ,
113+ CopySource : `${ process . env . S3_BUCKET } /${ objectKey } ` ,
114+ Key : `${ userId } /${ newFilename } ` ,
115+ ACL : 'public-read'
116+ } ;
117+
118+ try {
119+ await s3Client . send ( new CopyObjectCommand ( params ) ) ;
120+ return `${ s3Bucket } ${ userId } /${ newFilename } ` ;
121+ } catch ( error ) {
122+ console . error ( 'Error copying object in S3:' , error ) ;
123+ throw error ;
124+ }
132125}
133126
134- export function copyObjectInS3RequestHandler ( req , res ) {
127+ export async function copyObjectInS3RequestHandler ( req , res ) {
135128 const { url } = req . body ;
136- copyObjectInS3 ( url , req . user . id ) . then ( ( newUrl ) => {
137- res . json ( { url : newUrl } ) ;
138- } ) ;
129+ const newUrl = await copyObjectInS3 ( url , req . user . id ) ;
130+ res . json ( { url : newUrl } ) ;
139131}
140132
141- export function moveObjectToUserInS3 ( url , userId ) {
142- return new Promise ( ( resolve , reject ) => {
143- const objectKey = getObjectKey ( url ) ;
144- const fileExtension = getExtension ( objectKey ) ;
145- const newFilename = uuidv4 ( ) + fileExtension ;
133+ export async function moveObjectToUserInS3 ( url , userId ) {
134+ const objectKey = getObjectKey ( url ) ;
135+ const fileExtension = getExtension ( objectKey ) ;
136+ const newFilename = uuidv4 ( ) + fileExtension ;
137+
138+ try {
146139 const headParams = {
147- Bucket : ` ${ process . env . S3_BUCKET } ` ,
148- Key : ` ${ objectKey } `
140+ Bucket : process . env . S3_BUCKET ,
141+ Key : objectKey
149142 } ;
150- client . s3 . headObject ( headParams , ( headErr ) => {
151- if ( headErr ) {
152- reject (
153- new Error (
154- `Object with key ${ process . env . S3_BUCKET } /${ objectKey } does not exist.`
155- )
156- ) ;
157- return ;
158- }
159- const params = {
160- Bucket : `${ process . env . S3_BUCKET } ` ,
161- CopySource : `${ process . env . S3_BUCKET } /${ objectKey } ` ,
162- Key : `${ userId } /${ newFilename } ` ,
163- ACL : 'public-read'
164- } ;
165- const move = client . moveObject ( params ) ;
166- move . on ( 'err' , ( err ) => {
167- reject ( err ) ;
168- } ) ;
169- move . on ( 'end' , ( data ) => {
170- resolve ( `${ s3Bucket } ${ userId } /${ newFilename } ` ) ;
171- } ) ;
172- } ) ;
173- } ) ;
143+ await s3Client . send ( new HeadObjectCommand ( headParams ) ) ;
144+ } catch ( headErr ) {
145+ throw new Error (
146+ `Object with key ${ process . env . S3_BUCKET } /${ objectKey } does not exist.`
147+ ) ;
148+ }
149+
150+ const params = {
151+ Bucket : process . env . S3_BUCKET ,
152+ CopySource : `${ process . env . S3_BUCKET } /${ objectKey } ` ,
153+ Key : `${ userId } /${ newFilename } ` ,
154+ ACL : 'public-read'
155+ } ;
156+
157+ await s3Client . send ( new CopyObjectCommand ( params ) ) ;
158+ return `${ s3Bucket } ${ userId } /${ newFilename } ` ;
174159}
175160
176- export function listObjectsInS3ForUser ( userId ) {
177- let assets = [ ] ;
178- return new Promise ( ( resolve ) => {
161+ export async function listObjectsInS3ForUser ( userId ) {
162+ try {
163+ let assets = [ ] ;
179164 const params = {
180- s3Params : {
181- Bucket : `${ process . env . S3_BUCKET } ` ,
182- Prefix : `${ userId } /`
183- }
165+ Bucket : process . env . S3_BUCKET ,
166+ Prefix : `${ userId } /`
184167 } ;
185- client
186- . listObjects ( params )
187- . on ( 'data' , ( data ) => {
188- assets = assets . concat (
189- data . Contents . map ( ( object ) => ( {
190- key : object . Key ,
191- size : object . Size
192- } ) )
193- ) ;
194- } )
195- . on ( 'end' , ( ) => {
196- resolve ( ) ;
197- } ) ;
198- } )
199- . then ( ( ) => getProjectsForUserId ( userId ) )
200- . then ( ( projects ) => {
201- const projectAssets = [ ] ;
202- let totalSize = 0 ;
203- assets . forEach ( ( asset ) => {
204- const name = asset . key . split ( '/' ) . pop ( ) ;
205- const foundAsset = {
206- key : asset . key ,
207- name,
208- size : asset . size ,
209- url : `${ process . env . S3_BUCKET_URL_BASE } ${ asset . key } `
210- } ;
211- totalSize += asset . size ;
212- projects . some ( ( project ) => {
213- let found = false ;
214- project . files . some ( ( file ) => {
215- if ( ! file . url ) return false ;
216- if ( file . url . includes ( asset . key ) ) {
217- found = true ;
218- foundAsset . name = file . name ;
219- foundAsset . sketchName = project . name ;
220- foundAsset . sketchId = project . id ;
221- foundAsset . url = file . url ;
222- return true ;
223- }
224- return false ;
225- } ) ;
226- return found ;
168+
169+ const data = await s3Client . send ( new ListObjectsCommand ( params ) ) ;
170+
171+ assets = data . Contents . map ( ( object ) => ( {
172+ key : object . Key ,
173+ size : object . Size
174+ } ) ) ;
175+
176+ const projects = await getProjectsForUserId ( userId ) ;
177+ const projectAssets = [ ] ;
178+ let totalSize = 0 ;
179+
180+ assets . forEach ( ( asset ) => {
181+ const name = asset . key . split ( '/' ) . pop ( ) ;
182+ const foundAsset = {
183+ key : asset . key ,
184+ name,
185+ size : asset . size ,
186+ url : `${ process . env . S3_BUCKET_URL_BASE } ${ asset . key } `
187+ } ;
188+ totalSize += asset . size ;
189+
190+ projects . some ( ( project ) => {
191+ let found = false ;
192+ project . files . some ( ( file ) => {
193+ if ( ! file . url ) return false ;
194+ if ( file . url . includes ( asset . key ) ) {
195+ found = true ;
196+ foundAsset . name = file . name ;
197+ foundAsset . sketchName = project . name ;
198+ foundAsset . sketchId = project . id ;
199+ foundAsset . url = file . url ;
200+ return true ;
201+ }
202+ return false ;
227203 } ) ;
228- projectAssets . push ( foundAsset ) ;
204+ return found ;
229205 } ) ;
230- return Promise . resolve ( { assets : projectAssets , totalSize } ) ;
231- } )
232- . catch ( ( err ) => {
233- console . log ( 'got an error' ) ;
234- console . log ( err ) ;
206+ projectAssets . push ( foundAsset ) ;
235207 } ) ;
208+
209+ return { assets : projectAssets , totalSize } ;
210+ } catch ( error ) {
211+ console . log ( 'Got an error:' , error ) ;
212+ throw error ;
213+ }
236214}
237215
238216export function listObjectsInS3ForUserRequestHandler ( req , res ) {
0 commit comments