- Removed HttpError and refactored old code using it

This commit is contained in:
Alexis
2020-12-28 12:23:54 +01:00
parent 5f7e5499f7
commit f7a09c02ae
7 changed files with 311 additions and 164 deletions

View File

@@ -13,9 +13,6 @@ v.addSchema(IngredientValidation, "/IngredientValidation")
const isXSSAttempt = require('../functions').isXSSAttempt const isXSSAttempt = require('../functions').isXSSAttempt
const isEmptyObject = require('../functions').isEmptyObject const isEmptyObject = require('../functions').isEmptyObject
// Error handling
const { HttpError } = require('../validations/Errors')
class IngredientRepository { class IngredientRepository {
constructor() { constructor() {
@@ -23,22 +20,25 @@ class IngredientRepository {
getAll() { getAll() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.fetchAll({ withRelated: ['spells'] }) .fetchAll({ withRelated: ['spells'] })
.then(v => { .then(v => {
resolve(v.toJSON({ omitPivot: true })) resolve(v.toJSON({ omitPivot: true }))
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Couldn't get ingredients")) reject({
}) "message": "Il n'existe aucun ingrédient disponible.",
"code": 404,
});
})
}) })
} }
getOne(id) { getOne(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'id' : id }) .where({ 'id' : id })
.fetch({ withRelated: ['spells']}) .fetch({ withRelated: ['spells']})
.then(v => { .then(v => {
@@ -46,14 +46,17 @@ class IngredientRepository {
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Couldn't get ingredient")) reject({
"message": "L'ingrédient en question n'a pas pu être trouvé.",
"code": 404,
});
}) })
}) })
} }
getSpellsFromOne(id) { getSpellsFromOne(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'id' : id }) .where({ 'id' : id })
.fetch({ withRelated: ['spells', 'spells.schools', 'spells.variables', 'spells.ingredients', 'spells.schools.meta_schools']}) .fetch({ withRelated: ['spells', 'spells.schools', 'spells.variables', 'spells.ingredients', 'spells.schools.meta_schools']})
.then(v => { .then(v => {
@@ -61,7 +64,10 @@ class IngredientRepository {
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Couldn't get ingredient")) reject({
"message": "Les sortilèges liés à cet ingrédient n'ont pas pu être récupérés.",
"code": 404,
});
}) })
}) })
} }
@@ -70,14 +76,23 @@ class IngredientRepository {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Checks if body exists and if the model fits, and throws errors if it doesn't // Checks if body exists and if the model fits, and throws errors if it doesn't
if (isEmptyObject(igr)) { if (isEmptyObject(igr)) {
reject(new HttpError(403, "Error: Ingredient cannot be nothing !")) reject({
"message": "Le corps de la requête ne peut pas être vide.",
"code": 403,
});
} else if (!v.validate(igr, IngredientValidation).valid) { } else if (!v.validate(igr, IngredientValidation).valid) {
reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(igr, IngredientValidation).errors)) reject({
"message": `Le modèle d'ingrédient n'est pas respecté : ${v.validate(s, IngredientValidation).errors}`,
"code": 403,
});
} else if (isXSSAttempt(igr.description)) { } else if (isXSSAttempt(igr.description)) {
reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) reject({
"message": "Tentative d'injection XSS détectée, requête refusée.",
"code": 403,
});
} else { } else {
bookshelf.transaction(t => { bookshelf.transaction(t => {
return model.forge({ return new model({
'name': igr.name, 'name': igr.name,
'description': igr.description, 'description': igr.description,
}).save(null, { }).save(null, {
@@ -95,7 +110,10 @@ class IngredientRepository {
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Insert Ingredient error")) reject({
"message": "Une erreur d'insertion s'est produite.",
"code": 500,
});
}) })
} }
}) })
@@ -105,13 +123,22 @@ class IngredientRepository {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Checks if body exists and if the model fits, and throws errors if it doesn't // Checks if body exists and if the model fits, and throws errors if it doesn't
if (isEmptyObject(igr)) { if (isEmptyObject(igr)) {
reject(new HttpError(403, "Error: Ingredient cannot be nothing !")) reject({
"message": "Le corps de la requête ne peut pas être vide.",
"code": 403,
});
} else if (!v.validate(igr, IngredientValidation).valid) { } else if (!v.validate(igr, IngredientValidation).valid) {
reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(igr, IngredientValidation).errors)) reject({
"message": `Le modèle d'ingrédient n'est pas respecté : ${v.validate(s, IngredientValidation).errors}`,
"code": 403,
});
} else if (isXSSAttempt(igr.description)) { } else if (isXSSAttempt(igr.description)) {
reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) reject({
"message": "Tentative d'injection XSS détectée, requête refusée.",
"code": 403,
});
} else { } else {
model.forge({id: id}) new model({id: id})
.fetch({require: true, withRelated: ['spells']}) .fetch({require: true, withRelated: ['spells']})
.then(v => { .then(v => {
bookshelf.transaction(t => { bookshelf.transaction(t => {
@@ -135,12 +162,18 @@ class IngredientRepository {
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Update Ingredient error")) reject({
"message": "Une erreur d'insertion s'est produite.",
"code": 500,
});
}) })
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(404, "Couldn't get ingredient")) reject({
"message": "L'ingrédient en question n'a pas été trouvé.",
"code": 404,
});
}) })
} }
}) })
@@ -148,7 +181,7 @@ class IngredientRepository {
deleteOne(id) { deleteOne(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'id' : id }) .where({ 'id' : id })
.fetch({require: true, withRelated: ['spells']}) .fetch({require: true, withRelated: ['spells']})
.then(v => { .then(v => {
@@ -162,7 +195,10 @@ class IngredientRepository {
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(404, "Couldn't get ingredient")) reject({
"message": "L'ingrédient en question n'a pas été trouvé.",
"code": 404,
});
}) })
}) })
} }

