From 8932736e6a8308bd8cc896d8f63055d95d3b0e59 Mon Sep 17 00:00:00 2001 From: Alexis <35.alexis.pele@gmail.com> Date: Sat, 6 Jun 2020 16:38:08 +0200 Subject: [PATCH] jesus fucking christ finished the update spell thing why are apis like this --- repositories/spell-repository.js | 83 +++++++++++++- routes/spells.js | 186 ++----------------------------- routes/users.js | 3 + 3 files changed, 95 insertions(+), 177 deletions(-) diff --git a/repositories/spell-repository.js b/repositories/spell-repository.js index fdf2c6c..0a5b2df 100644 --- a/repositories/spell-repository.js +++ b/repositories/spell-repository.js @@ -67,7 +67,7 @@ class SpellRepository { return new Promise((resolve, reject) => { this._model.forge() .where({ 'id' : id }) - .fetch({ withRelated: ['schools.meta_schools', 'variables', 'ingredients'] }) + .fetch({ withRelated: ['schools.meta_schools', 'variables', 'ingredients']}) .then(v => { resolve(v.toJSON({ omitPivot: true })) }) @@ -138,6 +138,87 @@ class SpellRepository { }) } + updateOne(id, s) { + return new Promise((resolve, reject) => { + this._model.forge({id: id}) + .fetch({require: true, withRelated: ['schools.meta_schools', 'variables', 'ingredients']}) + .then(v => { + bookshelf.transaction(t => { + return v.save({ + 'name': s.name, + 'description': s.description, + 'level': s.level, + 'charge' : s.charge, + 'cost' : s.cost, + 'is_ritual' : s.is_ritual + }, { + method: 'update', + transacting: t + }) + // Detaches AND attaches pivot tables, dw about it + .tap(spell => { + if (s.schools) { + let schools = spell.related('school'); + return spell.schools().detach(schools, { transacting: t}); + } + return + }) + .tap(spell => { + if (s.variables) { + let variables = spell.related('variable'); + return spell.variables().detach(variables, { transacting: t}); + } + return + }) + .tap(spell => { + if (s.ingredients) { + let ingredients = spell.related('ingredient'); + return spell.ingredients().detach(ingredients, { transacting: t}); + } + }) + .tap(spell => { + return spell + .schools() + .attach(s.schools, { + transacting: t + }); + }) + .tap(spell => { + return spell + .variables() + .attach(s.variables, { + transacting: t + }); + }) + .tap(spell => { + return spell + .ingredients() + .attach(s.ingredients, { + transacting: t + }); + }) + .catch(err => { + console.log(err) + throw err + }) + }) + .then(v => { + return v.load(['schools.meta_schools', 'variables', 'ingredients']) + }) + .then(v => { + resolve(this.getOne(v.id)) + }) + .catch(err => { + console.log(err) + reject(new HttpError(500, "Update error")) + }) + }) + .catch(err => { + reject(new HttpError(404, "Couldn't get spell")) + }) + }) + } + // Check if object is null isEmptyObject = (obj) => { if (Object.keys(obj).length === 0 && obj.constructor === Object) { diff --git a/routes/spells.js b/routes/spells.js index 043b8ab..e2aefde 100644 --- a/routes/spells.js +++ b/routes/spells.js @@ -14,6 +14,9 @@ const Spells = new SpellReposity(); const regexInt = RegExp(/^[1-9]\d*$/) +// Error handling +const { HttpError } = require('../models/Errors') + // ROUTES // GET ALL ------------------ const getSpells = () => { @@ -70,6 +73,7 @@ const addSpell = (s) => { return Spells.addOne(s) .catch(err => { console.log(err) + throw err }) } router.post('/', async (req, res) => { @@ -90,186 +94,15 @@ router.post('/', async (req, res) => { // UPDATE ONE ------------------ -const updateSpell = (s, id) => { - return new Promise( async (resolve, reject) => { - - // Check if spell exists - let old_spell = await getSpell(id) - .catch(err => { - reject(err) - }) - - // Checks if body exists and if the model fits, and throws errors if it doesn't - if (isEmptyObject(s)) { - reject(new HttpError(403, "Error: Spell cannot be nothing !")) - } else if (!v.validate(s, SpellModel).valid) { - reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, SpellModel).errors)) - } else if (isXSSAttempt(s.name) || isXSSAttempt(s.description) || isXSSAttempt(s.cost)) { - reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) - } else { - - let updateSchoolsData = () => { - return new Promise((resolve, reject) => { - if (s.schools !== null) { - if (s.schools.length > 0) { - let delete_schools_query = - `DELETE FROM spells_schools WHERE id_spell = ${old_spell.id}` - - db.query(delete_schools_query, async (err, result) => { - if (err) { - reject(new HttpError(500, 'Database error - Spell school deletion failed.')) - } - }) - - for (let i = 0; i < s.schools.length; i++) { - if (!regexInt.test(s.schools[i].id)) { - reject(new HttpError(403, 'Query error - School ID should be an integer !')) - } else {} - - let update_schools_query = `INSERT INTO spells_schools (id_spell, id_school) VALUES (${old_spell.id}, ${s.schools[i].id})` - db.query(update_schools_query, async (err, result) => { - if (err) { - reject(new HttpError(404, 'Database error - No schools matching this ID')) - } else { - console.log(`Updated association school ID ${s.schools[i].id} to spell ID ${old_spell.id}`) - resolve() - } - }) - } - } else { - resolve() - } - } else { - resolve() - } - }) - } - - let updateVariablesData = () => { - return new Promise((resolve, reject) => { - if (s.variables !== null) { - if (s.variables.length > 0) { - let delete_variables_query = - `DELETE FROM spells_variables WHERE id_spell = ${old_spell.id}` - - db.query(delete_variables_query, async (err, result) => { - if (err) { - reject(new HttpError(500, 'Database error - Spell variable deletion failed.')) - } - }) - - for (let i = 0; i < s.variables.length; i++) { - if (!regexInt.test(s.variables[i].id)) { - reject(new HttpError(403, 'Query error - Variable ID should be an integer !')) - } - - let update_variables_query = `INSERT INTO spells_variables (id_spell, id_variable) VALUES (${old_spell.id}, ${s.variables[i].id})` - db.query(update_variables_query, async (err, result) => { - if (err) { - reject(new HttpError(404, 'Database error - No variables matching this ID')) - } else { - console.log(`Updated variable ID "${s.variables[i].id}" to spell ID ${old_spell.id}`) - resolve() - } - }) - } - } else { - resolve() - } - } else { - resolve() - } - }) - } - - let updateIngredientsData = () => { - return new Promise((resolve, reject) => { - if (s.ingredients !== null) { - if (s.ingredients.length > 0) { - let delete_ingredients_query = - `DELETE FROM spells_ingredients WHERE id_spell = ${old_spell.id}` - - db.query(delete_ingredients_query, async (err, result) => { - if (err) { - reject(new HttpError(500, 'Database error - Spell ingredients deletion failed.')) - } - console.log(result) - }) - - // Loops over ingredients query - for (let i = 0; i < s.ingredients.length; i++) { - if (!regexInt.test(s.ingredients[i].id)) { - reject(new HttpError(403, 'Query error - Ingredient ID should be an integer !')) - } - - let update_ingredients_query = `INSERT INTO spells_ingredients (id_spell, id_ingredient) VALUES (${old_spell.id}, ${s.ingredients[i].id})` - db.query(update_ingredients_query, async (err, result) => { - if (err) { - reject(new HttpError(404, 'Database error - No ingredients matching this ID')) - } else { - console.log(`Updated ingredient ID "${s.ingredients[i].id}" to spell ID ${old_spell.id}`) - resolve() - } - }) - } - } else { - resolve() - } - } else { - resolve() - } - }) - } - - let updateSpellData = () => { - return new Promise((resolve, reject) => { - let update_spell_query = - 'UPDATE spell SET ' - - if (s.name !== null) { update_spell_query += `name = "${s.name}" ` } - if (s.description !== null) { update_spell_query += `, description = "${s.description}" ` } - if (s.level !== null) { update_spell_query += `, level = ${s.level} ` } - if (s.charge !== null) { update_spell_query += `, charge = ${s.charge} ` } - if (s.cost !== null) { update_spell_query += `, cost = "${s.cost}" ` } - if (s.is_ritual !== null) { update_spell_query += `, is_ritual = ${s.is_ritual} ` } - - update_spell_query += ` WHERE id = ${db.escape(id)}` - - db.query(update_spell_query, async (err, result) => { - if (err) { - reject(new HttpError(500, 'Database error - Spell update failed')) - } else { - console.log(`Updated "${s.name}" on ID ${old_spell.id}, affecting ${result.affectedRows} row(s)`) - resolve() - } - }) - }) - } - - const sub_promises = [ - updateSchoolsData(), - updateVariablesData(), - updateIngredientsData() - ] - - Promise.all(sub_promises) - .then(() => { - updateSpellData() - }) - .then(() => { - resolve(getSpell(old_spell.id)) - }) - .catch(err => { - reject(err) - }) - } - }) +const updateSpell = (id, s) => { + return Spells.updateOne(id, s) .catch(err => { + console.log(err) throw err }) } router.put('/:id/', async (req, res) => { - updateSpell(req.body, req.params.id) + updateSpell(req.params.id, req.body) .then(v => { res.setHeader('Content-Type', 'application/json;charset=utf-8') res.send(JSON.stringify(v)) @@ -400,9 +233,10 @@ router.param('id', (req, res, next, id) => { if (regexInt.test(id)) { next() } else { - throw new HttpError(403, 'Provided ID must be an integer and not zero') + throw new Error; } } catch (err) { + err = new HttpError(403, 'Provided ID must be an integer and not zero') res.status(err.code).send(JSON.stringify( { "error": err.message, diff --git a/routes/users.js b/routes/users.js index 3c932c1..26ed9d2 100644 --- a/routes/users.js +++ b/routes/users.js @@ -14,6 +14,9 @@ const Users = new UserRepository(); const regexInt = RegExp(/^[1-9]\d*$/) +// Error handling +const { HttpError } = require('../models/Errors') + // ROUTES // GET ALL ------------------ const getUsers = () => {