- Added getAll route for spells with bookshelf

This commit is contained in:
Alexis
2020-05-27 21:26:35 +02:00
parent 48ee8cf08f
commit 1280d6ee1f
10 changed files with 139 additions and 89 deletions

View File

@@ -29,9 +29,9 @@ CREATE TABLE IF NOT EXISTS `school` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL DEFAULT "Nom de l'école", `name` VARCHAR(255) NOT NULL DEFAULT "Nom de l'école",
`description` VARCHAR(255) DEFAULT "Description de l'école", `description` VARCHAR(255) DEFAULT "Description de l'école",
`id_meta_school` INT UNSIGNED NOT NULL, `meta_school_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
FOREIGN KEY(`id_meta_school`) REFERENCES meta_school(`id`) FOREIGN KEY(`meta_school_id`) REFERENCES meta_school(`id`)
); );
/* COMMON INGREDIENTS */ /* COMMON INGREDIENTS */
@@ -63,30 +63,30 @@ CREATE TABLE IF NOT EXISTS `user` (
/* SPELLS' SCHOOLS */ /* SPELLS' SCHOOLS */
/* One spell can have multiple (up to 3) schools */ /* One spell can have multiple (up to 3) schools */
CREATE TABLE IF NOT EXISTS `spells_schools` ( CREATE TABLE IF NOT EXISTS `spell_school` (
`id_spell` INT UNSIGNED NOT NULL, `spell_id` INT UNSIGNED NOT NULL,
`id_school` INT UNSIGNED NOT NULL, `school_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id_spell`, `id_school`), PRIMARY KEY (`spell_id`, `school_id`),
FOREIGN KEY(`id_spell`) REFERENCES spell(`id`), FOREIGN KEY(`spell_id`) REFERENCES spell(`id`),
FOREIGN KEY(`id_school`) REFERENCES school(`id`) FOREIGN KEY(`school_id`) REFERENCES school(`id`)
); );
/* SPELLS' VARIABLES */ /* SPELLS' VARIABLES */
/* One spell can have multiple (up to 2) variables of cost */ /* One spell can have multiple (up to 2) variables of cost */
CREATE TABLE IF NOT EXISTS `spells_variables` ( CREATE TABLE IF NOT EXISTS `spell_variable` (
`id_spell` INT UNSIGNED NOT NULL, `spell_id` INT UNSIGNED NOT NULL,
`id_variable` INT UNSIGNED NOT NULL, `variable_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id_spell`, `id_variable`), PRIMARY KEY (`spell_id`, `variable_id`),
FOREIGN KEY(`id_spell`) REFERENCES spell(`id`), FOREIGN KEY(`spell_id`) REFERENCES spell(`id`),
FOREIGN KEY(`id_variable`) REFERENCES variable(`id`) FOREIGN KEY(`variable_id`) REFERENCES variable(`id`)
); );
/* SPELLS' VARIABLES */ /* SPELLS' VARIABLES */
/* One spell can have multiple ingredients */ /* One spell can have multiple ingredients */
CREATE TABLE IF NOT EXISTS `spells_ingredients` ( CREATE TABLE IF NOT EXISTS `spell_ingredient` (
`id_spell` INT UNSIGNED NOT NULL, `spell_id` INT UNSIGNED NOT NULL,
`id_ingredient` INT UNSIGNED NOT NULL, `ingredient_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id_spell`, `id_ingredient`), PRIMARY KEY (`spell_id`, `ingredient_id`),
FOREIGN KEY(`id_spell`) REFERENCES spell(`id`), FOREIGN KEY(`spell_id`) REFERENCES spell(`id`),
FOREIGN KEY(`id_ingredient`) REFERENCES ingredient(`id`) FOREIGN KEY(`ingredient_id`) REFERENCES ingredient(`id`)
); );

View File

@@ -12,7 +12,7 @@ INSERT INTO `meta_school` (name, description) VALUES
('Magies autres', 'Magies trop spécifiques et ne rentrant dans aucune autre grande école.'); ('Magies autres', 'Magies trop spécifiques et ne rentrant dans aucune autre grande école.');
-- SCHOOLS -- SCHOOLS
INSERT INTO `school` (name, description, id_meta_school) VALUES INSERT INTO `school` (name, description, meta_school_id) VALUES
('Lumomancie', 'Discipline arcanique de la lumière.', 1), ('Lumomancie', 'Discipline arcanique de la lumière.', 1),
('Vitamancie', 'Discipline arcanique de la guérison et de l\'énergie vitale.', 1), ('Vitamancie', 'Discipline arcanique de la guérison et de l\'énergie vitale.', 1),
('Obstrumancie', 'Discipline arcanique de la protection et des sceaux.', 1), ('Obstrumancie', 'Discipline arcanique de la protection et des sceaux.', 1),
@@ -223,11 +223,11 @@ SCHEMA
*/ */
DELIMITER $$ DELIMITER $$
CREATE PROCEDURE insertIntoSchoolRange(IN delimiter_start INT, IN delimiter_end INT, IN school_id INT) CREATE PROCEDURE insertIntoSchoolRange(IN delimiter_start INT, IN delimiter_end INT, IN id_school INT)
BEGIN BEGIN
SET @i = delimiter_start; SET @i = delimiter_start;
WHILE @i <= delimiter_end DO WHILE @i <= delimiter_end DO
INSERT INTO spells_schools (id_spell, id_school) VALUES (@i, school_id); INSERT INTO spell_school (spell_id, school_id) VALUES (@i, id_school);
SET @i = @i + 1; SET @i = @i + 1;
END WHILE; END WHILE;
END$$ END$$

View File

@@ -6,6 +6,20 @@ const mysql = require('mysql')
let credentials_data = fs.readFileSync('./database/credentials.json') let credentials_data = fs.readFileSync('./database/credentials.json')
let credentials = JSON.parse(credentials_data) let credentials = JSON.parse(credentials_data)
// Setting up the database connection
const knex = require('knex')({
client: credentials.client,
connection: {
host : credentials.host,
user : credentials.user,
password : credentials.password,
database : credentials.database,
charset : credentials.charset
},
debug: true
})
const bookshelf = require('bookshelf')(knex)
const db = mysql.createConnection({ const db = mysql.createConnection({
host: credentials.host, host: credentials.host,
user: credentials.user, user: credentials.user,
@@ -19,4 +33,4 @@ db.on('error', err => {
} }
}) })
module.exports = { db } module.exports = { db, bookshelf }

View File

@@ -1,39 +0,0 @@
const Spell = {
"id": "/SpellModel",
"type": Object,
"properties": {
"name": { "type": "string" },
"description": { "type": "string" },
"level": { "type": "number" },
"charge": { "type": "number" },
"cost": { "type": "string" },
"is_ritual": { "type": "boolean" },
"schools": {
"type": { "type": "array" },
"items": {
"properties": {
"id": { "type": "number" },
}
}
},
"variables": {
"type": { "type": "array" },
"items": {
"properties": {
"id": { "type": "number" },
}
}
},
"ingredients": {
"type": { "type": "array" },
"items": {
"properties": {
"id": { "type": "number" },
}
}
}
},
"required": ["name", "description"]
}
module.exports = Spell

39
models/SpellValidation.js Normal file
View File

@@ -0,0 +1,39 @@
const SpellModel = {
"id": "/SpellModel",
"type": Object,
"properties": {
"name": { "type": "string" },
"description": { "type": "string" },
"level": { "type": "number" },
"charge": { "type": "number" },
"cost": { "type": "string" },
"is_ritual": { "type": "boolean" },
"schools": {
"type": { "type": "array" },
"items": {
"properties": {
"id": { "type": "number" },
}
}
},
"variables": {
"type": { "type": "array" },
"items": {
"properties": {
"id": { "type": "number" },
}
}
},
"ingredients": {
"type": { "type": "array" },
"items": {
"properties": {
"id": { "type": "number" },
}
}
}
},
"required": ["name", "description"]
}
module.exports = SpellModel

View File

@@ -15,7 +15,7 @@ const regexXSS = RegExp(/<[^>]*script/)
// Model validation // Model validation
const Validator = require('jsonschema').Validator const Validator = require('jsonschema').Validator
const v = new Validator() const v = new Validator()
const School = require("../models/School") const School = require("../models/SchoolValidation")
v.addSchema(School, "/SchoolModel") v.addSchema(School, "/SchoolModel")
// Error handling // Error handling

View File

@@ -12,11 +12,58 @@ const db = connection.db
const regexInt = RegExp(/^[1-9]\d*$/) const regexInt = RegExp(/^[1-9]\d*$/)
const regexXSS = RegExp(/<[^>]*script/) const regexXSS = RegExp(/<[^>]*script/)
// Bookshelf Models
const bookshelf = require('../database/connection').bookshelf
const Spell = bookshelf.Model.extend({
tableName: 'spell',
schools() {
return this.belongsToMany( School, 'spell_school', 'spell_id', 'school_id' )
},
variables() {
return this.belongsToMany( Variable, 'spell_variable', 'spell_id', 'variable_id' )
},
ingredients() {
return this.belongsToMany( Ingredient, 'spell_ingredient', 'spell_id', 'ingredient_id' )
}
})
const MetaSchool = bookshelf.Model.extend({
tableName: 'meta_school',
schools() {
return this.hasMany( School )
}
})
const School = bookshelf.Model.extend({
tableName: 'school',
spells() {
return this.belongsToMany( Spell, 'spell_school', 'school_id', 'spell_id')
},
meta_school() {
return this.belongsTo( MetaSchool, 'meta_school_id')
}
})
const Ingredient = bookshelf.Model.extend({
tableName: 'ingredient',
spells() {
return this.belongsToMany( Spell, 'spell_ingredient', 'ingredient_id', 'spell_id')
}
})
const Variable = bookshelf.Model.extend({
tableName: 'variable',
spells() {
return this.belongsToMany( Spell, 'spell_variable', 'variable_id', 'spell_id')
}
})
// Model validation // Model validation
const Validator = require('jsonschema').Validator const Validator = require('jsonschema').Validator
const v = new Validator() const v = new Validator()
const Spell = require("../models/Spell") const SpellModel = require("../models/SpellValidation")
v.addSchema(Spell, "/SpellModel") v.addSchema(SpellModel, "/SpellModel")
// Error handling // Error handling
const { HttpError } = require('../models/Errors') const { HttpError } = require('../models/Errors')
@@ -26,25 +73,14 @@ const { HttpError } = require('../models/Errors')
const getSpells = () => { const getSpells = () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let query = "SELECT DISTINCT * FROM spell" Spell.forge().fetchAll({ withRelated: ['schools.meta_school', 'variables', 'ingredients'] })
.then(v => {
db.query(query, async (err, result) => { resolve(v.toJSON({ omitPivot: true }))
if (err) {
reject(new HttpError(500, 'Database error'))
} else if (result.length == 0) {
reject(new HttpError(404, 'No spells were found'))
}
// Loops over the results to fetch the associated tables
for (let i = 0; i < result.length; i++) {
try {
result[i] = await buildSpell(result[i])
} catch (err) {
reject(err)
}
}
resolve(result)
}) })
.catch(err => {
reject(new HttpError(500, err.message))
})
}) })
.catch(err => { .catch(err => {
throw err throw err
@@ -113,8 +149,8 @@ const addSpell = (s) => {
// 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(new HttpError(403, "Error: Spell cannot be nothing !"))
} else if (!v.validate(s, Spell).valid) { } else if (!v.validate(s, SpellModel).valid) {
reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, Spell).errors)) 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)) { } else if (isXSSAttempt(s.name) || isXSSAttempt(s.description) || isXSSAttempt(s.cost)) {
reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) reject(new HttpError(403, 'Injection attempt detected, aborting the request.'))
} else { } else {
@@ -271,8 +307,8 @@ const updateSpell = (s, id) => {
// 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(new HttpError(403, "Error: Spell cannot be nothing !"))
} else if (!v.validate(s, Spell).valid) { } else if (!v.validate(s, SpellModel).valid) {
reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, Spell).errors)) 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)) { } else if (isXSSAttempt(s.name) || isXSSAttempt(s.description) || isXSSAttempt(s.cost)) {
reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) reject(new HttpError(403, 'Injection attempt detected, aborting the request.'))
} else { } else {

View File

@@ -16,7 +16,7 @@ const regexXSS = RegExp(/<[^>]*script/)
// Model validation // Model validation
const Validator = require('jsonschema').Validator const Validator = require('jsonschema').Validator
const v = new Validator() const v = new Validator()
const User = require("../models/User") const User = require("../models/UserValidation")
v.addSchema(User, "/UserModel") v.addSchema(User, "/UserModel")
// Error handling // Error handling