mirror of
https://github.com/BobbyWibowo/lolisafe.git
synced 2024-12-14 00:16:21 +00:00
refactor: init UserError, a custom Error object
This will be used for errors that are to be delivered to users, AND not to be logged into the server (as in it stacktraces and all). This will eventually remove the need to throw string literals. In this commit, this has only been implemented on albumsController.js, but more will soon to come.
This commit is contained in:
parent
0dfdccb25e
commit
ae31033c0c
@ -7,6 +7,8 @@ const paths = require('./pathsController')
|
||||
const perms = require('./permissionController')
|
||||
const uploadController = require('./uploadController')
|
||||
const utils = require('./utilsController')
|
||||
const apiErrorsHandler = require('./handlers/apiErrorsHandler.js')
|
||||
const UserError = require('./utils/UserError')
|
||||
const config = require('./../config')
|
||||
const logger = require('./../logger')
|
||||
const db = require('knex')(config.database)
|
||||
@ -66,10 +68,11 @@ self.getUniqueRandomName = async () => {
|
||||
return identifier
|
||||
}
|
||||
|
||||
throw 'Sorry, we could not allocate a unique random identifier. Try again?'
|
||||
throw new UserError('Failed to allocate a unique identifier for the album. Try again?', 500)
|
||||
}
|
||||
|
||||
self.list = async (req, res, next) => {
|
||||
try {
|
||||
const user = await utils.authorize(req, res)
|
||||
if (!user) return
|
||||
|
||||
@ -87,7 +90,6 @@ self.list = async (req, res, next) => {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Query albums count for pagination
|
||||
const count = await db.table('albums')
|
||||
.where(filter)
|
||||
@ -164,12 +166,12 @@ self.list = async (req, res, next) => {
|
||||
|
||||
return res.json({ success: true, albums, count, users, homeDomain })
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
return res.status(500).json({ success: false, description: 'An unexpected error occurred. Try again?' })
|
||||
return apiErrorsHandler(error, req, res, next)
|
||||
}
|
||||
}
|
||||
|
||||
self.create = async (req, res, next) => {
|
||||
try {
|
||||
const user = await utils.authorize(req, res)
|
||||
if (!user) return
|
||||
|
||||
@ -179,7 +181,6 @@ self.create = async (req, res, next) => {
|
||||
|
||||
if (!name) return res.json({ success: false, description: 'No album name specified.' })
|
||||
|
||||
try {
|
||||
const album = await db.table('albums')
|
||||
.where({
|
||||
name,
|
||||
@ -211,8 +212,7 @@ self.create = async (req, res, next) => {
|
||||
|
||||
return res.json({ success: true, id: ids[0] })
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
return res.status(500).json({ success: false, description: 'An unexpected error occurred. Try again?' })
|
||||
return apiErrorsHandler(error, req, res, next)
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,6 +222,7 @@ self.delete = async (req, res, next) => {
|
||||
}
|
||||
|
||||
self.disable = async (req, res, next) => {
|
||||
try {
|
||||
const user = await utils.authorize(req, res)
|
||||
if (!user) return
|
||||
|
||||
@ -229,7 +230,6 @@ self.disable = async (req, res, next) => {
|
||||
const purge = req.body.purge
|
||||
if (!Number.isFinite(id)) return res.json({ success: false, description: 'No album specified.' })
|
||||
|
||||
try {
|
||||
if (purge) {
|
||||
const files = await db.table('files')
|
||||
.where({
|
||||
@ -264,17 +264,14 @@ self.disable = async (req, res, next) => {
|
||||
.then(row => row.identifier)
|
||||
|
||||
await paths.unlink(path.join(paths.zips, `${identifier}.zip`))
|
||||
} catch (error) {
|
||||
if (error && error.code !== 'ENOENT') {
|
||||
logger.error(error)
|
||||
return res.status(500).json({ success: false, description: 'An unexpected error occurred. Try again?' })
|
||||
}
|
||||
}
|
||||
|
||||
return res.json({ success: true })
|
||||
} catch (error) {
|
||||
return apiErrorsHandler(error, req, res, next)
|
||||
}
|
||||
}
|
||||
|
||||
self.edit = async (req, res, next) => {
|
||||
try {
|
||||
const user = await utils.authorize(req, res)
|
||||
if (!user) return
|
||||
|
||||
@ -300,7 +297,6 @@ self.edit = async (req, res, next) => {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const album = await db.table('albums')
|
||||
.where(filter)
|
||||
.first()
|
||||
@ -358,8 +354,7 @@ self.edit = async (req, res, next) => {
|
||||
return res.json({ success: true, name })
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
return res.status(500).json({ success: false, description: 'An unexpected error occurred. Try again?' })
|
||||
return apiErrorsHandler(error, req, res, next)
|
||||
}
|
||||
}
|
||||
|
||||
@ -370,12 +365,12 @@ self.rename = async (req, res, next) => {
|
||||
}
|
||||
|
||||
self.get = async (req, res, next) => {
|
||||
try {
|
||||
const identifier = req.params.identifier
|
||||
if (identifier === undefined) {
|
||||
return res.status(401).json({ success: false, description: 'No identifier provided.' })
|
||||
}
|
||||
|
||||
try {
|
||||
const album = await db.table('albums')
|
||||
.where({
|
||||
identifier,
|
||||
@ -416,12 +411,12 @@ self.get = async (req, res, next) => {
|
||||
files
|
||||
})
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
return res.status(500).json({ success: false, description: 'An unexpected error occcured. Try again?' })
|
||||
return apiErrorsHandler(error, req, res, next)
|
||||
}
|
||||
}
|
||||
|
||||
self.generateZip = async (req, res, next) => {
|
||||
try {
|
||||
const versionString = parseInt(req.query.v)
|
||||
|
||||
const identifier = req.params.identifier
|
||||
@ -439,7 +434,6 @@ self.generateZip = async (req, res, next) => {
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
const album = await db.table('albums')
|
||||
.where({
|
||||
identifier,
|
||||
@ -547,8 +541,7 @@ self.generateZip = async (req, res, next) => {
|
||||
self.zipEmitters.get(identifier).emit('done', filePath, fileName)
|
||||
return res.download(filePath, fileName)
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
return res.status(500).json({ success: false, description: 'An unexpected error occurred. Try again?' })
|
||||
return apiErrorsHandler(error, req, res, next)
|
||||
}
|
||||
}
|
||||
|
||||
@ -589,20 +582,21 @@ self.listFiles = async (req, res, next) => {
|
||||
}
|
||||
|
||||
self.addFiles = async (req, res, next) => {
|
||||
let ids, albumid, failed, albumids
|
||||
try {
|
||||
const user = await utils.authorize(req, res)
|
||||
if (!user) return
|
||||
|
||||
const ids = req.body.ids
|
||||
ids = req.body.ids
|
||||
if (!Array.isArray(ids) || !ids.length) {
|
||||
return res.json({ success: false, description: 'No files specified.' })
|
||||
}
|
||||
|
||||
let albumid = parseInt(req.body.albumid)
|
||||
albumid = parseInt(req.body.albumid)
|
||||
if (isNaN(albumid) || albumid < 0) albumid = null
|
||||
|
||||
let failed = []
|
||||
const albumids = []
|
||||
try {
|
||||
failed = []
|
||||
albumids = []
|
||||
if (albumid !== null) {
|
||||
const album = await db.table('albums')
|
||||
.where('id', albumid)
|
||||
@ -646,14 +640,13 @@ self.addFiles = async (req, res, next) => {
|
||||
|
||||
return res.json({ success: true, failed })
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
if (failed.length === ids.length) {
|
||||
if (Array.isArray(failed) && (failed.length === ids.length)) {
|
||||
return res.json({
|
||||
success: false,
|
||||
description: `Could not ${albumid === null ? 'add' : 'remove'} any files ${albumid === null ? 'to' : 'from'} the album.`
|
||||
})
|
||||
} else {
|
||||
return res.status(500).json({ success: false, description: 'An unexpected error occurred. Try again?' })
|
||||
return apiErrorsHandler(error, req, res, next)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
30
controllers/handlers/apiErrorsHandler.js
Normal file
30
controllers/handlers/apiErrorsHandler.js
Normal file
@ -0,0 +1,30 @@
|
||||
const UserError = require('./../utils/UserError')
|
||||
const logger = require('./../../logger')
|
||||
|
||||
module.exports = (error, req, res, next) => {
|
||||
if (!res) {
|
||||
return logger.error(new Error('Missing "res" object.'))
|
||||
}
|
||||
|
||||
// Intentional error messages to be delivered to users
|
||||
const isUserError = error instanceof UserError
|
||||
|
||||
// ENOENT or missing file errors, typically harmless, so do not log stacktrace
|
||||
const isENOENTError = error instanceof Error && error.code === 'ENOENT'
|
||||
|
||||
if (!isUserError && !isENOENTError) {
|
||||
logger.error(error)
|
||||
}
|
||||
|
||||
const statusCode = isUserError
|
||||
? error.statusCode
|
||||
: 500
|
||||
|
||||
const description = isUserError
|
||||
? error.message
|
||||
: 'An unexpected error occurred. Try again?'
|
||||
|
||||
return res
|
||||
.status(statusCode)
|
||||
.json({ success: false, description })
|
||||
}
|
11
controllers/utils/UserError.js
Normal file
11
controllers/utils/UserError.js
Normal file
@ -0,0 +1,11 @@
|
||||
class UserError extends Error {
|
||||
constructor (message, statusCode) {
|
||||
super(message)
|
||||
|
||||
this.statusCode = statusCode !== undefined
|
||||
? statusCode
|
||||
: 400
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UserError
|
Loading…
Reference in New Issue
Block a user