diff --git a/app/src/Upload/store/upload.js b/app/src/Upload/store/upload.js index c47b118..41c39c8 100644 --- a/app/src/Upload/store/upload.js +++ b/app/src/Upload/store/upload.js @@ -231,7 +231,10 @@ export default { progress: { percentage: 100, humanFileSize: file.humanSize, bytesUploaded: file._File.size } } }); - if (state.files.every(f => f.uploaded)) commit('STATE', 'uploaded', { root: true }); + if (state.files.every(f => f.uploaded)) { + fetch(state.uploadURI + '/' + state.sid + '?lock=yes', { method: 'PATCH' }); + commit('STATE', 'uploaded', { root: true }); + } } }).start(); } diff --git a/lib/db.js b/lib/db.js index 3d33403..5824160 100644 --- a/lib/db.js +++ b/lib/db.js @@ -132,6 +132,19 @@ module.exports = class DB { await this.store.update(`${ sid }++${ key }`, file); } + async lock(sid) { + const files = this.get(sid); + if(!files) return; + await Promise.all(files.map(async file => { + await this.updateMetadata(sid, file.key, { buckedLocked: true }); + })); + } + + isLocked(sid) { + const files = this.get(sid); + if(!files) return false; + return files.some(file => file.metadata.buckedLocked); + } get(sid) { return this.db[sid]; diff --git a/lib/endpoints.js b/lib/endpoints.js index 93fb921..9d91b69 100644 --- a/lib/endpoints.js +++ b/lib/endpoints.js @@ -332,11 +332,25 @@ app.use(`${ config.uploadAppPath }files`, if (req.method === 'GET') return res.status(405).end(); - // Restrict upload to a file which upload completed already + // Lock bucket by PATCH /files/:sid?lock=yes + const fid = req.path.substring(1); + if(!fid.includes('++') && req.method === 'PATCH' && req.query.lock) { + await db.lock(fid); + return res.status(204).end('Bucket locked'); + } + if(['POST', 'PATCH'].includes(req.method)) { + // Restrict upload to the bucket if it is locked + if(!fid.includes('++') && db.isLocked(fid)) { + return res.status(400).end('Bucket locked'); + } try { - const fid = req.url.substring(1); const info = await store.info(fid); + // Restrict upload to the bucket if it is locked + if(info.metadata.locked) { + return res.status(400).end('Bucket locked'); + } + // Restrict upload to a file which upload completed already if(!info.isPartial) { return res.status(400).end('Upload already completed'); } @@ -363,6 +377,11 @@ app.use(`${ config.uploadAppPath }files`, const uploadLength = req.get('Upload-Length'); assert(uploadLength, 'missing Upload-Length header'); + // Restrict creating new files for locked buckets + if(db.isLocked(meta.sid)) { + return res.status(400).end('Bucket locked'); + } + meta.uploadLength = uploadLength; meta.key = uuid(); meta.createdAt = Date.now().toString();