View File

@@ -12,9 +12,6 @@ v.addSchema(MetaSchoolValidation, "/MetaSchoolValidation")
// Validations // Validations
const regexXSS = RegExp(/<[^>]*script/) const regexXSS = RegExp(/<[^>]*script/)
// Error handling
const { HttpError } = require('../validations/Errors')
class MetaSchoolRepository { class MetaSchoolRepository {
constructor() { constructor() {
@@ -22,21 +19,24 @@ class MetaSchoolRepository {
getAll() { getAll() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.fetchAll({ withRelated: ['schools'] }) .fetchAll({ withRelated: ['schools'] })
.then(v => { .then(v => {
resolve(v.toJSON({ omitPivot: true })) resolve(v.toJSON({ omitPivot: true }))
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Couldn't get meta schools")) reject({
"message": "Il n'existe aucune grande école disponible.",
"code": 404,
});
}) })
}) })
} }
getOne(id) { getOne(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'id' : id }) .where({ 'id' : id })
.fetch({ withRelated: ['schools']}) .fetch({ withRelated: ['schools']})
.then(v => { .then(v => {
@@ -44,7 +44,10 @@ class MetaSchoolRepository {
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Couldn't get meta school")) reject({
"message": "La grande école en question n'a pas pu être trouvée.",
"code": 404,
});
}) })
}) })
} }

View File

