refactor: logic improvements

This commit is contained in:
Bobby 2022-09-28 10:14:08 +07:00
parent 5b19fbd9fc
commit c1bb2f5015
No known key found for this signature in database
GPG Key ID: 941839794CBF5A09
2 changed files with 22 additions and 24 deletions

View File

@ -396,7 +396,7 @@ self.edit = async (req, res) => {
throw new ClientError('Could not get album with the specified ID.') throw new ClientError('Could not get album with the specified ID.')
} }
const albumNewState = (ismoderator && typeof req.body.enabled !== 'undefined') const albumNewState = (ismoderator && req.body.enabled !== undefined)
? Boolean(req.body.enabled) ? Boolean(req.body.enabled)
: null : null

View File

@ -354,7 +354,7 @@ self.actuallyUpload = async (req, res, data = {}) => {
name = name.replace(/^dz/, '') name = name.replace(/^dz/, '')
} }
req.body[name] = field.value req.body[name] = field.value || ''
return return
} }
@ -370,12 +370,11 @@ self.actuallyUpload = async (req, res, data = {}) => {
age: data.age, age: data.age,
originalname: field.file.name || '', originalname: field.file.name || '',
mimetype: field.mime_type || '', mimetype: field.mime_type || '',
isChunk: req.body.uuid !== undefined &&
req.body.chunkindex !== undefined
} }
req.files.push(file) req.files.push(file)
if (file.isChunk) { const isChunk = typeof req.body.uuid === 'string' && Boolean(req.body.uuid)
if (isChunk) {
if (!chunkedUploads) { if (!chunkedUploads) {
throw new ClientError('Chunked uploads are disabled at the moment.') throw new ClientError('Chunked uploads are disabled at the moment.')
} else if (req.files.length > 1) { } else if (req.files.length > 1) {
@ -388,7 +387,7 @@ self.actuallyUpload = async (req, res, data = {}) => {
throw new ClientError(`${file.extname ? `${file.extname.substr(1).toUpperCase()} files` : 'Files with no extension'} are not permitted.`) throw new ClientError(`${file.extname ? `${file.extname.substr(1).toUpperCase()} files` : 'Files with no extension'} are not permitted.`)
} }
if (file.isChunk) { if (isChunk) {
// Re-map UUID property to IP-specific UUID // Re-map UUID property to IP-specific UUID
const uuid = `${req.ip}_${req.body.uuid}` const uuid = `${req.ip}_${req.body.uuid}`
// Calling initChunks() will also reset the chunked uploads' timeout // Calling initChunks() will also reset the chunked uploads' timeout
@ -420,7 +419,7 @@ self.actuallyUpload = async (req, res, data = {}) => {
readStream.once('error', _reject) readStream.once('error', _reject)
if (file.isChunk) { if (file.chunksData) {
writeStream = file.chunksData.writeStream writeStream = file.chunksData.writeStream
hashStream = file.chunksData.hashStream hashStream = file.chunksData.hashStream
} else { } else {
@ -444,7 +443,7 @@ self.actuallyUpload = async (req, res, data = {}) => {
}) })
} }
if (file.isChunk) { if (file.chunksData) {
// We listen for readStream's end event // We listen for readStream's end event
readStream.once('end', () => _resolve()) readStream.once('end', () => _resolve())
} else { } else {
@ -464,7 +463,7 @@ self.actuallyUpload = async (req, res, data = {}) => {
// Pipe readStream to writeStream // Pipe readStream to writeStream
// Do not end writeStream when readStream finishes if it's a chunk upload // Do not end writeStream when readStream finishes if it's a chunk upload
readStream readStream
.pipe(writeStream, { end: !file.isChunk }) .pipe(writeStream, { end: !file.chunksData })
}).catch(error => { }).catch(error => {
// Dispose of unfinished write & hasher streams // Dispose of unfinished write & hasher streams
if (writeStream && !writeStream.destroyed) { if (writeStream && !writeStream.destroyed) {
@ -477,13 +476,13 @@ self.actuallyUpload = async (req, res, data = {}) => {
// Re-throw error // Re-throw error
throw error throw error
}).finally(() => { }).finally(() => {
if (!file.isChunk) return if (!file.chunksData) return
// Unlisten streams' error event for this Request if it's a chunk upload // Unlisten streams' error event for this Request if it's a chunk upload
utils.unlistenEmitters([writeStream, hashStream], 'error', _reject) utils.unlistenEmitters([writeStream, hashStream], 'error', _reject)
}) })
// file.size is not populated if a chunk upload, so ignore // file.size is not populated if a chunk upload, so ignore
if (config.filterEmptyFile && !file.isChunk && file.size === 0) { if (config.filterEmptyFile && !file.chunksData && file.size === 0) {
throw new ClientError('Empty files are not allowed.') throw new ClientError('Empty files are not allowed.')
} }
} }
@ -780,22 +779,27 @@ self.finishChunks = async (req, res) => {
} }
const files = req.body.files const files = req.body.files
if (!Array.isArray(files) || !files.length) { if (!Array.isArray(files) || !files.length || files.some(file => {
return typeof file !== 'object' || !file.uuid
})) {
throw new ClientError('Bad request.') throw new ClientError('Bad request.')
} }
// Re-map UUID property to IP-specific UUID // Re-map UUID property to IP-specific UUID
files.forEach(file => { files.forEach(file => {
file.uuid = `${req.ip}_${file.uuid}` file.uuid = `${req.ip}_${file.uuid}`
file.chunksData = chunksData[file.uuid]
}) })
if (files.some(file => !file.chunksData || file.chunksData.processing)) {
throw new ClientError('Invalid file UUID, chunks data had already timed out, or is still processing. Try again?')
}
return self.actuallyFinishChunks(req, res, files) return self.actuallyFinishChunks(req, res, files)
.catch(error => { .catch(error => {
// Unlink temp files (do not wait) // Unlink temp files (do not wait)
Promise.all(files.map(async file => { Promise.all(files.map(async file => {
if (file.uuid && chunksData[file.uuid]) {
return self.cleanUpChunks(file.uuid).catch(logger.error) return self.cleanUpChunks(file.uuid).catch(logger.error)
}
})) }))
// Re-throw errors // Re-throw errors
throw error throw error
@ -805,14 +809,6 @@ self.finishChunks = async (req, res) => {
self.actuallyFinishChunks = async (req, res, files) => { self.actuallyFinishChunks = async (req, res, files) => {
const filesData = [] const filesData = []
await Promise.all(files.map(async file => { await Promise.all(files.map(async file => {
if (!file.uuid || typeof chunksData[file.uuid] === 'undefined') {
throw new ClientError('Invalid file UUID, or chunks data had already timed out. Try again?')
}
if (chunksData[file.uuid].processing) {
throw new ClientError('Previous chunk upload is still being processed. Try again?')
}
// Suspend timeout // Suspend timeout
// If the chunk errors out there, it will be immediately cleaned up anyway // If the chunk errors out there, it will be immediately cleaned up anyway
chunksData[file.uuid].clearTimeout() chunksData[file.uuid].clearTimeout()
@ -835,7 +831,7 @@ self.actuallyFinishChunks = async (req, res, files) => {
const age = self.assertRetentionPeriod(req.locals.user, file.age) const age = self.assertRetentionPeriod(req.locals.user, file.age)
let size = file.size let size = typeof file.size === 'number' ? file.size : undefined
if (size === undefined) { if (size === undefined) {
size = bytesWritten size = bytesWritten
} else if (size !== bytesWritten) { } else if (size !== bytesWritten) {
@ -906,6 +902,8 @@ self.actuallyFinishChunks = async (req, res, files) => {
} }
self.cleanUpChunks = async uuid => { self.cleanUpChunks = async uuid => {
if (!uuid || !chunksData[uuid]) return
// Dispose of unfinished write & hasher streams // Dispose of unfinished write & hasher streams
if (chunksData[uuid].writeStream && !chunksData[uuid].writeStream.destroyed) { if (chunksData[uuid].writeStream && !chunksData[uuid].writeStream.destroyed) {
chunksData[uuid].writeStream.destroy() chunksData[uuid].writeStream.destroy()