From 7a2ab7dd5b31b4997bab17b19f82b32ee88948d5 Mon Sep 17 00:00:00 2001 From: leca Date: Thu, 31 Oct 2024 06:33:57 +0300 Subject: [PATCH] Centralized errors and added their translations. Didn't test --- messages/en-US/msgs.json | 52 +++++++ messages/ru-RU/msgs.json | 52 +++++++ src/controllers/abstractproduct.js | 89 +++++------- src/controllers/category.js | 20 ++- src/controllers/group.js | 42 +++--- src/controllers/product.js | 41 ++---- src/controllers/user.js | 37 +++-- src/middlewares/auth.js | 58 ++++---- src/middlewares/existance.js | 116 --------------- src/response/customError.js | 12 ++ src/response/errorHandler.js | 26 ++++ src/response/responseCodes.js | 218 +++++++++++++++++++++++++++++ src/routers/abstractproduct.js | 6 +- src/routers/category.js | 6 +- src/routers/group.js | 8 +- src/routers/product.js | 6 +- src/routers/user.js | 8 +- src/services/abstractproduct.js | 13 +- src/services/category.js | 8 +- src/services/group.js | 11 +- src/services/product.js | 13 +- src/services/user.js | 10 +- src/utils/log.js | 10 +- src/utils/pgerrorhandler.js | 24 +--- src/utils/status.js | 9 -- src/utils/translate.js | 7 + 26 files changed, 543 insertions(+), 359 deletions(-) create mode 100644 messages/en-US/msgs.json create mode 100644 messages/ru-RU/msgs.json delete mode 100644 src/middlewares/existance.js create mode 100644 src/response/customError.js create mode 100644 src/response/errorHandler.js create mode 100644 src/response/responseCodes.js delete mode 100644 src/utils/status.js create mode 100644 src/utils/translate.js diff --git a/messages/en-US/msgs.json b/messages/en-US/msgs.json new file mode 100644 index 0000000..7e6d4bf --- /dev/null +++ b/messages/en-US/msgs.json @@ -0,0 +1,52 @@ +{ + "authentication not found": "Authentication token not found!", + "authentication invalid": "Authentication token is invalid", + "user duplicate": "Such user already exists!", + "user invalid syntax": "Invalid syntax in one of user's parameters!", + "user already in group": "User is already in group!", + "username taken": "Username is taken!", + "username not found": "Such username not found!", + "username required": "Username is required!", + "password required": "Password is required!", + "password invalid": "Wrong password!", + "group name taken": "Group name is taken!", + "group name not found": "Group with such name not found!", + "group id not found": "Group with such ID not found!", + "group not an owner": "You are not an owner of this group!", + "group not a member": "You are not a member of this group!", + "abstract product not found": "Such abstract product is not found!", + "hash without file": "Please, supply a hash of an image!", + "file without hash": "Please, supply an image!", + "abstract product invalid syntax": "Invalid syntax in one of user's parameters!", + "barcode not found": "Such barcode not found!", + "barcode duplicate": "Such barcode already exists!", + "barcode too long": "This barcode is too long!", + "barcode invalid syntax": "Invalid syntax in barcode!", + "abstract product name not found": "Abstract product with such name not found!", + "abstract product name duplicate": "Abstract product with such name already exists!", + "abstract product name too long": "Abstract product name is too long!", + "abstract product name invalid syntax": "Invalid syntax in abstract product name!", + "net weight too long": "Specified net weight is too long!", + "net weight invalid syntax": "Invalid syntax in specified net weight!", + "image hash too long": "Specified image hash is too long!", + "image hash invalid syntax": "Invalid syntax in specified image hash!", + "category too long": "Specified category is too long!", + "category invalid syntax": "Invalid syntax in specified category!", + "category not found": "Such category not found!", + "unit too long": "Specified unit is too long!", + "unit invalid syntax": "Invalid syntax in specified unit!", + "product not found": "Such product not found!", + "product invalid syntax": "Invalid syntax in one of product's parameters!", + "abstract product id not found": "Specified abstract product id not found!", + "abstract product id invalid syntax": "Invalid syntax in abstract product id!", + "expiry date too long": "Specified expiry date is too long!", + "expiry date invalid syntax": "Invalid syntax in specified expiry date!", + "categories not found": "Such category not found!", + "categories duplicate": "Such category already exists!", + "categories invalid syntax": "Invalid syntax in one of category parameters!", + "ok": "Successfull.", + "invalid syntax": "Invalid syntax!", + "png only": "Only .png files are allowed!", + "too long": "Specified value is too long!", + "unknown": "Unknown server error. Please, contact the develoeper!" +} \ No newline at end of file diff --git a/messages/ru-RU/msgs.json b/messages/ru-RU/msgs.json new file mode 100644 index 0000000..109a142 --- /dev/null +++ b/messages/ru-RU/msgs.json @@ -0,0 +1,52 @@ +{ + "authentication not found": "Токен аутентификации не найден!", + "authentication invalid": "Токен аутентификации неверен!", + "user duplicate": "Такой пользователь уже существует!", + "user invalid syntax": "Неправильный синткасис в одном из параметров пользователя!", + "user already in group": "Пользователь уже в группе!", + "username taken": "Имя пользователя занято!", + "username not found": "Такое имя пользователя не найдено!", + "username required": "Требуется имя пользователя!", + "password required": "Требуется пароль!", + "password invalid": "Неверный пароль!", + "group name taken": "Такое имя группы уже существует!", + "group name not found": "Группы с таким именем не существует!", + "group id not found": "Группы с таким ID не существует!", + "group not an owner": "Вы не владелец этой группы!", + "group not a member": "Вы не участник этой группы!", + "abstract product not found": "Такой абстрактный продукт не найден!", + "hash without file": "Пожалуйста, укажите хеш изображения!", + "file without hash": "Пожалуйста, укажите изображение!", + "abstract product invalid syntax": "Неправильный синткасис в одном из параметров абстрактного продукта!", + "barcode not found": "Такой штрихкод не найден!", + "barcode duplicate": "Такой штрихкод уже существует!", + "barcode too long": "Этот штрихкод слишком большой!", + "barcode invalid syntax": "Этот штрихкод неверен!", + "abstract product name not found": "абстрактного продукта с таким именем не найдено!", + "abstract product name duplicate": "абстрактный продукт с таким именем уже существует!", + "abstract product name too long": "Имя абстрактного продукта слишком длинное!", + "abstract product name invalid syntax": "Неверный синткасис в имени абстрактного продукта!", + "net weight too long": "Указанный вес нетто слишком длинный!", + "net weight invalid syntax": "Неверный указанный вес нетто!", + "image hash too long": "Указанный хеш изображения слишком длинный!", + "image hash invalid syntax": "Неверный указанный хеш изображения!", + "category too long": "Указанная категория слишком длинная!", + "category invalid syntax": "Неверный синткасис в категории!", + "category not found": "Такая категория не найдена!!", + "unit too long": "Указанная единица измерения слишком длинная!", + "unit invalid syntax": "Неправильный синткасис в указанной единице измерения!", + "product not found": "Такой продукт не найден!", + "product invalid syntax": "Неверный синткасис в одном из параметров продукта!", + "abstract product id not found": "Абстрактный продукт с таким ID не найден!", + "abstract product id invalid syntax": "Неверный синткасис ID абстрактного продукта!", + "expiry date too long": "Указанная дата годен до слишком длинная!", + "expiry date invalid syntax": "Неверный синткасис в указанной дате годен до!", + "categories not found": "Накая категория не найдена!", + "categories duplicate": "Такая категория уже существует!", + "categories invalid syntax": "Неверный синткасис одного из параметров категории!", + "ok": "Успешно.", + "invalid syntax": "Неправильный синткасис!", + "png only": "Разрешены только файлы формата .png!", + "too long": "Указанное значение слишком длинное!", + "unknown": "Неизвестная ошибка сервера! Пожалуйста, сообщите разработчику!" +} \ No newline at end of file diff --git a/src/controllers/abstractproduct.js b/src/controllers/abstractproduct.js index c5f3ef2..1c292d8 100644 --- a/src/controllers/abstractproduct.js +++ b/src/controllers/abstractproduct.js @@ -1,79 +1,60 @@ import AbstractProductService from '../services/abstractproduct.js'; -import statuses from '../utils/status.js'; -import log from '../utils/log.js'; import fs from 'fs'; import path from 'path'; +import customError from '../response/customError.js'; +import responseCodes from '../response/responseCodes.js'; +import translate from '../utils/translate.js'; const TAG = "/controllers/abstractproduct.js"; class AbstractProductController { async create(req, res) { - try { - const { groupId, localId, barcode, name, net_weight, image_filename, category, unit } = req.body; + const { groupId, localId, barcode, name, net_weight, image_filename, category, unit } = req.body; - const tempPath = req.file.path; - const targetPath = path.join(path.resolve(path.dirname('')), `/uploads/${image_filename}.png`); + const tempPath = req.file.path; + const targetPath = path.join(path.resolve(path.dirname('')), `/uploads/${image_filename}.png`); - if (path.extname(req.file.originalname).toLowerCase() !== ".png") { - return res.status(400).send("Only .png files are allowed") - } - - //fs.renameSync(tempPath, targetPath); - fs.copyFileSync(tempPath, targetPath); + if (path.extname(req.file.originalname).toLowerCase() !== ".png") { fs.rmSync(tempPath); - await AbstractProductService.create(groupId, localId, barcode, name, net_weight, image_filename, category, unit); - return res.status(200).send("Successfull"); - } catch (e) { - switch (e.status) { - case statuses.duplicate: - return res.status(400).send(e.message); - default: - log.error(e.original); - return res.status(500).send(e.message); - } + throw new customError(`create abstract product only png allowed`, responseCodes.responses.general.png_only); } + + fs.copyFileSync(tempPath, targetPath); + fs.rmSync(tempPath); + + await AbstractProductService.create(groupId, localId, barcode, name, net_weight, image_filename, category, unit); + return res.status(200).send(translate(req.headers["accept-language"], responseCodes.responses.general.ok)); } async update(req, res) { - try { - let { groupId, localId, barcode, name, net_weight, image_filename, category, unit } = req.body; + let { groupId, localId, barcode, name, net_weight, image_filename, category, unit } = req.body; - const tempPath = req.file.path; - const targetPath = path.join(path.resolve(path.dirname('')) + `/uploads/${image_filename}.png`); + const tempPath = req.file.path; + const targetPath = path.join(path.resolve(path.dirname('')) + `/uploads/${image_filename}.png`); - if (barcode) await AbstractProductService.updateBarcode(groupId, localId, barcode); + if (barcode) await AbstractProductService.updateBarcode(groupId, localId, barcode); - if (name) await AbstractProductService.updateName(groupId, localId, name); + if (name) await AbstractProductService.updateName(groupId, localId, name); - if (net_weight) await AbstractProductService.updateNetWeight(groupId, localId, net_weight); + if (net_weight) await AbstractProductService.updateNetWeight(groupId, localId, net_weight); - if (image_filename && tempPath) { - //fs.renameSync(tempPath, targetPath); - fs.copyFileSync(tempPath, targetPath); - fs.rmSync(tempPath); - await AbstractProductService.updateImageFilename(groupId, localId, image_filename); - } else if (image_filename && !tempPath) { - return res.status(400).send("You must supply image file along with its hash"); - } else if (!image_file && tempPath) { - return res.status(400).send("You must supply image file hash along with file"); - } - - if (category) await AbstractProductService.updateCategory(groupId, localId, category); - - if (unit) await AbstractProductService.updateUnit(groupId, localId, unit); - - return res.status(200).send("Successfull"); - } catch (e) { - switch (e.status) { - case statuses.invalid_syntax: - log.error(e.original); - return res.status(400).send(e.message); - default: - log.error(e.original); - return res.status(500).send(e.message); - } + if (image_filename && tempPath) { + fs.copyFileSync(tempPath, targetPath); + fs.rmSync(tempPath); + await AbstractProductService.updateImageFilename(groupId, localId, image_filename); + } else if (image_filename && !tempPath) { + throw new customError(`Abstract product update image hash without file`, responseCodes.responses.abstractproducts.hash_without_file); + } else if (!image_file && tempPath) { + fs.rmSync(tempPath); + throw new customError(`Abstract product update file without image hash`, responseCodes.responses.abstractproducts.file_without_hash); } + + if (category) await AbstractProductService.updateCategory(groupId, localId, category); + + if (unit) await AbstractProductService.updateUnit(groupId, localId, unit); + + return res.status(200).send(translate(req.headers["accept-language"], responseCodes.responses.general.ok)); } }; diff --git a/src/controllers/category.js b/src/controllers/category.js index 8f8650f..6f94bed 100644 --- a/src/controllers/category.js +++ b/src/controllers/category.js @@ -1,25 +1,23 @@ import CategoryService from "../services/category.js"; -import log from "../utils/log.js"; +import translate from "../utils/translate.js"; + const TAG = "controllers/category.js"; class CategoryController { async create(req, res) { - try { - const { localId, categoryName, groupId } = req.body; + const { localId, categoryName, groupId } = req.body; - await CategoryService.create(groupId, localId, categoryName); - return res.status(200).send("Success"); + await CategoryService.create(groupId, localId, categoryName); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/create: ${e}`)); } + return res.status(200).send(translate(req.headers["accept-language"], responseCodes.responses.general.ok)); } async update(req, res) { - try { - const { localId, groupId, name } = req.body; + const { localId, groupId, name } = req.body; - await CategoryService.update(groupId, localId, name); - return res.status(200).send("Success"); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/update: ${e}`)); } + await CategoryService.update(groupId, localId, name); + + return res.status(200).send(translate(req.headers["accept-language"], responseCodes.responses.general.ok)); } }; diff --git a/src/controllers/group.js b/src/controllers/group.js index 2fd3a92..6d84f0d 100644 --- a/src/controllers/group.js +++ b/src/controllers/group.js @@ -2,49 +2,41 @@ import GroupService from '../services/group.js'; import UserService from '../services/user.js'; import jwt from 'jsonwebtoken'; import config from '../../config.json' with {type: "json"}; -import statuses from '../utils/status.js'; import log from '../utils/log.js'; +import translate from '../utils/translate.js'; const TAG = "/controllers/group.js"; class GroupController { async create(req, res) { - try { - let { groupName } = req.params; + let { groupName } = req.params; - let user = jwt.decode(req.headers.authorization.split(' ')[1], config.secret); - let status = await GroupService.create(groupName, user.login.id); + let user = jwt.decode(req.headers.authorization.split(' ')[1], config.secret); + let status = await GroupService.create(groupName, user.login.id); - log.info(`New group with name ${groupName} was just created by user ${user.login.username}`); + log.info(`New group with name ${groupName} was just created by user ${user.login.username}`); - UserService.joinGroup(user.login.id, status.id); - return res.status(200).send("Successfull"); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/create: ${e}`)); } + UserService.joinGroup(user.login.id, status.id); + return res.status(200).send(translate(req.headers["accept-language"], responseCodes.responses.general.ok)); } async join(req, res) { - try { - let { groupId } = req.params; + let { groupId } = req.params; - let user = jwt.decode(req.headers.authorization.split(' ')[1], config.secret); - let status = await UserService.joinGroup(user.login.id, groupId); + let user = jwt.decode(req.headers.authorization.split(' ')[1], config.secret); + await UserService.joinGroup(user.login.id, groupId); - if (status == statuses.duplicate) return res.status(400).send("Already in group"); - - log.info(`User ${user.login.username} has just joined group with ID ${groupId}`); - return res.status(200).send("Successfull"); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/join: ${e}`)); } + log.info(`User ${user.login.username} has just joined group with ID ${groupId}`); + return res.status(200).send(translate(req.headers["accept-language"], responseCodes.responses.general.ok)); } async updatePassword(req, res) { - try { - let { groupId } = req.params; - let { password } = req.body; + let { groupId } = req.params; + let { password } = req.body; - await GroupService.updatePassword(groupId, password); - log.info(`Password for group with ID ${groupId} was updated`); - return res.status(200).send("Successfull"); + await GroupService.updatePassword(groupId, password); + log.info(`Password for group with ID ${groupId} was updated`); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/updatePassword ${e}`)); } + return res.status(200).send(translate(req.headers["accept-language"], responseCodes.responses.general.ok)); } } diff --git a/src/controllers/product.js b/src/controllers/product.js index 7a0e25c..f14d851 100644 --- a/src/controllers/product.js +++ b/src/controllers/product.js @@ -1,47 +1,30 @@ import ProductService from '../services/product.js'; -import statuses from '../utils/status.js'; -import log from '../utils/log.js'; +import translate from '../utils/translate.js'; const TAG = "/controllers/product.js" class AbstractProductController { async create(req, res) { - try { - const { groupId, localId, abstract_product_id, amount, date_of_production, expiry_date } = req.body; - await ProductService.create(groupId, localId, abstract_product_id, amount, date_of_production, expiry_date); - return res.status(200).send("Successfull"); - } catch (e) { - switch (e.status) { - case statuses.duplicate: - return res.status(400).send(e.message); - default: - log.error(e.original) - return res.status(500).send(e.message) - } - } + const { groupId, localId, abstract_product_id, amount, date_of_production, expiry_date } = req.body; + + await ProductService.create(groupId, localId, abstract_product_id, amount, date_of_production, expiry_date); + + return res.status(200).send(translate(req.headers["accept-language"], responseCodes.responses.general.ok)); } async update(req, res) { - try { - let { groupId, localId, abstract_product_id, amount, date_of_production, expiry_date } = req.body; + let { groupId, localId, abstract_product_id, amount, date_of_production, expiry_date } = req.body; - if (abstract_product_id) await ProductService.updateAbstractProductId(groupId, localId, abstract_product_id); + if (abstract_product_id) await ProductService.updateAbstractProductId(groupId, localId, abstract_product_id); - if (amount) await ProductService.updateAmount(groupId, localId, amount); + if (amount) await ProductService.updateAmount(groupId, localId, amount); - if (date_of_production) await ProductService.updateDateOfProduction(groupId, localId, date_of_production); + if (date_of_production) await ProductService.updateDateOfProduction(groupId, localId, date_of_production); - if (expiry_date) await ProductService.updateExpiryDate(groupId, localId, expiry_date); - } catch (e) { - switch (e.status) { - case statuses.invalid_syntax: - log.error(e.original); - return res.status(400).send(e.message); - } - } + if (expiry_date) await ProductService.updateExpiryDate(groupId, localId, expiry_date); - return res.status(200).send("Successfull"); + return res.status(200).send(translate(req.headers["accept-language"], responseCodes.responses.general.ok)); } }; diff --git a/src/controllers/user.js b/src/controllers/user.js index b6b8072..7f37c17 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -4,44 +4,39 @@ import bcrypt from 'bcrypt'; import genToken from '../utils/jwt.js'; import AbstractProductService from '../services/abstractproduct.js'; import ProductService from '../services/product.js'; +import translate from '../utils/translate.js'; const TAG = "/controllers/userjs" class UserController { async register(req, res) { - try { - const { username, password } = req.body; + const { username, password } = req.body; - await UserService.create(username, password); + await UserService.create(username, password); - log.info(`New user with name ${username} has just registered`); - return res.status(200).send("Successfull register"); - } catch (e) { res.status(500).send(log.unknownError(`${TAG}/register: ${e}`)); } + log.info(`New user with name ${username} has just registered`); + return res.status(200).send(translate(req.headers["accept-language"], responseCodes.responses.general.ok)); } async login(req, res) { - try { - const { username, password } = req.body; + const { username, password } = req.body; - const user = await UserService.getByUsername(username); - if (!bcrypt.compareSync(password, user.password)) return res.status(401).send("Wrong password"); + const user = await UserService.getByUsername(username); + if (!bcrypt.compareSync(password, user.password)) return res.status(401).send("Wrong password"); - const token = genToken(user); - return res.status(200).send(token); - } catch (e) { res.status(500).send(log.unknownError(`${TAG}/login: ${e}`)); } + const token = genToken(user); + return res.status(200).send(translate(req.headers["accept-language"], responseCodes.responses.general.ok)); } async synchronize(req, res) { - try { - const { groupId } = req.params; + const { groupId } = req.params; - let result = {}; - result.abstract_products = await AbstractProductService.getAll(groupId); - result.products = await ProductService.getAll(groupId); - result.categories = await CategoryService.getAll(groupId); + let result = {}; + result.abstract_products = await AbstractProductService.getAll(groupId); + result.products = await ProductService.getAll(groupId); + result.categories = await CategoryService.getAll(groupId); - return res.status(200).json(result); - } catch (e) { res.status(500).send(log.unknownError(`${TAG}/synchronize: ${e}`)); } + return res.status(200).send(translate(req.headers["accept-language"], responseCodes.responses.general.ok)); } } diff --git a/src/middlewares/auth.js b/src/middlewares/auth.js index 0831996..ba71dd5 100644 --- a/src/middlewares/auth.js +++ b/src/middlewares/auth.js @@ -3,71 +3,63 @@ import jwt from 'jsonwebtoken'; import config from '../../config.json' with {type: "json"}; import GroupService from '../services/group.js'; import UserService from '../services/user.js'; +import customError from '../response/customError.js'; +import responseCodes from '../response/responseCodes.js'; const TAG = "/middlewares/auth.js"; const requireUsername = async (req, res, next) => { if (req.method == "OPTIONS") next(); - try { - const { username } = req.body; - if (!username) return res.status(400).send("Username is required"); - next(); - } catch (e) { return res.status(500).send(unknownError(`${TAG}/requireUsername: ${e}`)); } + const { username } = req.body; + if (!username) throw new customError(`requireUsername username is required`, responseCodes.responses.usernames.required) + next(); }; const requirePassword = async (req, res, next) => { if (req.method == "OPTIONS") next(); - try { - const { password } = req.body; - if (!password) return res.status(400).send("Password is required"); - next(); - } catch (e) { return res.status(500).send(unknownError(`${TAG}/requirePassword: ${e}`)); } + const { password } = req.body; + if (!password) throw new customError(`requirePassword password is required`, responseCodes.responses.passwords.required); + next(); }; const authenticate = async (req, res, next) => { if (req.method == "OPTIONS") next(); - try { - if (!req.headers.authorization) return res.status(403).send("No authorization header supplied"); - const token = req.headers.authorization.split(' ')[1]; - if (!token) return res.status(403).send("No authorization token supplied"); - if (!jwt.verify(token, config.secret)) return res.status(403).send("Authorization token is incorrect"); + if (!req.headers.authorization) throw new customError(`authenticate no authorization header`, responseCodes.responses.authentication.not_found); + const token = req.headers.authorization.split(' ')[1]; + if (!token) throw new customError(`authenticate no authorization token in header`, responseCodes.responses.authentication.not_found); + if (!jwt.verify(token, config.secret)) throw new customError(`authenticate token is invalid`, responseCodes.responses.authentication.invalid); - next(); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/authenticate: ${e}`)); } + next(); }; const authorizeGroupOwner = async (req, res, next) => { if (req.method == "OPTIONS") next(); - try { - const token = req.headers.authorization.split(' ')[1]; + const token = req.headers.authorization.split(' ')[1]; - const { groupId } = req.params; + const { groupId } = req.params; - let user = jwt.decode(token, config.secret); + let user = jwt.decode(token, config.secret); - let adminId = await GroupService.getAdminId(groupId); - if (user.login.id != adminId) return res.status(403).send("Not your group"); - next(); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/authorizeGroupOwner: ${e}`)); } + let adminId = await GroupService.getAdminId(groupId); + if (user.login.id != adminId) throw new customError(`authorizeGroupOwner not an owner`, responseCodes.responses.groups.not_an_owner) + next(); }; const checkGroupPassword = async (req, res, next) => { if (req.method == "OPTIONS") next(); - try { - const { groupId } = req.params; - const { password } = req.body; + const { groupId } = req.params; + const { password } = req.body; - const groupPassword = await GroupService.getPassword(groupId); + const groupPassword = await GroupService.getPassword(groupId); - if (groupPassword != password) return res.status(403).send("Wrong password"); - next(); + if (groupPassword != password) throw new customError(`checkGroupPassword password is invalid`, responseCodes.responses.passwords.invalid); + next(); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/checkGroupPassword: ${e}`)); } }; const userIsInGroup = async (req, res, next) => { @@ -77,7 +69,7 @@ const userIsInGroup = async (req, res, next) => { const token = req.headers.authorization.split(' ')[1]; let user = jwt.decode(token, config.secret); - if (!await UserService.isInGroup(user.login.id, groupId)) return res.status(403).send("You are not a member of this group"); + if (!await UserService.isInGroup(user.login.id, groupId)) throw new customError(`userIsInGroup not a member`, responseCodes.responses.groups.not_a_member) next(); }; diff --git a/src/middlewares/existance.js b/src/middlewares/existance.js deleted file mode 100644 index 7df7006..0000000 --- a/src/middlewares/existance.js +++ /dev/null @@ -1,116 +0,0 @@ -import UserService from '../services/user.js'; -import GroupService from '../services/group.js'; -import AbstractProductService from '../services/abstractproduct.js'; -import ProductService from '../services/product.js'; -import CategoryService from '../services/category.js'; -import log from '../utils/log.js'; -import statuses from '../utils/status.js'; - -const TAG = "/middlewares/existance.js"; - -const usernameExists = async (req, res, next) => { - try { - let { username } = req.body; - - let user = await UserService.getByUsername(username); - if (!user || user == statuses.not_found) return res.status(404).send("User not found"); - next(); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/usernameExists: ${e}`)); } -}; - -const usernameDoesntExist = async (req, res, next) => { - try { - let { username } = req.body; - - let user = await UserService.getByUsername(username); - if (user != undefined && user != statuses.not_found) return res.status(400).send("Such username already taken"); - next(); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/usernameDoesntExist: ${e}`)); } -}; - -const groupExists = async (req, res, next) => { - try { - let groupId = req.params.groupId || req.body.groupId; - - let group = await GroupService.getById(groupId); - - if (!group || group == statuses.not_found) return res.status(404).send("Group not found"); - next(); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/groupExists: ${e}`)) } -}; - -const groupDoesntExist = async (req, res, next) => { - try { - let groupId = req.params.groupId || req.body.groupId; - - let group = await GroupService.getById(groupId); - - if (group || group != statuses.not_found) return res.status(400).send("Such group already exists"); - next(); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/groupDoesntExist: ${e}`)) } -}; - -const groupNameDoesntExist = async (req, res, next) => { - try { - const { groupName } = req.params; - - let group = await GroupService.getByName(groupName); - if (group) return res.status(400).send("Such group name already exists"); - next(); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/groupNameDoesntExist: ${e}`)); } -}; - -const abstractProductExists = async (req, res, next) => { - try { - const { groupId, localId } = req.body; - - let result = await AbstractProductService.exists(groupId, localId); - if (!result) return res.status(404).send("Abstract product not found"); - next(); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/abstractProductExists: ${e}`)); } -}; - -const productExists = async (req, res, next) => { - try { - const { groupId, localId } = req.body; - - let result = await ProductService.exists(groupId, localId); - if (!result) return res.status(404).send("Product not found"); - next(); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/productExists: ${e}`)); } -}; - -const categoryNameDoesntExist = async (req, res, next) => { - try { - const { categoryName, localId, groupId } = req.body; - - let result = await CategoryService.getByName(groupId, localId, categoryName); - if (result != statuses.not_found) return res.status(400).send("Such category name exists"); - next(); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/categoryNameDoesntExist: ${e}`)); } -}; - -const categoryExists = async (req, res, next) => { - try { - const { localId, groupId } = req.body; - - let result = await CategoryService.getById(groupId, localId); - if (!result || result == statuses.not_found) return res.status(404).send("No such category"); - next(); - } catch (e) { return res.status(500).send(log.unknownError(`${TAG}/categoryExists: ${e}`)); } -}; - -export default { - usernameExists, - usernameDoesntExist, - - groupExists, - groupDoesntExist, - groupNameDoesntExist, - - abstractProductExists, - productExists, - - categoryNameDoesntExist, - categoryExists -}; \ No newline at end of file diff --git a/src/response/customError.js b/src/response/customError.js new file mode 100644 index 0000000..f4ce1b6 --- /dev/null +++ b/src/response/customError.js @@ -0,0 +1,12 @@ +class customError extends Error { + constructor(message, code) { + super(message) + if (Error.captureStackTrace) { + Error.captureStackTrace(this, customError); + } + + this.code = code; + } +} + +export default customError; \ No newline at end of file diff --git a/src/response/errorHandler.js b/src/response/errorHandler.js new file mode 100644 index 0000000..f287926 --- /dev/null +++ b/src/response/errorHandler.js @@ -0,0 +1,26 @@ +import log from "../utils/log"; +import customError from "./customError"; +import responses from './responseCodes'; +import translate from '../utils/translate.js'; + +const errorHandler = (err, req, res) => { + log.error(err); + + let language = req.headers["accept-language"]; + + if (err instanceof customError) { + return res.status(responses.getHTTPCode(err.code)).send(translate(language, code)); + } +} + +const tryHandler = (func) => { + return async (req, res, next) => { + try { + await func(req, res, next); + } catch (err) { + errorHandler(err, req, res); + } + } +} + +export default tryHandler; \ No newline at end of file diff --git a/src/response/responseCodes.js b/src/response/responseCodes.js new file mode 100644 index 0000000..b202621 --- /dev/null +++ b/src/response/responseCodes.js @@ -0,0 +1,218 @@ +import fs from 'fs'; + +const responses = { + authentication: { + not_found: "authentication not found", + invalid: "authentication invalid" + }, + user: { + duplicate: "user duplicate", + invalid_syntax: "user invalid syntax", + already_in_group: "user already in group" + }, + usernames: { + duplicate: "username taken", + not_found: "username not found", + required: "username required" + }, + passwords: { + required: "password required", + invalid: "password invalid" + }, + groups: { + duplicate: "group name taken", + name_not_found: "group name not found", + id_not_found: "group id not found", + not_an_owner: "group not an owner", + not_a_member: "group not a member" + }, + abstractproducts: { + not_found: "abstract product not found", + hash_without_file: "hash without file", + file_without_hash: "file without hash", + invalid_syntax: "abstract product invalid syntax" + }, + barcode: { + not_found: "barcode not found", + duplicate: "barcode duplicate", + too_long: "barcode too long", + invalid_syntax: "barcode invalid syntax" + }, + abstractproductname: { + not_found: "abstract product name not found", + duplicate: "abstract product name duplicate", + too_long: "abstract product name too long", + invalid_syntax: "abstract product name invalid syntax" + }, + netweight: { + too_long: "net weight too long", + invalid_syntax: "net weight invalid syntax" + }, + imagehash: { + too_long: "image hash too long", + invalid_syntax: "image hash invalid syntax" + }, + category: { + too_long: "category too long", + invalid_syntax: "category invalid syntax", + not_found: "category not found" + }, + unit: { + too_long: "unit too long", + invalid_syntax: "unit invalid syntax" + }, + products: { + not_found: "product not found", + invalid_syntax: "product invalid syntax" + }, + abstractproductid: { + not_found: "abstract product id not found", + invalid_syntax: "abstract product id invalid syntax" + }, + amount: { + too_long: "amount too long", + invalid_syntax: "amount invalid syntax" + }, + dateofproduction: { + too_long: "date of production too long", + invalid_syntax: "date of production invalid syntax" + }, + expirydate: { + too_long: "expiry date too long", + invalid_syntax: "expiry date invalid syntax" + }, + categories: { + duplicate: "categories duplicate", + not_found: "categories not found" + }, + general: { + ok: "ok", + invalid_syntax: "invalid syntax", + png_only: "png only", + too_long: "too long", + unknown: "unknown" + } +} + +const getHTTPCode = (type) => { + switch (code) { + case responses.general.ok: + return 200 + case responses.general.invalid_syntax: + return 400 + case responses.general.unknown: + return 500 + case responses.general.png_only: + return 400 + case responses.general.too_long: + return 400 + + case responses.authentication.invalid: + return 403 + case responses.authentication.not_found: + return 403 + + case responses.user.already_in_group: + return 409 + case responses.user.duplicate: + return 409 + case responses.user.invalid_syntax: + return 400 + + + case responses.usernames.duplicate: + return 409 + case responses.usernames.not_found: + return 404 + case responses.usernames.required: + return 400 + + case responses.passwords.required: + return 400 + case responses.passwords.invalid: + return 403 + + case responses.groups.id_not_found: + return 404 + case responses.groups.name_not_found: + return 404 + case responses.groups.duplicate: + return 409 + case responses.groups.not_an_owner: + return 403 + case responses.groups.not_a_member: + return 403 + + case responses.abstractproducts.not_found: + return 404 + case responses.abstractproducts.file_without_hash: + return 400 + case responses.abstractproducts.hash_without_file: + return 400 + case responses.abstractproducts.invalid_syntax: + return 400 + + case responses.abstractproductid.invalid_syntax: + return 400 + case responses.abstractproductid.not_found: + return 404 + + case responses.abstractproductname.duplicate: + return 409 + case responses.abstractproductname.invalid_syntax: + return 400 + case responses.abstractproductname.not_found: + return 404 + case responses.abstractproductname.too_long: + return 400 + + case responses.abstractproducts.file_without_hash: + return 400 + case responses.abstractproducts.hash_without_file: + return 400 + case responses.abstractproducts.invalid_syntax: + return 400 + case responses.abstractproducts.not_found: + return 404 + + case responses.amount.invalid_syntax: + return 400 + case responses.amount.too_long: + return 409 + + case responses.barcode.duplicate: + return 409 + case responses.barcode.invalid_syntax: + return 400 + case responses.barcode.not_found: + return 404 + case responses.barcode.too_long: + return 400 + + case responses.categories.duplicate: + return 409 + case responses.categories.not_found: + return 404 + + case responses.category.invalid_syntax: + return 400 + case responses.category.too_long: + return 400 + case responses.category.not_found: + return 404 + + case responses.dateofproduction.invalid_syntax: + return 400 + case responses.dateofproduction.too_long: + return 400 + + case responses.expirydate.invalid_syntax: + return 400 + case responses.expirydate.too_long: + return 400 + default: + return 500 + } +} + +export default { responses, getHTTPCode } \ No newline at end of file diff --git a/src/routers/abstractproduct.js b/src/routers/abstractproduct.js index 9ee5317..a043cce 100644 --- a/src/routers/abstractproduct.js +++ b/src/routers/abstractproduct.js @@ -1,9 +1,9 @@ import { Router } from 'express'; import auth from '../middlewares/auth.js'; import AbstractProductController from '../controllers/abstractproduct.js'; -import existance from '../middlewares/existance.js'; import multer from 'multer'; import path from 'path'; +import tryHandler from '../response/errorHandler.js'; const upload = multer(({ dest: path.join(path.resolve(path.dirname('')), "/temp") @@ -11,7 +11,7 @@ const upload = multer(({ const AbstractProductRouter = new Router(); -AbstractProductRouter.post('/create', upload.single("file"), auth.authenticate, existance.groupExists, auth.userIsInGroup, AbstractProductController.create); -AbstractProductRouter.post('/update', upload.single("file"), auth.authenticate, existance.groupExists, auth.userIsInGroup, existance.abstractProductExists, AbstractProductController.update); +AbstractProductRouter.post('/create', upload.single("file"), tryHandler(auth.authenticate), tryHandler(auth.userIsInGroup), tryHandler(AbstractProductController.create)); +AbstractProductRouter.post('/update', upload.single("file"), tryHandler(auth.authenticate), tryHandler(auth.userIsInGroup), tryHandler(AbstractProductController.update)); export default AbstractProductRouter; \ No newline at end of file diff --git a/src/routers/category.js b/src/routers/category.js index e235b67..07f7839 100644 --- a/src/routers/category.js +++ b/src/routers/category.js @@ -1,11 +1,11 @@ import { Router } from 'express'; import auth from '../middlewares/auth.js'; -import existance from '../middlewares/existance.js'; import CategoryController from '../controllers/category.js'; +import tryHandler from '../response/errorHandler.js'; const CategoryRouter = new Router(); -CategoryRouter.post('/create', auth.authenticate, existance.groupExists, existance.categoryNameDoesntExist, CategoryController.create); -CategoryRouter.post('/update', auth.authenticate, existance.groupExists, existance.categoryExists, CategoryController.update); +CategoryRouter.post('/create', tryHandler(auth.authenticate), tryHandler(CategoryController.create)); +CategoryRouter.post('/update', tryHandler(auth.authenticate), tryHandler(CategoryController.update)); export default CategoryRouter; \ No newline at end of file diff --git a/src/routers/group.js b/src/routers/group.js index 6d18890..e27571a 100644 --- a/src/routers/group.js +++ b/src/routers/group.js @@ -1,12 +1,12 @@ import { Router } from 'express'; import auth from '../middlewares/auth.js'; import GroupController from '../controllers/group.js'; -import existance from '../middlewares/existance.js'; +import tryHandler from '../response/errorHandler.js'; const GroupRouter = new Router(); -GroupRouter.post('/create/:groupName', auth.authenticate, existance.groupNameDoesntExist, GroupController.create); -GroupRouter.post('/join/:groupId', auth.authenticate, existance.groupExists, auth.requirePassword, auth.checkGroupPassword, GroupController.join); -GroupRouter.post('/password/:groupId', auth.authenticate, existance.groupExists, auth.authorizeGroupOwner, auth.requirePassword, GroupController.updatePassword); +GroupRouter.post('/create/:groupName', tryHandler(auth.authenticate), tryHandler(GroupController.create)); +GroupRouter.post('/join/:groupId', tryHandler(auth.authenticate), tryHandler(auth.requirePassword), tryHandler(auth.checkGroupPassword), tryHandler(GroupController.join)); +GroupRouter.post('/password/:groupId', tryHandler(auth.authenticate), tryHandler(auth.authorizeGroupOwner), tryHandler(auth.requirePassword), tryHandler(GroupController.updatePassword)); export default GroupRouter; \ No newline at end of file diff --git a/src/routers/product.js b/src/routers/product.js index c1ef235..07d338e 100644 --- a/src/routers/product.js +++ b/src/routers/product.js @@ -1,11 +1,11 @@ import { Router } from 'express'; import auth from '../middlewares/auth.js'; import ProductController from '../controllers/product.js' -import existance from '../middlewares/existance.js'; +import tryHandler from '../response/errorHandler.js'; const ProductRouter = new Router(); -ProductRouter.post('/create', auth.authenticate, existance.groupExists, auth.userIsInGroup, ProductController.create); -ProductRouter.post('/update', auth.authenticate, existance.groupExists, auth.userIsInGroup, existance.productExists, ProductController.update); +ProductRouter.post('/create', tryHandler(auth.authenticate), tryHandler(auth.userIsInGroup), tryHandler(ProductController.create)); +ProductRouter.post('/update', tryHandler(auth.authenticate), tryHandler(auth.userIsInGroup), tryHandler(ProductController.update)); export default ProductRouter; \ No newline at end of file diff --git a/src/routers/user.js b/src/routers/user.js index 4037de8..ff3439c 100644 --- a/src/routers/user.js +++ b/src/routers/user.js @@ -1,12 +1,12 @@ import { Router } from 'express'; import auth from '../middlewares/auth.js'; -import existance from '../middlewares/existance.js'; import UserController from '../controllers/user.js'; +import tryHandler from '../response/errorHandler.js'; const UserRouter = new Router(); -UserRouter.post('/register', auth.requireUsername, auth.requirePassword, existance.usernameDoesntExist, UserController.register); -UserRouter.post('/login', auth.requireUsername, auth.requirePassword, existance.usernameExists, UserController.login); -UserRouter.get('/synchronize/:groupId', auth.authenticate, existance.groupExists, auth.userIsInGroup, UserController.synchronize); +UserRouter.post('/register', tryHandler(auth.requireUsername), tryHandler(auth.requirePassword), tryHandler(UserController.register)); +UserRouter.post('/login', tryHandler(auth.requireUsername), tryHandler(auth.requirePassword), tryHandler(UserController.login)); +UserRouter.get('/synchronize/:groupId', tryHandler(auth.authenticate), tryHandler(auth.userIsInGroup), tryHandler(UserController.synchronize)); export default UserRouter; \ No newline at end of file diff --git a/src/services/abstractproduct.js b/src/services/abstractproduct.js index dd96c6f..9362598 100644 --- a/src/services/abstractproduct.js +++ b/src/services/abstractproduct.js @@ -1,12 +1,15 @@ import db from '../db.js'; import statuses from '../utils/status.js'; import errorHandler from '../utils/pgerrorhandler.js'; +import tryHandler from '../response/errorHandler.js'; +import responses from '../response/responseCodes.js'; +import customError from '../response/customError.js'; class AbstractProductService { async create(groupid, localid, barcode, name, net_weight, image_filename, category, unit) { await db.query("INSERT INTO abstract_products (group_id, local_id, barcode, name, net_weight, image_filename, category, unit) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", [groupid, localid, barcode, name, net_weight, image_filename, category, unit]) .catch((e) => { - errorHandler(e, "abstract product") + errorHandler(e, "abstractproduct") }); } @@ -20,21 +23,21 @@ class AbstractProductService { async updateName(groupId, localId, name) { await db.query("UPDATE abstract_products SET name = $1 WHERE group_id = $2 AND local_id = $3", [name, groupId, localId]) .catch((e) => { - errorHandler(e, "name") + errorHandler(e, "abstractproductname") }); } async updateNetWeight(groupId, localId, net_weight) { await db.query("UPDATE abstract_products SET net_weight = $1 WHERE group_id = $2 AND local_id = $3", [net_weight, groupId, localId] .catch((e) => { - errorHandler(e, "net weight") + errorHandler(e, "netweight") })); } async updateImageFilename(groupId, localId, image_filename) { await db.query("UPDATE abstract_products SET image_filename = $1 WHERE group_id = $2 AND local_id = $3", [image_filename, groupId, localId]) .catch((e) => { - errorHandler(e, "image filename") + errorHandler(e, "imagehash") }); } @@ -54,7 +57,7 @@ class AbstractProductService { async getAll(groupId) { let result = (await db.query("SELECT local_id, barcode, name, net_weight, image_filename, category, unit FROM abstract_products WHERE group_id = $1", [groupId])).rows; - if (!result) return statuses.not_found; + if (!result) throw new customError("getAll abstract products not found", responses.responses.abstractproducts.not_found) return result; } diff --git a/src/services/category.js b/src/services/category.js index e314e01..73cce2d 100644 --- a/src/services/category.js +++ b/src/services/category.js @@ -1,4 +1,6 @@ import db from '../db.js'; +import customError from '../response/customError.js'; +import responseCodes from '../response/responseCodes.js'; import statuses from '../utils/status.js'; class CategoryService { @@ -11,14 +13,14 @@ class CategoryService { } async getById(groupId, localId) { - let result = (await db.query("SELECT * FROM categories WHERE group_id = $1 AND local_id = $2", [groupId, localId])) - if (result.rowCount == 0) return statuses.not_found; + let result = (await db.query("SELECT * FROM categories WHERE group_id = $1 AND local_id = $2", [groupId, localId])); + if (result.rowCount == 0) throw new customError(`getById categorirs not found`, responseCodes.responses.category.not_found) return result.rows[0]; } async getByName(groupId, localId, name) { let result = (await db.query("SELECT * FROM categories WHERE group_id = $1 AND local_id = $2 AND name = $3", [groupId, localId, name])); - if (result.rowCount == 0) return statuses.not_found; + if (result.rowCount == 0) throw new customError(`getByName categories not found`, responseCodes.responses.category.not_found) return result.rows[0]; } } diff --git a/src/services/group.js b/src/services/group.js index 8de8802..de2e560 100644 --- a/src/services/group.js +++ b/src/services/group.js @@ -1,17 +1,18 @@ import db from '../db.js'; +import customError from '../response/customError.js'; +import responseCodes from '../response/responseCodes.js'; import errorHandler from '../utils/pgerrorhandler.js'; -import status from '../utils/status.js'; class GroupService { async create(name, creatorId) { - let res = await db.query("INSERT INTO groups (name, admin_id) VALUES ($1, $2) RETURNING ID", [name, creatorId]).catch(errorHandler); + let res = await db.query("INSERT INTO groups (name, admin_id) VALUES ($1, $2) RETURNING ID", [name, creatorId]).catch((e) => errorHandler(e, "group")); return res.rows[0]; } async getById(id) { let res = (await db.query("SELECT * FROM groups WHERE id = $1", [id])); - if (res.rowCount == 0) return status.not_found; + if (res.rowCount == 0) throw new customError(`getByUd group not found`, responseCodes.responses.groups.id_not_found); return res.rows[0]; } @@ -28,7 +29,9 @@ class GroupService { } async getByName(name) { - return (await db.query("SELECT * FROM groups WHERE name = $1", [name])).rows[0]; + let res = (await db.query("SELECT * FROM groups WHERE name = $1", [name])); + if (res.rowCount == 0) throw new customError(`getByName group not found`, responseCodes.responses.groups.name_not_found); + return res.rows[0]; } }; diff --git a/src/services/product.js b/src/services/product.js index 8eca893..d09868c 100644 --- a/src/services/product.js +++ b/src/services/product.js @@ -1,19 +1,20 @@ import db from '../db.js'; -import statuses from '../utils/status.js'; import errorHandler from '../utils/pgerrorhandler.js'; +import customError from '../response/customError.js'; +import responseCodes from '../response/responseCodes.js'; class ProductService { async create(groupid, localid, abstract_product_id, amount, date_of_production, expiry_date) { await db.query("INSERT INTO products (group_id, local_id, abstract_product_id, amount, date_of_production, expiry_date) VALUES ($1, $2, $3, $4, $5, $6)", [groupid, localid, abstract_product_id, amount, date_of_production, expiry_date]) .catch((e) => { - errorHandler(e, "Abstract Product") + errorHandler(e, "product") }); } async updateAbstractProductId(groupId, localId, abstract_product_id) { await db.query("UPDATE products SET abstract_product_id = $1 WHERE group_id = $2 AND local_id = $3", [abstract_product_id, groupId, localId]) .catch((e) => { - errorHandler(e, "abstract product id") + errorHandler(e, "abstractproductid") }); } @@ -28,20 +29,20 @@ class ProductService { async updateDateOfProduction(groupId, localId, date_of_production) { await db.query("UPDATE products SET date_of_production = $1 WHERE group_id = $2 AND local_id = $3", [date_of_production, groupId, localId]) .catch((e) => { - errorHandler(e, "date of production") + errorHandler(e, "dateofproduction") }); } async updateExpiryDate(groupId, localId, expiry_date) { await db.query("UPDATE products SET expiry_date = $1 WHERE group_id = $2 AND local_id = $3", [expiry_date, groupId, localId]) .catch((e) => { - errorHandler(e, "expiry date") + errorHandler(e, "expirydate") }); } async getAll(groupId) { let result = (await db.query("SELECT local_id, abstract_product_id, amount, date_of_production, expiry_date FROM products WHERE group_id = $1", [groupId])).rows; - if (!result) return statuses.not_found; + if (!result) throw new customError(`getAll product not found`, responseCodes.responses.products.not_found); return result; } diff --git a/src/services/user.js b/src/services/user.js index 6a96241..b0b48f7 100644 --- a/src/services/user.js +++ b/src/services/user.js @@ -1,4 +1,6 @@ import db from '../db.js' +import customError from '../response/customError.js'; +import responseCodes from '../response/responseCodes.js'; import statuses from '../utils/status.js'; import bcrypt from 'bcrypt'; @@ -12,12 +14,14 @@ class UserService { async getByUsername(username) { let user = (await db.query("SELECT * FROM Users WHERE username = $1", [username])).rows; - if (user == undefined) return statuses.not_found; + if (user == undefined) throw new customError(`getByUsername user not found`, responseCodes.responses.usernames.not_found); return (user[0]); } async getAll() { - return (await db.query("SELECT * FROM Users")).rows; + let res = await db.query("SELECT * FROM Users"); + if (res.rowCount == 0) throw new customError(`getAll user not found`, responseCodes.responses.usernames.not_found); + return res.rows[0] } async isInGroup(userId, groupId) { @@ -25,7 +29,7 @@ class UserService { } async joinGroup(userId, groupId) { - if (await (this.isInGroup(userId, groupId))) return statuses.duplicate; + if (await (this.isInGroup(userId, groupId))) throw new customError(`joinGroup user already in group`, responseCodes.responses.user.already_in_group); await db.query("UPDATE Users SET groups = array_append(groups, $1::integer) WHERE ID = $2", [groupId, userId]); return statuses.ok; } diff --git a/src/utils/log.js b/src/utils/log.js index 8c8261f..93a3764 100644 --- a/src/utils/log.js +++ b/src/utils/log.js @@ -2,23 +2,23 @@ import config from '../../config.json' with {type: "json"}; const debug = (text) => { if (config.debug) console.debug(`[D] [${Date()}]: ${text}`); -} +}; const info = (text) => { console.log(`[I] [${Date()}]: ${text}`); -} +}; const error = (text) => { console.error(`[E] [${Date()}]: ${text}`); -} +}; const warn = (text) => { console.warn(`[W] [${Date()}]: ${text}`); -} +}; const unknownError = (text) => { error(text); return "Unknown server error. Please, report to the developer"; -} +}; export default { debug, info, error, warn, unknownError }; \ No newline at end of file diff --git a/src/utils/pgerrorhandler.js b/src/utils/pgerrorhandler.js index 1baf11e..5035dc7 100644 --- a/src/utils/pgerrorhandler.js +++ b/src/utils/pgerrorhandler.js @@ -1,28 +1,16 @@ -import statuses from "./status.js"; +import customError from "../response/customError.js"; +import responseCodes from "../response/responseCodes.js"; const errorHandler = (e, obj) => { switch (e.code) { case '23505': - throw { - status: statuses.duplicate, - message: `Such ${obj} already exists` - }; + throw new customError(`Duplicate ${obj}`, responseCodes.responses[obs].duplicate) case '22007': - throw { - status: statuses.invalid_syntax, - message: `Invalid syntax in ${obj}` - }; + throw new customError(`Invalid syntax ${obj}`, responseCodes.responses.general.invalid_syntax) case '22001': - throw { - status: statuses.invalid_syntax, - message: `Value too long (${obj})` - }; + throw new customError(`Value too long ${obj}`, responseCodes.responses[obj].too_long) default: - throw { - status: statuses.unknown, - message: `Unknown error. Please, report to the developer`, - original: e - }; + throw new customError(`Unknown error ${obj}`, responseCodes.responses.general.unknown) }; }; diff --git a/src/utils/status.js b/src/utils/status.js deleted file mode 100644 index b13dd90..0000000 --- a/src/utils/status.js +++ /dev/null @@ -1,9 +0,0 @@ -const statuses = { - ok: "ok", - duplicate: "duplicate", - not_found: "not found", - invalid_syntax: "invalid syntax", - unknown: "unknown" -}; - -export default statuses; \ No newline at end of file diff --git a/src/utils/translate.js b/src/utils/translate.js new file mode 100644 index 0000000..9aebbba --- /dev/null +++ b/src/utils/translate.js @@ -0,0 +1,7 @@ +const translate = (language, code) => { + if (!language) language = "en-US" + if (!code) code = "unknown" + return JSON.parse(fs.readFileSync(`../../messages/${language}/msgs.json`).toString())[code] +} + +export default translate \ No newline at end of file