@@ -13,9 +13,6 @@ v.addSchema(SchoolValidation, "/SchoolValidation")
const isXSSAttempt = require('../functions').isXSSAttempt const isXSSAttempt = require('../functions').isXSSAttempt
const isEmptyObject = require('../functions').isEmptyObject const isEmptyObject = require('../functions').isEmptyObject
// Error handling
const { HttpError } = require('../validations/Errors')
class SchoolRepository { class SchoolRepository {
constructor() { constructor() {
@@ -23,44 +20,53 @@ class SchoolRepository {
getAll() { getAll() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.fetchAll({ withRelated: ['meta_schools'] }) .fetchAll({ withRelated: ['meta_schools'] })
.then(v => { .then(v => {
resolve(v.toJSON({ omitPivot: true })) resolve(v.toJSON({ omitPivot: true }))
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(500, "Couldn't get schools")) reject({
"message": "Il n'existe aucune école disponible.",
"code": 404,
});
}) })
}) })
} }
getOne(id) { getOne(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'id' : id }) .where({ 'id' : id })
.fetch({ withRelated: ['meta_schools']}) .fetch({ withRelated: ['meta_schools']})
.then(v => { .then(v => {
resolve(v.toJSON({ omitPivot: true })) resolve(v.toJSON({ omitPivot: true }))
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(500, "Couldn't get school")) reject({
"message": "L'école en question n'a pas pu être trouvée.",
"code": 404,
});
}) })
}) })
} }
getSpellsFromOne(id) { getSpellsFromOne(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'id' : id }) .where({ 'id' : id })
.fetch({ withRelated: ['spells', 'spells.schools', 'spells.variables', 'spells.ingredients', 'spells.schools.meta_schools']}) .fetch({ withRelated: ['spells', 'spells.schools', 'spells.variables', 'spells.ingredients', 'spells.schools.meta_schools']})
.then(v => { .then(v => {
resolve(v.toJSON({ omitPivot: true })) resolve(v.toJSON({ omitPivot: true }))
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(500, "Couldn't get spells from school")) reject({
"message": "Les sortilèges de cette école n'ont pas pu être récupérés.",
"code": 404,
});
}) })
}) })
} }
@@ -69,14 +75,23 @@ class SchoolRepository {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Checks if body exists and if the model fits, and throws errors if it doesn't // Checks if body exists and if the model fits, and throws errors if it doesn't
if (isEmptyObject(s)) { if (isEmptyObject(s)) {
reject(new HttpError(403, "Error: School cannot be nothing !")) reject({
"message": "Le corps de la requête ne peut pas être vide.",
"code": 403,
});
} else if (!v.validate(s, SchoolValidation).valid) { } else if (!v.validate(s, SchoolValidation).valid) {
reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, SchoolValidation).errors)) reject({
"message": `Le modèle d'école n'est pas respecté : ${v.validate(s, SchoolValidation).errors}`,
"code": 403,
});
} else if (isXSSAttempt(s.name) || isXSSAttempt(s.description)) { } else if (isXSSAttempt(s.name) || isXSSAttempt(s.description)) {
reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) reject({
"message": "Tentative d'injection XSS détectée, requête refusée.",
"code": 403,
});
} else { } else {
bookshelf.transaction(t => { bookshelf.transaction(t => {
return model.forge({ return new model({
'name': s.name, 'name': s.name,
'description': s.description, 'description': s.description,
'meta_school_id': s.meta_school_id, 'meta_school_id': s.meta_school_id,
@@ -88,14 +103,17 @@ class SchoolRepository {
}) })
}) })
.then(v => { .then(v => {
return v.load(['meta_schools']) return v.load(['meta_schools']);
}) })
.then(v => { .then(v => {
resolve(this.getOne(v.id)) resolve(this.getOne(v.id));
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Insert School error")) reject({
"message": "Une erreur d'insertion s'est produite.",
"code": 500,
})
}) })
} }
}) })
@@ -105,13 +123,22 @@ class SchoolRepository {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Checks if body exists and if the model fits, and throws errors if it doesn't // Checks if body exists and if the model fits, and throws errors if it doesn't
if (isEmptyObject(s)) { if (isEmptyObject(s)) {
reject(new HttpError(403, "Error: School cannot be nothing !")) reject({
"message": "Le corps de la requête ne peut pas être vide.",
"code": 403,
});
} else if (!v.validate(s, SchoolValidation).valid) { } else if (!v.validate(s, SchoolValidation).valid) {
reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, SchoolValidation).errors)) reject({
"message": `Le modèle d'école n'est pas respecté : ${v.validate(s, SchoolValidation).errors}`,
"code": 403,
});
} else if (isXSSAttempt(s.name) || isXSSAttempt(s.description)) { } else if (isXSSAttempt(s.name) || isXSSAttempt(s.description)) {
reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) reject({
"message": "Tentative d'injection XSS détectée, requête refusée.",
"code": 403,
});
} else { } else {
model.forge({id: id}) new model({id: id})
.fetch({require: true, withRelated: ['meta_schools']}) .fetch({require: true, withRelated: ['meta_schools']})
.then(v => { .then(v => {
bookshelf.transaction(t => { bookshelf.transaction(t => {
@@ -136,12 +163,18 @@ class SchoolRepository {
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Update School error")) reject({
"message": "Une erreur d'insertion s'est produite.",
"code": 500,
})
}) })
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(404, "Couldn't get school")) reject({
"message": "L'école en question n'a pas été trouvée.",
"code": 404,
});
}) })
} }
}) })
@@ -149,7 +182,7 @@ class SchoolRepository {
deleteOne(id) { deleteOne(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'id' : id }) .where({ 'id' : id })
.fetch({require: true, withRelated: ['spells', 'meta_schools']}) .fetch({require: true, withRelated: ['spells', 'meta_schools']})
.then(v => { .then(v => {
@@ -162,8 +195,11 @@ class SchoolRepository {
}) })
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(404, "Couldn't get school")) reject({
"message": "L'école en question n'a pas été trouvée.",
"code": 404,
});
}) })
}) })
} }

