- 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,
`name` VARCHAR(255) NOT NULL DEFAULT "Nom 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`),
FOREIGN KEY(`id_meta_school`) REFERENCES meta_school(`id`)
FOREIGN KEY(`meta_school_id`) REFERENCES meta_school(`id`)
);
/* COMMON INGREDIENTS */
@@ -63,30 +63,30 @@ CREATE TABLE IF NOT EXISTS `user` (
/* SPELLS' SCHOOLS */
/* One spell can have multiple (up to 3) schools */
CREATE TABLE IF NOT EXISTS `spells_schools` (
`id_spell` INT UNSIGNED NOT NULL,
`id_school` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id_spell`, `id_school`),
FOREIGN KEY(`id_spell`) REFERENCES spell(`id`),
FOREIGN KEY(`id_school`) REFERENCES school(`id`)
CREATE TABLE IF NOT EXISTS `spell_school` (
`spell_id` INT UNSIGNED NOT NULL,
`school_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`spell_id`, `school_id`),
FOREIGN KEY(`spell_id`) REFERENCES spell(`id`),
FOREIGN KEY(`school_id`) REFERENCES school(`id`)
);
/* SPELLS' VARIABLES */
/* One spell can have multiple (up to 2) variables of cost */
CREATE TABLE IF NOT EXISTS `spells_variables` (
`id_spell` INT UNSIGNED NOT NULL,
`id_variable` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id_spell`, `id_variable`),
FOREIGN KEY(`id_spell`) REFERENCES spell(`id`),
FOREIGN KEY(`id_variable`) REFERENCES variable(`id`)
CREATE TABLE IF NOT EXISTS `spell_variable` (
`spell_id` INT UNSIGNED NOT NULL,
`variable_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`spell_id`, `variable_id`),
FOREIGN KEY(`spell_id`) REFERENCES spell(`id`),
FOREIGN KEY(`variable_id`) REFERENCES variable(`id`)
);
/* SPELLS' VARIABLES */
/* One spell can have multiple ingredients */
CREATE TABLE IF NOT EXISTS `spells_ingredients` (
`id_spell` INT UNSIGNED NOT NULL,
`id_ingredient` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id_spell`, `id_ingredient`),
FOREIGN KEY(`id_spell`) REFERENCES spell(`id`),
FOREIGN KEY(`id_ingredient`) REFERENCES ingredient(`id`)
CREATE TABLE IF NOT EXISTS `spell_ingredient` (
`spell_id` INT UNSIGNED NOT NULL,
`ingredient_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`spell_id`, `ingredient_id`),
FOREIGN KEY(`spell_id`) REFERENCES spell(`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.');
-- 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),
('Vitamancie', 'Discipline arcanique de la guérison et de l\'énergie vitale.', 1),
('Obstrumancie', 'Discipline arcanique de la protection et des sceaux.', 1),
@@ -223,11 +223,11 @@ SCHEMA
*/
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
SET @i = delimiter_start;
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;
END WHILE;
END$$

View File

@@ -6,6 +6,20 @@ const mysql = require('mysql')
let credentials_data = fs.readFileSync('./database/credentials.json')
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({
host: credentials.host,
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
const Validator = require('jsonschema').Validator
const v = new Validator()
const School = require("../models/School")
const School = require("../models/SchoolValidation")
v.addSchema(School, "/SchoolModel")
// Error handling

View File

@@ -12,11 +12,58 @@ const db = connection.db
const regexInt = RegExp(/^[1-9]\d*$/)
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
const Validator = require('jsonschema').Validator
const v = new Validator()
const Spell = require("../models/Spell")
v.addSchema(Spell, "/SpellModel")
const SpellModel = require("../models/SpellValidation")
v.addSchema(SpellModel, "/SpellModel")
// Error handling
const { HttpError } = require('../models/Errors')
@@ -26,25 +73,14 @@ const { HttpError } = require('../models/Errors')
const getSpells = () => {
return new Promise((resolve, reject) => {
let query = "SELECT DISTINCT * FROM spell"
db.query(query, async (err, result) => {
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)
Spell.forge().fetchAll({ withRelated: ['schools.meta_school', 'variables', 'ingredients'] })
.then(v => {
resolve(v.toJSON({ omitPivot: true }))
})
.catch(err => {
reject(new HttpError(500, err.message))
})
})
.catch(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
if (isEmptyObject(s)) {
reject(new HttpError(403, "Error: Spell cannot be nothing !"))
} else if (!v.validate(s, Spell).valid) {
reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, Spell).errors))
} 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 {
@@ -271,8 +307,8 @@ const updateSpell = (s, id) => {
// 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, Spell).valid) {
reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, Spell).errors))
} 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 {

View File

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