View File

@@ -13,9 +13,6 @@ v.addSchema(SpellValidation, "/SpellValidation")
const isXSSAttempt = require('../functions').isXSSAttempt const isXSSAttempt = require('../functions').isXSSAttempt
const isEmptyObject = require('../functions').isEmptyObject const isEmptyObject = require('../functions').isEmptyObject
// Error handling
const { HttpError } = require('../validations/Errors')
class SpellRepository { class SpellRepository {
constructor() { constructor() {
@@ -24,7 +21,7 @@ class SpellRepository {
getAll(name, description, level, charge, cost, ritual) { getAll(name, description, level, charge, cost, ritual) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let query = model.forge() let query = new model();
if (name) { query.where('name', 'like', `%${name}%`) } if (name) { query.where('name', 'like', `%${name}%`) }
if (description) { query.where('description', 'like', `%${description}%`) } if (description) { query.where('description', 'like', `%${description}%`) }
@@ -38,8 +35,11 @@ class SpellRepository {
resolve(v.toJSON({ omitPivot: true })) resolve(v.toJSON({ omitPivot: true }))
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(500, "Couldn't get spells")) reject({
"message": "Il n'existe aucun sortilège disponible.",
"code": 404,
});
}) })
}) })
} }
@@ -47,8 +47,7 @@ class SpellRepository {
getAllPublic(name, description, level, charge, cost, ritual) { getAllPublic(name, description, level, charge, cost, ritual) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let query = model.forge() let query = new model().where({ 'public' : 1 })
.where({ 'public' : 1 })
if (name) { query.where('name', 'like', `%${name}%`) } if (name) { query.where('name', 'like', `%${name}%`) }
if (description) { query.where('description', 'like', `%${description}%`) } if (description) { query.where('description', 'like', `%${description}%`) }
@@ -59,18 +58,21 @@ class SpellRepository {
query.fetchAll({ withRelated: ['schools.meta_schools', 'variables', 'ingredients'] }) query.fetchAll({ withRelated: ['schools.meta_schools', 'variables', 'ingredients'] })
.then(v => { .then(v => {
resolve(v.toJSON({ omitPivot: true })) resolve(v.toJSON({ omitPivot: true }));
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(500, "Couldn't get public spells")) reject({
"message": "Il n'existe aucun sortilège disponible.",
"code": 404,
});
}) })
}) })
} }
getPage(page) { getPage(page) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'public' : 1 }) .where({ 'public' : 1 })
.fetchPage({ .fetchPage({
pageSize: 20, pageSize: 20,
@@ -81,23 +83,29 @@ class SpellRepository {
resolve(v.toJSON({ omitPivot: true })) resolve(v.toJSON({ omitPivot: true }))
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(500, "Couldn't get public spells")) reject({
"message": "La page de sortilèges n'a pas pu être chargée",
"code": 404,
});
}) })
}) })
} }
getOne(id) { getOne(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'id' : id }) .where({ 'id' : id })
.fetch({ withRelated: ['schools.meta_schools', 'variables', 'ingredients']}) .fetch({ withRelated: ['schools.meta_schools', 'variables', 'ingredients']})
.then(v => { .then(v => {
resolve(v.toJSON({ omitPivot: true })) resolve(v.toJSON({ omitPivot: true }))
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(500, "Couldn't get spell")) reject({
"message": "Le sortilège en question n'a pas été trouvé.",
"code": 404,
});
}) })
}) })
} }
@@ -106,14 +114,23 @@ class SpellRepository {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Checks if body exists and if the model fits, and throws errors if it doesn't // Checks if body exists and if the model fits, and throws errors if it doesn't
if (isEmptyObject(s)) { if (isEmptyObject(s)) {
reject(new HttpError(403, "Error: Spell cannot be nothing !")) reject({
"message": "Le corps de la requête ne peut pas être vide.",
"code": 403,
});
} else if (!v.validate(s, SpellValidation).valid) { } else if (!v.validate(s, SpellValidation).valid) {
reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, SpellValidation).errors)) reject({
"message": `Le modèle de sortilège n'est pas respecté : ${v.validate(s, SpellValidation).errors}`,
"code": 403,
});
} else if (isXSSAttempt(s.name) || isXSSAttempt(s.description) || isXSSAttempt(s.cost)) { } else if (isXSSAttempt(s.name) || isXSSAttempt(s.description) || isXSSAttempt(s.cost)) {
reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) reject({
"message": "Tentative d'injection XSS détectée, requête refusée.",
"code": 403,
});
} else { } else {
bookshelf.transaction(t => { bookshelf.transaction(t => {
return model.forge({ return new model({
'name': s.name, 'name': s.name,
'description': s.description, 'description': s.description,
'level': s.level, 'level': s.level,
@@ -145,7 +162,11 @@ class SpellRepository {
}); });
}) })
.catch(err => { .catch(err => {
throw err console.log(err);
reject({
"message": "Un attributs du sortilège a provoqué une erreur d'insertion.",
"code": 500,
});
}) })
}) })
.then(v => { .then(v => {
@@ -155,8 +176,11 @@ class SpellRepository {
resolve(this.getOne(v.id)) resolve(this.getOne(v.id))
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(500, "Insert Spell error")) reject({
"message": "Le sortilège n'a pas pu être ajouté.",
"code": 500,
});
}) })
} }
}) })
@@ -166,13 +190,22 @@ class SpellRepository {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Checks if body exists and if the model fits, and throws errors if it doesn't // Checks if body exists and if the model fits, and throws errors if it doesn't
if (isEmptyObject(s)) { if (isEmptyObject(s)) {
reject(new HttpError(403, "Error: Spell cannot be nothing !")) reject({
"message": "Le corps de la requête ne peut pas être vide.",
"code": 403,
});
} else if (!v.validate(s, SpellValidation).valid) { } else if (!v.validate(s, SpellValidation).valid) {
reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, SpellValidation).errors)) reject({
"message": `Le modèle de sortilège n'est pas respecté : ${v.validate(s, SpellValidation).errors}`,
"code": 403,
});
} else if (isXSSAttempt(s.name) || isXSSAttempt(s.description) || isXSSAttempt(s.cost)) { } else if (isXSSAttempt(s.name) || isXSSAttempt(s.description) || isXSSAttempt(s.cost)) {
reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) reject({
"message": "Tentative d'injection XSS détectée, requête refusée.",
"code": 403,
});
} else { } else {
model.forge({id: id}) new model({id: id})
.fetch({require: true, withRelated: ['schools.meta_schools', 'variables', 'ingredients']}) .fetch({require: true, withRelated: ['schools.meta_schools', 'variables', 'ingredients']})
.then(v => { .then(v => {
bookshelf.transaction(t => { bookshelf.transaction(t => {
@@ -193,14 +226,12 @@ class SpellRepository {
let schools = spell.related('school'); let schools = spell.related('school');
return spell.schools().detach(schools, { transacting: t}); return spell.schools().detach(schools, { transacting: t});
} }
return
}) })
.tap(spell => { .tap(spell => {
if (s.variables) { if (s.variables) {
let variables = spell.related('variable'); let variables = spell.related('variable');
return spell.variables().detach(variables, { transacting: t}); return spell.variables().detach(variables, { transacting: t});
} }
return
}) })
.tap(spell => { .tap(spell => {
if (s.ingredients) { if (s.ingredients) {
@@ -230,24 +261,33 @@ class SpellRepository {
}); });
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
throw err reject({
"message": "Un attributs du sortilège a provoqué une erreur d'insertion.",
"code": 500,
})
}) })
}) })
.then(v => { .then(v => {
return v.load(['schools.meta_schools', 'variables', 'ingredients']) return v.load(['schools.meta_schools', 'variables', 'ingredients']);
}) })
.then(v => { .then(v => {
resolve(this.getOne(v.id)) resolve(this.getOne(v.id));
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(500, "Update Spell error")) reject({
"message": "Une erreur de chargement est survenue.",
"code": 500,
});
}) })
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(404, "Couldn't get spell")) reject({
"message": "Le sortilège en question n'a pas été trouvé.",
"code": 404,
});
}) })
} }
}) })
@@ -255,23 +295,27 @@ class SpellRepository {
deleteOne(id) { deleteOne(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'id' : id }) .where({ 'id' : id })
.fetch({require: true, withRelated: ['schools.meta_schools', 'variables', 'ingredients']}) .fetch({require: true, withRelated: ['schools.meta_schools', 'variables', 'ingredients']})
.then(v => { .then(v => {
v.schools().detach() v.schools().detach();
v.variables().detach() v.variables().detach();
v.ingredients().detach() v.ingredients().detach();
v.destroy() v.destroy();
}) })
.then(() => { .then(() => {
resolve({ resolve({
'message': 'Spell with ID ' + id + ' successfully deleted !' "message": `Le sortilège #${id} a été supprimé avec succès.`,
}) "code": 200,
});
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err);
reject(new HttpError(404, "Couldn't get spell")) reject({
"message": "Le sortilège en question n'a pas été trouvé.",
"code": 404,
});
}) })
}) })
} }

View File

@@ -27,50 +27,50 @@ class UserRepository {
getAll() { getAll() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.fetchAll() .fetchAll()
.then(v => { .then(v => {
resolve(v.toJSON({ omitPivot: true })) resolve(v.toJSON({ omitPivot: true }));
}) })
.catch(() => { .catch(() => {
reject({ reject({
"message": "Erreur de base de données, les utilisateurs n'ont pas pu être récupérés.", "message": "Erreur de base de données, les utilisateurs n'ont pas pu être récupérés.",
"code": 500 "code": 500,
}) });
}) })
}) })
} }
getOneByUUID(uuid, full) { getOneByUUID(uuid, full) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'uuid' : uuid }) .where({ 'uuid' : uuid })
.fetch() .fetch()
.then(v => { .then(v => {
resolve(v.toJSON({ omitPivot: true, visibility: !full })) resolve(v.toJSON({ omitPivot: true, visibility: !full }));
}) })
.catch(err => { .catch(() => {
reject({ reject({
"message": "L'utilisateur avec cet UUID n'a pas été trouvé.", "message": "L'utilisateur avec cet UUID n'a pas été trouvé.",
"code": 404 "code": 404,
}) });
}) })
}) })
} }
getOneByEmail(mail, full) { getOneByEmail(mail, full) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'mail': mail }) .where({ 'mail': mail })
.fetch() .fetch()
.then(v => { .then(v => {
resolve(v.toJSON({ omitPivot: true, visibility: !full })) resolve(v.toJSON({ omitPivot: true, visibility: !full }));
}) })
.catch(() => { .catch(() => {
reject({ reject({
"message": "L'utilisateur avec cet email n'a pas été trouvé.", "message": "L'utilisateur avec cet email n'a pas été trouvé.",
"code": 404 "code": 404,
}) });
}) })
}) })
} }
@@ -81,17 +81,17 @@ class UserRepository {
if (isEmptyObject(u)) { if (isEmptyObject(u)) {
reject({ reject({
"message": "Le corps de requête ne peut être vide.", "message": "Le corps de requête ne peut être vide.",
"code": 403 "code": 403,
}) })
} else if (!v.validate(u, UserValidation).valid) { } else if (!v.validate(u, UserValidation).valid) {
reject({ reject({
"message": "Structure de la requête invalide - " + v.validate(u, UserValidation).errors, "message": "Structure de la requête invalide - " + v.validate(u, UserValidation).errors,
"code": 403 "code": 403,
}) })
} else if (isXSSAttempt(u.name) || isXSSAttempt(u.password) || isXSSAttempt(u.mail)) { } else if (isXSSAttempt(u.name) || isXSSAttempt(u.password) || isXSSAttempt(u.mail)) {
reject({ reject({
"message": "Essai d'injection détecté, avortement de la requête.", "message": "Essai d'injection détecté, avortement de la requête.",
"code": 403 "code": 403,
}) })
} else { } else {
let hash = await bcrypt.hash(u.password, 10) let hash = await bcrypt.hash(u.password, 10)
@@ -102,7 +102,7 @@ class UserRepository {
this.checkIfEmailAvailable(u.mail) this.checkIfEmailAvailable(u.mail)
.then(() => { .then(() => {
bookshelf.transaction(t => { bookshelf.transaction(t => {
return model.forge({ return new model({
'uuid': uuid, 'uuid': uuid,
'name': u.name, 'name': u.name,
'mail': u.mail, 'mail': u.mail,
@@ -113,7 +113,11 @@ class UserRepository {
transacting: t transacting: t
}) })
.catch(err => { .catch(err => {
throw err console.log(err);
reject({
"message": "Un attributs de l'utilisateur a provoqué une erreur d'insertion.",
"code": 500,
});
}) })
}) })
.then(() => { .then(() => {
@@ -153,7 +157,7 @@ class UserRepository {
verifyUser(token) { verifyUser(token) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'verification_token' : token }) .where({ 'verification_token' : token })
.fetch() .fetch()
.then(v => { .then(v => {
@@ -176,7 +180,7 @@ class UserRepository {
.catch(() => { .catch(() => {
reject({ reject({
"message": "Le lien de vérification ne semble pas correct.", "message": "Le lien de vérification ne semble pas correct.",
"code": 404 "code": 404,
}) })
}) })
}); });
@@ -196,12 +200,12 @@ class UserRepository {
if (fetchedUser.banned) { if (fetchedUser.banned) {
reject({ reject({
"message": `L'utilisateur #${fetchedUser.name} a été banni, la connexion est impossible.`, "message": `L'utilisateur #${fetchedUser.name} a été banni, la connexion est impossible.`,
"code": 403 "code": 403,
}) })
} else if (!fetchedUser.verified) { } else if (!fetchedUser.verified) {
reject({ reject({
"message": `L'utilisateur #${fetchedUser.name} n'as pas été vérifié, le compte doit être activé avant la connexion.`, "message": `L'utilisateur #${fetchedUser.name} n'as pas été vérifié, le compte doit être activé avant la connexion.`,
"code": 401 "code": 401,
}) })
} else { } else {
resolve({ resolve({
@@ -238,13 +242,13 @@ class UserRepository {
.then(() => { .then(() => {
reject({ reject({
"message": "Cet email est déjà lié à un compte.", "message": "Cet email est déjà lié à un compte.",
"code": 409 "code": 409,
}) })
}) })
.catch(() => { .catch(() => {
resolve({ resolve({
"message": "Cet email est disponible.", "message": "Cet email est disponible.",
"code": 200 "code": 200,
}) })
}) })
}) })

View File

@@ -13,8 +13,6 @@ v.addSchema(VariableValidation, "/VariableValidation")
const isXSSAttempt = require('../functions').isXSSAttempt const isXSSAttempt = require('../functions').isXSSAttempt
const isEmptyObject = require('../functions').isEmptyObject const isEmptyObject = require('../functions').isEmptyObject
// Error handling
const { HttpError } = require('../validations/Errors')
class VariableRepository { class VariableRepository {
constructor() { constructor() {
@@ -22,14 +20,17 @@ class VariableRepository {
getAll() { getAll() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.fetchAll({ withRelated: ['spells'] }) .fetchAll({ withRelated: ['spells'] })
.then(v => { .then(v => {
resolve(v.toJSON({ omitPivot: true })) resolve(v.toJSON({ omitPivot: true }))
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Couldn't get variables")) reject({
"message": "Il n'existe aucune variable disponible.",
"code": 404,
});
}) })
}) })
} }
@@ -37,7 +38,7 @@ class VariableRepository {
getOne(id) { getOne(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'id' : id }) .where({ 'id' : id })
.fetch({ withRelated: ['spells']}) .fetch({ withRelated: ['spells']})
.then(v => { .then(v => {
@@ -45,14 +46,17 @@ class VariableRepository {
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Couldn't get variable")) reject({
"message": "La variable en question n'a pas pu être trouvée.",
"code": 404,
});
}) })
}) })
} }
getSpellsFromOne(id) { getSpellsFromOne(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'id' : id }) .where({ 'id' : id })
.fetch({ withRelated: ['spells', 'spells.schools', 'spells.variables', 'spells.ingredients', 'spells.schools.meta_schools']}) .fetch({ withRelated: ['spells', 'spells.schools', 'spells.variables', 'spells.ingredients', 'spells.schools.meta_schools']})
.then(v => { .then(v => {
@@ -60,7 +64,10 @@ class VariableRepository {
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Couldn't get variable")) reject({
"message": "Les sortilèges liés à cette variable n'ont pas pu être récupérés.",
"code": 404,
});
}) })
}) })
} }
@@ -69,14 +76,23 @@ class VariableRepository {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Checks if body exists and if the model fits, and throws errors if it doesn't // Checks if body exists and if the model fits, and throws errors if it doesn't
if (isEmptyObject(vr)) { if (isEmptyObject(vr)) {
reject(new HttpError(403, "Error: Variable cannot be nothing !")) reject({
"message": "Le corps de la requête ne peut pas être vide.",
"code": 403,
});
} else if (!v.validate(vr, VariableValidation).valid) { } else if (!v.validate(vr, VariableValidation).valid) {
reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(vr, VariableValidation).errors)) reject({
"message": `Le modèle de variable n'est pas respecté : ${v.validate(s, VariableValidation).errors}`,
"code": 403,
});
} else if (isXSSAttempt(vr.description)) { } else if (isXSSAttempt(vr.description)) {
reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) reject({
"message": "Tentative d'injection XSS détectée, requête refusée.",
"code": 403,
});
} else { } else {
bookshelf.transaction(t => { bookshelf.transaction(t => {
return model.forge({ return new model({
'description': vr.description, 'description': vr.description,
}).save(null, { }).save(null, {
transacting: t transacting: t
@@ -93,7 +109,10 @@ class VariableRepository {
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Insert Variable error")) reject({
"message": "Une erreur d'insertion s'est produite.",
"code": 500,
});
}) })
} }
}) })
@@ -103,13 +122,22 @@ class VariableRepository {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Checks if body exists and if the model fits, and throws errors if it doesn't // Checks if body exists and if the model fits, and throws errors if it doesn't
if (isEmptyObject(vr)) { if (isEmptyObject(vr)) {
reject(new HttpError(403, "Error: Variable cannot be nothing !")) reject({
"message": "Le corps de la requête ne peut pas être vide.",
"code": 403,
});
} else if (!v.validate(vr, VariableValidation).valid) { } else if (!v.validate(vr, VariableValidation).valid) {
reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(vr, VariableValidation).errors)) reject({
"message": `Le modèle de variable n'est pas respecté : ${v.validate(s, VariableValidation).errors}`,
"code": 403,
});
} else if (isXSSAttempt(vr.description)) { } else if (isXSSAttempt(vr.description)) {
reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) reject({
"message": "Tentative d'injection XSS détectée, requête refusée.",
"code": 403,
});
} else { } else {
model.forge({id: id}) new model({id: id})
.fetch({require: true, withRelated: ['spells']}) .fetch({require: true, withRelated: ['spells']})
.then(v => { .then(v => {
bookshelf.transaction(t => { bookshelf.transaction(t => {
@@ -132,12 +160,18 @@ class VariableRepository {
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(500, "Update Variable error")) reject({
"message": "Une erreur d'insertion s'est produite.",
"code": 500,
});
}) })
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(404, "Couldn't get variable")) reject({
"message": "La variable en question n'a pas été trouvée.",
"code": 404,
});
}) })
} }
}) })
@@ -145,7 +179,7 @@ class VariableRepository {
deleteOne(id) { deleteOne(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
model.forge() new model()
.where({ 'id' : id }) .where({ 'id' : id })
.fetch({require: true, withRelated: ['spells']}) .fetch({require: true, withRelated: ['spells']})
.then(v => { .then(v => {
@@ -159,7 +193,10 @@ class VariableRepository {
}) })
.catch(err => { .catch(err => {
console.log(err) console.log(err)
reject(new HttpError(404, "Couldn't get variable")) reject({
"message": "La variable en question n'a pas été trouvée.",
"code": 404,
});
}) })
}) })
} }

View File

@@ -1,13 +0,0 @@
// Http error w/ http code
class HttpError extends Error {
constructor(code, message) {
super(message)
this.name = "HttpError"
this.code = code
Error.captureStackTrace(this, this.constructor);
}
}
module.exports = {
HttpError
}