diff --git a/api/database/auracle_db_create.sql b/api/database/auracle_db_create.sql new file mode 100644 index 0000000..1809d37 --- /dev/null +++ b/api/database/auracle_db_create.sql @@ -0,0 +1,176 @@ +DROP DATABASE IF EXISTS auracle; +CREATE DATABASE auracle CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; +USE auracle; + +/* =========== PRIMARY TABLES =========== */ + +/* PERMISSIONS */ +CREATE TABLE IF NOT EXISTS `role` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL, + `description` VARCHAR(255) NOT NULL, + PRIMARY KEY(`id`) +); + +/* USERS */ +CREATE TABLE IF NOT EXISTS `user` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `uuid` VARCHAR(36) NOT NULL, + `name` VARCHAR(255) NOT NULL DEFAULT "Disciple", + `mail` VARCHAR(255) NOT NULL, + `avatar` VARCHAR(255), + `gender` VARCHAR(255), + `password` VARCHAR(255) NOT NULL, + `role_id` INT UNSIGNED NOT NULL DEFAULT 1, + `verified` BOOLEAN DEFAULT false, + `banned` BOOLEAN DEFAULT false, + PRIMARY KEY(`id`), + FOREIGN KEY(`role_id`) REFERENCES role(`id`) +); + +/* SPELLS */ +CREATE TABLE IF NOT EXISTS `spell` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL DEFAULT "Nom du sort", + `description` VARCHAR(1000) NOT NULL DEFAULT "Description du sort", + `level` INT UNSIGNED DEFAULT 0, + `charge` INT UNSIGNED DEFAULT 0, + `cost` VARCHAR(255) DEFAULT "0", + `is_ritual` BOOLEAN DEFAULT false, + `published` BOOLEAN DEFAULT true, + `public` BOOLEAN DEFAULT true, + `author_id` INT UNSIGNED NOT NULL DEFAULT 1, + PRIMARY KEY (`id`), + FOREIGN KEY(`author_id`) REFERENCES user(`id`) +); + +/* META SCHOOLS */ +CREATE TABLE IF NOT EXISTS `meta_school` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL DEFAULT "Nom de l'école mère", + `description` VARCHAR(255) DEFAULT "Description de l'école mère", + PRIMARY KEY (`id`) +); + +/* SCHOOLS */ +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", + `meta_school_id` INT UNSIGNED NOT NULL, + PRIMARY KEY (`id`), + FOREIGN KEY(`meta_school_id`) REFERENCES meta_school(`id`) +); + +/* COMMON INGREDIENTS */ +CREATE TABLE IF NOT EXISTS `ingredient` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL DEFAULT "Langue de salamandre", + `description` VARCHAR(255) NOT NULL DEFAULT "Une langue de salamandre de feu encore chaude.", + PRIMARY KEY (`id`) +); + +/* COMMON VARIABLES */ +CREATE TABLE IF NOT EXISTS `variable` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `description` VARCHAR(255) NOT NULL DEFAULT "Nombre de créatures affectées", + PRIMARY KEY (`id`) +); + +/* ==== ASSOCIATION TABLES ==== */ + +/* SPELLS' SCHOOLS */ +/* One spell can have multiple (up to 3) schools */ +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 `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 `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`) +); + +/* Ajout d'une nouvelle ligne avant l'insert de description */ +DELIMITER $$ +CREATE TRIGGER `multiLine` BEFORE INSERT ON `spell` FOR EACH ROW +BEGIN + SET NEW.description = replace(NEW.description, '', '\n'); +END$$ +DELIMITER ; + +/* =========== PRIMARY INSERTS =========== */ +SET NAMES utf8; +USE auracle; + +-- PERMISSIONS +INSERT INTO `role` (name, description) VALUES +("Visiteur", "Utilisateur normal, peut consulter les sorts."), +("Scribe", "Gardiens des écrits, les scribes sont capables de modifier et d'ajouter des sortilèges."), +("Arcanologue", "Maîtres de l'arcane, ils ont le pouvoir et la responsabilité de juger les sortilèges récents et de les supprimer, ou valider."), +("Augure", "Régents des grimoires, ils ont droit d'accès à l'intégralité des informations connues, et pouvoir absolu sur le savoir arcanique."); + +-- META SCHOOLS +INSERT INTO `meta_school` (name, description) VALUES +('Magies blanches', 'Magies disciplinant les arts de soins et de lumières.'), +('Magies noires', 'Magies disciplinant l\'art de la mort et des secrets.'), +('Magies élémentaires', 'Magies disciplinant les éléments basiques tels que l\'eau, la foudre et le feu, pour n\'en citer que les plus populaires.'), +('Magies spirituelles', 'Magies disciplinant l\'esprit, tant pour le défendre que l\'attaquer.'), +('Magies spatio-temporelles', 'Magies régissant le temps et l\'espace.'), +('Magies affiliées', 'Magies rattachées à une forme d\'énergie magique particulière.'), +('Magies autres', 'Magies trop spécifiques et ne rentrant dans aucune autre grande école.'); + +-- SCHOOLS +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), +('Tenebromancie', 'Discipline arcanique de la lumière.', 2), +('Necromancie', 'Discipline arcanique de la mort.', 2), +('Morbomancie', 'Discipline arcanique des maladies et malédictions.', 2), +('Pyromancie', 'Discipline arcanique du feu.', 3), +('Hydromancie', 'Discipline arcanique de l\'eau.', 3), +('Electromancie', 'Discipline arcanique de la foudre.', 3), +('Terramancie', 'Discipline arcanique de la terre.', 3), +('Sidéromancie', 'Discipline arcanique des métaux rares et précieux.', 3), +('Caelomancie', 'Discipline arcanique de l\'air.', 3), +('Légimancie', 'Discipline arcanique de la lecture et du contrôle spirituel.', 4), +('Illusiomancie', 'Discipline arcanique des illusions.', 4), +('Cruciomancie', 'Discipline arcanique de la destruction spirituelle.', 4), +('Chronomancie', 'Discipline arcanique du temps.', 5), +('Spatiomancie', 'Discipline arcanique de l\'espace.', 5), +('Kénomancie', 'Discipline arcanique du néant.', 6), +('Lutomancie', 'Discipline arcanique des abysses.', 6), +('Échomancie', 'Discipline arcanique de la résolution animique.', 6), +('Protomancie', 'Discipline arcanique de la magie pure.', 7), +('Rebumancie', 'Discipline arcanique de la lumière.', 7), +('Vocamancie', 'Discipline arcanique de la lumière.', 7), +('Somamancie', 'Discipline arcanique de la maîtrise corporelle.', 7), +('Antimancie', 'Discipline arcanique de l\'annulation arcanique.', 7); + +-- INGREDIENTS +INSERT INTO `ingredient` (name, description) VALUES +('Volonté', 'La force de volonté du lanceur, concentrée sur un objectif'), +('Geste', 'Un geste précis facilitant la canalisation magique'); + +-- VARIABLES +INSERT INTO `variable` (description) VALUES +('Nombre de personnes soignées'); \ No newline at end of file diff --git a/api/database/auracle_db_schools.sql b/api/database/auracle_db_schools.sql new file mode 100644 index 0000000..ef0b0c0 --- /dev/null +++ b/api/database/auracle_db_schools.sql @@ -0,0 +1,37 @@ +USE auracle; + +/* Insertions de masses */ +DELIMITER $$ +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 spell_school (spell_id, school_id) VALUES (@i, id_school); + SET @i = @i + 1; + END WHILE; +END$$ +DELIMITER ; + +CALL insertIntoSchoolRange(1, 25, 1); +CALL insertIntoSchoolRange(26, 50, 2); +CALL insertIntoSchoolRange(51, 70, 3); +CALL insertIntoSchoolRange(71, 95, 4); +CALL insertIntoSchoolRange(96, 111, 5); +CALL insertIntoSchoolRange(112, 115, 6); +CALL insertIntoSchoolRange(116, 141, 7); +CALL insertIntoSchoolRange(142, 167, 8); +CALL insertIntoSchoolRange(168, 193, 9); +CALL insertIntoSchoolRange(194, 217, 10); +CALL insertIntoSchoolRange(218, 220, 11); +CALL insertIntoSchoolRange(221, 242, 12); +CALL insertIntoSchoolRange(243, 257, 13); +CALL insertIntoSchoolRange(258, 272, 14); +CALL insertIntoSchoolRange(273, 283, 15); +CALL insertIntoSchoolRange(284, 301, 16); +CALL insertIntoSchoolRange(302, 322, 17); +CALL insertIntoSchoolRange(323, 339, 19); +CALL insertIntoSchoolRange(340, 341, 20); +CALL insertIntoSchoolRange(342, 356, 21); +CALL insertIntoSchoolRange(357, 387, 22); +CALL insertIntoSchoolRange(388, 396, 24); +CALL insertIntoSchoolRange(397, 403, 25); diff --git a/database/bookshelf.js b/api/database/bookshelf.js similarity index 100% rename from database/bookshelf.js rename to api/database/bookshelf.js diff --git a/api/functions.js b/api/functions.js new file mode 100644 index 0000000..2fbdb92 --- /dev/null +++ b/api/functions.js @@ -0,0 +1,48 @@ +// Error handling +const { HttpError } = require('./validations/Errors') + +const regexInt = RegExp(/^[1-9]\d*$/) +const regexXSS = RegExp(/<[^>]*script/) + +// Check if int for param validation +const paramIntCheck = (req, res, next, input) => { + try { + if (regexInt.test(input)) { + next() + } else { + 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, + "code": err.code + }) + ) + } +} + +// Check if script injection attempt +const isXSSAttempt = (string) => { + if (regexXSS.test(string)) { + return true + } else { + return false + } +} + +// Check if object is null +const isEmptyObject = (obj) => { + if (Object.keys(obj).length === 0 && obj.constructor === Object) { + return true + } else { + return false + } +} + +module.exports = { + paramIntCheck, + isXSSAttempt, + isEmptyObject +} \ No newline at end of file diff --git a/index.js b/api/index.js similarity index 100% rename from index.js rename to api/index.js diff --git a/models/ingredient-model.js b/api/models/ingredient-model.js similarity index 100% rename from models/ingredient-model.js rename to api/models/ingredient-model.js diff --git a/models/meta-school-model.js b/api/models/meta-school-model.js similarity index 100% rename from models/meta-school-model.js rename to api/models/meta-school-model.js diff --git a/models/school-model.js b/api/models/school-model.js similarity index 100% rename from models/school-model.js rename to api/models/school-model.js diff --git a/models/spell-model.js b/api/models/spell-model.js similarity index 100% rename from models/spell-model.js rename to api/models/spell-model.js diff --git a/models/user-model.js b/api/models/user-model.js similarity index 85% rename from models/user-model.js rename to api/models/user-model.js index 60b5c64..9d7c019 100644 --- a/models/user-model.js +++ b/api/models/user-model.js @@ -3,6 +3,7 @@ const bookshelf = require('../database/bookshelf').bookshelf let User = bookshelf.Model.extend({ tableName: 'user', + hidden: ['id', 'password'] }) module.exports = bookshelf.model('User', User) \ No newline at end of file diff --git a/models/variable-model.js b/api/models/variable-model.js similarity index 100% rename from models/variable-model.js rename to api/models/variable-model.js diff --git a/package-lock.json b/api/package-lock.json similarity index 98% rename from package-lock.json rename to api/package-lock.json index d128861..ab9c5b9 100644 --- a/package-lock.json +++ b/api/package-lock.json @@ -146,12 +146,12 @@ } }, "bcrypt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-4.0.1.tgz", - "integrity": "sha512-hSIZHkUxIDS5zA2o00Kf2O5RfVbQ888n54xQoF/eIaquU4uaLxK8vhhBdktd0B3n2MjkcAWzv4mnhogykBKOUQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz", + "integrity": "sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==", "requires": { - "node-addon-api": "^2.0.0", - "node-pre-gyp": "0.14.0" + "node-addon-api": "^3.0.0", + "node-pre-gyp": "0.15.0" } }, "bignumber.js": { @@ -1287,6 +1287,11 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" } } }, @@ -1306,9 +1311,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" }, "lodash.includes": { "version": "4.3.0", @@ -1565,18 +1570,18 @@ "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==" }, "node-addon-api": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz", - "integrity": "sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.0.tgz", + "integrity": "sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg==" }, "node-pre-gyp": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz", - "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz", + "integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==", "requires": { "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", + "mkdirp": "^0.5.3", + "needle": "^2.5.0", "nopt": "^4.0.1", "npm-packlist": "^1.1.6", "npmlog": "^4.0.2", @@ -2376,9 +2381,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", + "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==" }, "v8flags": { "version": "3.1.3", diff --git a/package.json b/api/package.json similarity index 89% rename from package.json rename to api/package.json index f707d85..244fba0 100644 --- a/package.json +++ b/api/package.json @@ -4,7 +4,7 @@ "description": "API for Auracle database", "main": "index.js", "scripts": { - "test": "start" + "run": "node index.js" }, "repository": { "type": "git", @@ -27,7 +27,7 @@ }, "homepage": "https://github.com/AlexisNP/spellsaurus#readme", "dependencies": { - "bcrypt": "^4.0.1", + "bcrypt": "^5.0.0", "bookshelf": "^1.1.1", "cors": "^2.8.5", "dotenv": "^8.2.0", @@ -37,6 +37,7 @@ "jsonwebtoken": "^8.5.1", "knex": "^0.21.1", "morgan": "^1.10.0", - "mysql": "^2.18.1" + "mysql": "^2.18.1", + "uuid": "^8.2.0" } } diff --git a/repositories/ingredient-repository.js b/api/repositories/ingredient-repository.js similarity index 89% rename from repositories/ingredient-repository.js rename to api/repositories/ingredient-repository.js index ea226b4..e91aeb9 100644 --- a/repositories/ingredient-repository.js +++ b/api/repositories/ingredient-repository.js @@ -10,7 +10,8 @@ const IngredientValidation = require("../validations/IngredientValidation") v.addSchema(IngredientValidation, "/IngredientValidation") // Validations -const regexXSS = RegExp(/<[^>]*script/) +const isXSSAttempt = require('../functions').isXSSAttempt +const isEmptyObject = require('../functions').isEmptyObject // Error handling const { HttpError } = require('../validations/Errors') @@ -68,11 +69,11 @@ class IngredientRepository { addOne(igr) { return new Promise((resolve, reject) => { // Checks if body exists and if the model fits, and throws errors if it doesn't - if (this.isEmptyObject(igr)) { + if (isEmptyObject(igr)) { reject(new HttpError(403, "Error: Ingredient cannot be nothing !")) } else if (!v.validate(igr, IngredientValidation).valid) { reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(igr, IngredientValidation).errors)) - } else if (this.isXSSAttempt(igr.description)) { + } else if (isXSSAttempt(igr.description)) { reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) } else { bookshelf.transaction(t => { @@ -103,11 +104,11 @@ class IngredientRepository { updateOne(id, igr) { return new Promise((resolve, reject) => { // Checks if body exists and if the model fits, and throws errors if it doesn't - if (this.isEmptyObject(igr)) { + if (isEmptyObject(igr)) { reject(new HttpError(403, "Error: Ingredient cannot be nothing !")) } else if (!v.validate(igr, IngredientValidation).valid) { reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(igr, IngredientValidation).errors)) - } else if (this.isXSSAttempt(igr.description)) { + } else if (isXSSAttempt(igr.description)) { reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) } else { model.forge({id: id}) @@ -165,24 +166,6 @@ class IngredientRepository { }) }) } - - // Check if object is null - isEmptyObject(obj) { - if (Object.keys(obj).length === 0 && obj.constructor === Object) { - return true - } else { - return false - } - } - - // Check if script injection attempt - isXSSAttempt(string) { - if (regexXSS.test(string)) { - return true - } else { - return false - } - } } module.exports = IngredientRepository \ No newline at end of file diff --git a/repositories/meta-school-repository.js b/api/repositories/meta-school-repository.js similarity index 100% rename from repositories/meta-school-repository.js rename to api/repositories/meta-school-repository.js diff --git a/repositories/school-repository.js b/api/repositories/school-repository.js similarity index 88% rename from repositories/school-repository.js rename to api/repositories/school-repository.js index f15d597..0aef22b 100644 --- a/repositories/school-repository.js +++ b/api/repositories/school-repository.js @@ -10,7 +10,8 @@ const SchoolValidation = require("../validations/SchoolValidation") v.addSchema(SchoolValidation, "/SchoolValidation") // Validations -const regexXSS = RegExp(/<[^>]*script/) +const isXSSAttempt = require('../functions').isXSSAttempt +const isEmptyObject = require('../functions').isEmptyObject // Error handling const { HttpError } = require('../validations/Errors') @@ -59,7 +60,7 @@ class SchoolRepository { }) .catch(err => { console.log(err) - reject(new HttpError(500, "Couldn't get school")) + reject(new HttpError(500, "Couldn't get spells from school")) }) }) } @@ -67,11 +68,11 @@ class SchoolRepository { addOne(s) { return new Promise((resolve, reject) => { // Checks if body exists and if the model fits, and throws errors if it doesn't - if (this.isEmptyObject(s)) { + if (isEmptyObject(s)) { reject(new HttpError(403, "Error: School cannot be nothing !")) } else if (!v.validate(s, SchoolValidation).valid) { reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, SchoolValidation).errors)) - } else if (this.isXSSAttempt(s.name) || this.isXSSAttempt(s.description)) { + } else if (isXSSAttempt(s.name) || isXSSAttempt(s.description)) { reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) } else { bookshelf.transaction(t => { @@ -103,11 +104,11 @@ class SchoolRepository { updateOne(id, s) { return new Promise((resolve, reject) => { // Checks if body exists and if the model fits, and throws errors if it doesn't - if (this.isEmptyObject(s)) { + if (isEmptyObject(s)) { reject(new HttpError(403, "Error: School cannot be nothing !")) } else if (!v.validate(s, SchoolValidation).valid) { reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, SchoolValidation).errors)) - } else if (this.isXSSAttempt(s.name) || this.isXSSAttempt(s.description)) { + } else if (isXSSAttempt(s.name) || isXSSAttempt(s.description)) { reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) } else { model.forge({id: id}) @@ -166,24 +167,6 @@ class SchoolRepository { }) }) } - - // Check if object is null - isEmptyObject(obj) { - if (Object.keys(obj).length === 0 && obj.constructor === Object) { - return true - } else { - return false - } - } - - // Check if script injection attempt - isXSSAttempt(string) { - if (regexXSS.test(string)) { - return true - } else { - return false - } - } } module.exports = SchoolRepository \ No newline at end of file diff --git a/repositories/spell-repository.js b/api/repositories/spell-repository.js similarity index 77% rename from repositories/spell-repository.js rename to api/repositories/spell-repository.js index b376e96..da8b5d2 100644 --- a/repositories/spell-repository.js +++ b/api/repositories/spell-repository.js @@ -10,7 +10,8 @@ const SpellValidation = require("../validations/SpellValidation") v.addSchema(SpellValidation, "/SpellValidation") // Validations -const regexXSS = RegExp(/<[^>]*script/) +const isXSSAttempt = require('../functions').isXSSAttempt +const isEmptyObject = require('../functions').isEmptyObject // Error handling const { HttpError } = require('../validations/Errors') @@ -20,10 +21,19 @@ class SpellRepository { constructor() { } - getAll() { + getAll(name, description, level, charge, cost, ritual) { return new Promise((resolve, reject) => { - model.forge() - .fetchAll({ withRelated: ['schools.meta_schools', 'variables', 'ingredients'] }) + + let query = model.forge() + + if (name) { query.where('name', 'like', `%${name}%`) } + if (description) { query.where('description', 'like', `%${description}%`) } + if (level) { query.where({ 'level' : level }) } + if (charge) { query.where({ 'charge' : charge }) } + if (cost) { query.where({ 'cost' : cost }) } + if (ritual) { query.where({ 'is_ritual' : ritual }) } + + query.fetchAll({ withRelated: ['schools.meta_schools', 'variables', 'ingredients'] }) .then(v => { resolve(v.toJSON({ omitPivot: true })) }) @@ -34,6 +44,49 @@ class SpellRepository { }) } + getAllPublic(name, description, level, charge, cost, ritual) { + return new Promise((resolve, reject) => { + + let query = model.forge() + .where({ 'public' : 1 }) + + if (name) { query.where('name', 'like', `%${name}%`) } + if (description) { query.where('description', 'like', `%${description}%`) } + if (level) { query.where({ 'level' : level }) } + if (charge) { query.where({ 'charge' : charge }) } + if (cost) { query.where({ 'cost' : cost }) } + if (ritual) { query.where({ 'is_ritual' : ritual }) } + + query.fetchAll({ withRelated: ['schools.meta_schools', 'variables', 'ingredients'] }) + .then(v => { + resolve(v.toJSON({ omitPivot: true })) + }) + .catch(err => { + console.log(err) + reject(new HttpError(500, "Couldn't get public spells")) + }) + }) + } + + getPage(page) { + return new Promise((resolve, reject) => { + model.forge() + .where({ 'public' : 1 }) + .fetchPage({ + pageSize: 20, + page: page, + withRelated: ['schools.meta_schools', 'variables', 'ingredients'], + }) + .then(v => { + resolve(v.toJSON({ omitPivot: true })) + }) + .catch(err => { + console.log(err) + reject(new HttpError(500, "Couldn't get public spells")) + }) + }) + } + getOne(id) { return new Promise((resolve, reject) => { model.forge() @@ -52,11 +105,11 @@ class SpellRepository { addOne(s) { return new Promise((resolve, reject) => { // Checks if body exists and if the model fits, and throws errors if it doesn't - if (this.isEmptyObject(s)) { + if (isEmptyObject(s)) { reject(new HttpError(403, "Error: Spell cannot be nothing !")) } else if (!v.validate(s, SpellValidation).valid) { reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, SpellValidation).errors)) - } else if (this.isXSSAttempt(s.name) || this.isXSSAttempt(s.description) || this.isXSSAttempt(s.cost)) { + } else if (isXSSAttempt(s.name) || isXSSAttempt(s.description) || isXSSAttempt(s.cost)) { reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) } else { bookshelf.transaction(t => { @@ -112,11 +165,11 @@ class SpellRepository { updateOne(id, s) { return new Promise((resolve, reject) => { // Checks if body exists and if the model fits, and throws errors if it doesn't - if (this.isEmptyObject(s)) { + if (isEmptyObject(s)) { reject(new HttpError(403, "Error: Spell cannot be nothing !")) } else if (!v.validate(s, SpellValidation).valid) { reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(s, SpellValidation).errors)) - } else if (this.isXSSAttempt(s.name) || this.isXSSAttempt(s.description) || this.isXSSAttempt(s.cost)) { + } else if (isXSSAttempt(s.name) || isXSSAttempt(s.description) || isXSSAttempt(s.cost)) { reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) } else { model.forge({id: id}) @@ -222,24 +275,6 @@ class SpellRepository { }) }) } - - // Check if object is null - isEmptyObject(obj) { - if (Object.keys(obj).length === 0 && obj.constructor === Object) { - return true - } else { - return false - } - } - - // Check if script injection attempt - isXSSAttempt(string) { - if (regexXSS.test(string)) { - return true - } else { - return false - } - } } module.exports = SpellRepository \ No newline at end of file diff --git a/api/repositories/user-repository.js b/api/repositories/user-repository.js new file mode 100644 index 0000000..88c7046 --- /dev/null +++ b/api/repositories/user-repository.js @@ -0,0 +1,180 @@ +'use strict' +// Bookshelf +const bookshelf = require('../database/bookshelf').bookshelf +const model = require('../models/user-model') + +// Hashing and passwords +const bcrypt = require('bcrypt') +const { v4: uuidv4 } = require('uuid') + +// Model validation +const Validator = require('jsonschema').Validator +const v = new Validator() +const UserValidation = require("../validations/UserValidation") +v.addSchema(UserValidation, "/UserValidation") + +// Validations +const isXSSAttempt = require('../functions').isXSSAttempt +const isEmptyObject = require('../functions').isEmptyObject + +class UserRepository { + + constructor() { + } + + getAll() { + return new Promise((resolve, reject) => { + model.forge() + .fetchAll() + .then(v => { + resolve(v.toJSON({ omitPivot: true })) + }) + .catch(() => { + reject({ + "message": "Database error, couldn't get all users.", + "code": 500 + }) + }) + }) + } + + getOneByUUID(uuid, full) { + return new Promise((resolve, reject) => { + model.forge() + .where({ 'uuid' : uuid }) + .fetch() + .then(v => { + resolve(v.toJSON({ omitPivot: true, visibility: !full })) + }) + .catch(err => { + reject({ + "message": "User with this UUID was not found.", + "code": 404 + }) + }) + }) + } + + getOneByEmail(mail, full) { + return new Promise((resolve, reject) => { + model.forge() + .where({ 'mail': mail }) + .fetch() + .then(v => { + resolve(v.toJSON({ omitPivot: true, visibility: !full })) + }) + .catch(() => { + reject({ + "message": "User with this email was not found.", + "code": 404 + }) + }) + }) + } + + addOne(u) { + return new Promise(async (resolve, reject) => { + // Checks if body exists and if the model fits, and throws errors if it doesn't + if (isEmptyObject(u)) { + reject({ + "message": "Request body cannot be empty.", + "code": 403 + }) + } else if (!v.validate(u, UserValidation).valid) { + reject({ + "message": "Schema is not valid - " + v.validate(u, UserValidation).errors, + "code": 403 + }) + } else if (isXSSAttempt(u.name) || isXSSAttempt(u.password) || isXSSAttempt(u.mail)) { + reject({ + "message": "Injection attempt detected, aborting the request.", + "code": 403 + }) + } else { + let hash = await bcrypt.hash(u.password, 10) + let uuid = uuidv4() + + this.checkIfEmailAvailable(u.mail) + .then(() => { + bookshelf.transaction(t => { + return model.forge({ + 'uuid': uuid, + 'name': u.name, + 'mail': u.mail, + 'password': hash, + }) + .save(null, { + transacting: t + }) + .catch(err => { + throw err + }) + }) + .then(() => { + return this.getOneByUUID(uuid, false) + }) + .then(newUser => { + resolve({ + "message": "Account successfully created !", + "user": newUser, + }) + }) + .catch(err => { + resolve({ + "message": "An error has occured while creating your account.", + "code": 500, + }) + }) + }) + .catch(err => { + reject(err) + }) + } + }) + } + + // Log user with an email address and a password + logUser(mail, password) { + return new Promise((resolve, reject) => { + this.getOneByEmail(mail, true) + .then(async fetchedUser => { + + let match = await bcrypt.compare(password, fetchedUser.password) + delete fetchedUser.id + delete fetchedUser.password + + if (match) { + resolve({ + "message": "User successfully logged in !", + "user": fetchedUser, + }) + } else { + reject({ + "message": "Les informations de connexion sont erronées.", + }) + } + }) + .catch(err => { + reject(err) + }) + }) + } + + // Check if one user already has that email + checkIfEmailAvailable(mail) { + return new Promise((resolve, reject) => { + this.getOneByEmail(mail, false) + .then(() => { + reject({ + "message": "L'email est déjà utilisé par un autre utilisateur.", + "code": 403 + }) + }) + .catch(() => { + resolve(true) + }) + }) + } +} + +module.exports = UserRepository \ No newline at end of file diff --git a/repositories/variable-repository.js b/api/repositories/variable-repository.js similarity index 89% rename from repositories/variable-repository.js rename to api/repositories/variable-repository.js index 57bb530..2fc2a31 100644 --- a/repositories/variable-repository.js +++ b/api/repositories/variable-repository.js @@ -10,7 +10,8 @@ const VariableValidation = require("../validations/VariableValidation") v.addSchema(VariableValidation, "/VariableValidation") // Validations -const regexXSS = RegExp(/<[^>]*script/) +const isXSSAttempt = require('../functions').isXSSAttempt +const isEmptyObject = require('../functions').isEmptyObject // Error handling const { HttpError } = require('../validations/Errors') @@ -67,11 +68,11 @@ class VariableRepository { addOne(vr) { return new Promise((resolve, reject) => { // Checks if body exists and if the model fits, and throws errors if it doesn't - if (this.isEmptyObject(vr)) { + if (isEmptyObject(vr)) { reject(new HttpError(403, "Error: Variable cannot be nothing !")) } else if (!v.validate(vr, VariableValidation).valid) { reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(vr, VariableValidation).errors)) - } else if (this.isXSSAttempt(vr.description)) { + } else if (isXSSAttempt(vr.description)) { reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) } else { bookshelf.transaction(t => { @@ -101,11 +102,11 @@ class VariableRepository { updateOne(id, vr) { return new Promise((resolve, reject) => { // Checks if body exists and if the model fits, and throws errors if it doesn't - if (this.isEmptyObject(vr)) { + if (isEmptyObject(vr)) { reject(new HttpError(403, "Error: Variable cannot be nothing !")) } else if (!v.validate(vr, VariableValidation).valid) { reject(new HttpError(403, "Error: Schema is not valid - " + v.validate(vr, VariableValidation).errors)) - } else if (this.isXSSAttempt(vr.description)) { + } else if (isXSSAttempt(vr.description)) { reject(new HttpError(403, 'Injection attempt detected, aborting the request.')) } else { model.forge({id: id}) @@ -162,24 +163,6 @@ class VariableRepository { }) }) } - - // Check if object is null - isEmptyObject(obj) { - if (Object.keys(obj).length === 0 && obj.constructor === Object) { - return true - } else { - return false - } - } - - // Check if script injection attempt - isXSSAttempt(string) { - if (regexXSS.test(string)) { - return true - } else { - return false - } - } } module.exports = VariableRepository \ No newline at end of file diff --git a/routes/index.js b/api/routes/index.js similarity index 100% rename from routes/index.js rename to api/routes/index.js diff --git a/routes/ingredients.js b/api/routes/ingredients.js similarity index 85% rename from routes/ingredients.js rename to api/routes/ingredients.js index 7748a8e..e51c348 100644 --- a/routes/ingredients.js +++ b/api/routes/ingredients.js @@ -6,17 +6,12 @@ let router = express.Router() // Connection const connection = require('../database/bookshelf') -const db = connection.db +const functions = require('../functions') // Repository const IngredientRepository = require('../repositories/ingredient-repository'); const Ingredients = new IngredientRepository(); -const regexInt = RegExp(/^[1-9]\d*$/) - -// Error handling -const { HttpError } = require('../validations/Errors') - // ROUTES // GET ALL ------------------ const getIngredients = () => { @@ -167,24 +162,7 @@ router.delete('/:id/', async (req, res) => { }) }) -// Param validation for ID -// (check if id is int) (could be refactored) -router.param('id', (req, res, next, id) => { - try { - if (regexInt.test(id)) { - next() - } else { - 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, - "code": err.code - }) - ) - } -}) +// Param validations +router.param('id', functions.paramIntCheck) module.exports = router \ No newline at end of file diff --git a/routes/meta_schools.js b/api/routes/meta_schools.js similarity index 69% rename from routes/meta_schools.js rename to api/routes/meta_schools.js index 4639c36..8812891 100644 --- a/routes/meta_schools.js +++ b/api/routes/meta_schools.js @@ -6,17 +6,12 @@ let router = express.Router() // Connection const connection = require('../database/bookshelf') -const db = connection.db +const functions = require('../functions') // Repository const MetaSchoolRepository = require('../repositories/meta-school-repository'); const MetaSchools = new MetaSchoolRepository(); -const regexInt = RegExp(/^[1-9]\d*$/) - -// Error handling -const { HttpError } = require('../validations/Errors') - // ROUTES // GET ALL ------------------ const getMetaSchools = () => { @@ -67,25 +62,7 @@ router.get('/:id/', async (req, res) => { }) }) - -// Param validation for ID -// (check if id is int) (could be refactored) -router.param('id', (req, res, next, id) => { - try { - if (regexInt.test(id)) { - next() - } else { - 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, - "code": err.code - }) - ) - } -}) +// Param validations +router.param('id', functions.paramIntCheck) module.exports = router \ No newline at end of file diff --git a/routes/schools.js b/api/routes/schools.js similarity index 85% rename from routes/schools.js rename to api/routes/schools.js index 1be0200..173af9c 100644 --- a/routes/schools.js +++ b/api/routes/schools.js @@ -6,17 +6,12 @@ let router = express.Router() // Connection const connection = require('../database/bookshelf') -const db = connection.db +const functions = require('../functions') // Repository const SchoolRepository = require('../repositories/school-repository'); const Schools = new SchoolRepository(); -const regexInt = RegExp(/^[1-9]\d*$/) - -// Error handling -const { HttpError } = require('../validations/Errors') - // ROUTES // GET ALL ------------------ const getSchools = () => { @@ -166,24 +161,7 @@ router.delete('/:id/', async (req, res) => { }) }) -// Param validation for ID -// (check if id is int) (could be refactored) -router.param('id', (req, res, next, id) => { - try { - if (regexInt.test(id)) { - next() - } else { - 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, - "code": err.code - }) - ) - } -}) +// Param validations +router.param('id', functions.paramIntCheck) module.exports = router \ No newline at end of file diff --git a/routes/spells.js b/api/routes/spells.js similarity index 64% rename from routes/spells.js rename to api/routes/spells.js index 2d3ea4f..621f38a 100644 --- a/routes/spells.js +++ b/api/routes/spells.js @@ -6,28 +6,23 @@ let router = express.Router() // Connection const connection = require('../database/bookshelf') -const db = connection.db +const functions = require('../functions') // Repository const SpellReposity = require('../repositories/spell-repository'); const Spells = new SpellReposity(); -const regexInt = RegExp(/^[1-9]\d*$/) - -// Error handling -const { HttpError } = require('../validations/Errors') - // ROUTES -// GET ALL ------------------ -const getSpells = () => { - return Spells.getAll() +// GET ALL PUBLIC ------------------ +const getPublicSpells = (name, description, level, charge, cost, ritual) => { + return Spells.getAllPublic(name, description, level, charge, cost, ritual) .catch(err => { console.log(err) throw err }) } -router.get('/', async (req, res) => { - getSpells() +router.get('//:name?/:description?/:level?/:charge?/:cost?/:ritual?/', async (req, res) => { + getPublicSpells(req.query.name, req.query.description, req.query.level, req.query.charge, req.query.cost, req.query.ritual) .then(v => { res.setHeader('Content-Type', 'application/json;charset=utf-8') res.end(JSON.stringify(v)) @@ -42,6 +37,53 @@ router.get('/', async (req, res) => { }) }) +// GET ALL ------------------ +const getSpells = (name, description, level, charge, cost, ritual) => { + return Spells.getAll(name, description, level, charge, cost, ritual) + .catch(err => { + console.log(err) + throw err + }) +} +router.get('/private/:name?/:description?/:level?/:charge?/:cost?/:ritual?/', async (req, res) => { + getSpells(req.query.name, req.query.description, req.query.level, req.query.charge, req.query.cost, req.query.ritual) + .then(v => { + res.setHeader('Content-Type', 'application/json;charset=utf-8') + res.end(JSON.stringify(v)) + }) + .catch(err => { + res.status(err.code).send(JSON.stringify( + { + "error": err.message, + "code": err.code + }) + ) + }) +}) + +// GET SOME ------------------ +const getSomeSpells = (page) => { + return Spells.getPage(page) + .catch(err => { + console.log(err) + throw err + }) +} +router.get('/page/:page', async (req, res) => { + getSomeSpells(req.params.page) + .then(v => { + res.setHeader('Content-Type', 'application/json;charset=utf-8') + res.end(JSON.stringify(v)) + }) + .catch(err => { + res.status(err.code).send(JSON.stringify( + { + "error": err.message, + "code": err.code + }) + ) + }) +}) // GET ONE ------------------ const getSpell = (id) => { @@ -142,25 +184,8 @@ router.delete('/:id/', async (req, res) => { }) }) - -// Param validation for ID - // (check if id is int) (could be refactored) -router.param('id', (req, res, next, id) => { - try { - if (regexInt.test(id)) { - next() - } else { - 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, - "code": err.code - }) - ) - } -}) +// Param validations +router.param('id', functions.paramIntCheck) +router.param('page', functions.paramIntCheck) module.exports = router diff --git a/api/routes/users.js b/api/routes/users.js new file mode 100644 index 0000000..6219953 --- /dev/null +++ b/api/routes/users.js @@ -0,0 +1,113 @@ +'use strict' + +// Router +const express = require('express') +let router = express.Router() + +// Connection +const connection = require('../database/bookshelf') +const db = connection.db + +// Repository +const UserRepository = require('../repositories/user-repository'); +const Users = new UserRepository(); + +// ROUTES +// GET ALL ------------------ +const getUsers = () => { + return Users.getAll() + .catch(err => { + console.log(err) + throw err + }) +} +router.get('/', async (req, res) => { + getUsers() + .then(v => { + res.setHeader('Content-Type', 'application/json;charset=utf-8') + res.end(JSON.stringify(v)) + }) + .catch(err => { + res.status(err.code).send(JSON.stringify( + { + "error": err.message, + "code": err.code + }) + ) + }) +}) + + +// GET ONE FORM UUID ------------------ +const getUserByUUID = (uuid) => { + return Users.getOneByUUID(uuid) + .catch(err => { + console.log(err) + throw err + }) +} +router.get('/:uuid/', async (req, res) => { + getUserByUUID(req.params.uuid) + .then(v => { + res.setHeader('Content-Type', 'application/json;charset=utf-8') + res.end(JSON.stringify(v)) + }) + .catch(err => { + res.status(err.code).send(JSON.stringify( + { + "error": err.message, + "code": err.code + }) + ) + }) +}) + + +// LOG A USER ------------------ +const logUser = (mail, password) => { + return Users.logUser(mail, password) + .catch(err => { + console.log(err) + throw err + }) +} +router.post('/login', async (req, res) => { + logUser(req.body.mail, req.body.password) + .then(v => { + res.setHeader('Content-Type', 'application/json;charset=utf-8') + res.end(JSON.stringify(v)) + }) + .catch(err => { + res.status(err.code).send(JSON.stringify( + { + "error": err.message, + "code": err.code + }) + ) + }) +}) + +// CREATE ONE ------------------ +const addUser = (u) => { + return Users.addOne(u) + .catch(err => { + throw err + }) +} +router.post('/', async (req, res) => { + addUser(req.body) + .then(v => { + res.setHeader('Content-Type', 'application/json;charset=utf-8') + res.send(JSON.stringify(v)) + }) + .catch(err => { + res.status(err.code).send(JSON.stringify( + { + "error": err.message, + "code": err.code + }) + ) + }) +}) + +module.exports = router \ No newline at end of file diff --git a/routes/variables.js b/api/routes/variables.js similarity index 85% rename from routes/variables.js rename to api/routes/variables.js index 01ee961..15bfa39 100644 --- a/routes/variables.js +++ b/api/routes/variables.js @@ -6,17 +6,12 @@ let router = express.Router() // Connection const connection = require('../database/bookshelf') -const db = connection.db +const functions = require('../functions') // Repository const VariableRepository = require('../repositories/variable-repository'); const Variables = new VariableRepository(); -const regexInt = RegExp(/^[1-9]\d*$/) - -// Error handling -const { HttpError } = require('../validations/Errors') - // ROUTES // GET ALL ------------------ const getvariables = () => { @@ -167,24 +162,7 @@ router.delete('/:id/', async (req, res) => { }) }) -// Param validation for ID -// (check if id is int) (could be refactored) -router.param('id', (req, res, next, id) => { - try { - if (regexInt.test(id)) { - next() - } else { - 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, - "code": err.code - }) - ) - } -}) +// Param validations +router.param('id', functions.paramIntCheck) module.exports = router \ No newline at end of file diff --git a/validations/Errors.js b/api/validations/Errors.js similarity index 100% rename from validations/Errors.js rename to api/validations/Errors.js diff --git a/validations/IngredientValidation.js b/api/validations/IngredientValidation.js similarity index 100% rename from validations/IngredientValidation.js rename to api/validations/IngredientValidation.js diff --git a/validations/MetaSchoolValidation.js b/api/validations/MetaSchoolValidation.js similarity index 100% rename from validations/MetaSchoolValidation.js rename to api/validations/MetaSchoolValidation.js diff --git a/validations/SchoolValidation.js b/api/validations/SchoolValidation.js similarity index 100% rename from validations/SchoolValidation.js rename to api/validations/SchoolValidation.js diff --git a/validations/SpellValidation.js b/api/validations/SpellValidation.js similarity index 100% rename from validations/SpellValidation.js rename to api/validations/SpellValidation.js diff --git a/validations/UserValidation.js b/api/validations/UserValidation.js similarity index 87% rename from validations/UserValidation.js rename to api/validations/UserValidation.js index 1dc9290..4ea8968 100644 --- a/validations/UserValidation.js +++ b/api/validations/UserValidation.js @@ -5,7 +5,6 @@ const User = { "name": { "type": "string" }, "mail": { "type": "string" }, "password": { "type": "string" }, - "banned": { "type": "boolean"}, }, "required": ["name", "password", "mail"] } diff --git a/validations/VariableValidation.js b/api/validations/VariableValidation.js similarity index 100% rename from validations/VariableValidation.js rename to api/validations/VariableValidation.js diff --git a/client/package-lock.json b/client/package-lock.json index e53b9cb..30b1565 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -4270,9 +4270,9 @@ "dev": true }, "elliptic": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", - "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -7490,9 +7490,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true }, "lodash.defaultsdeep": { @@ -8046,9 +8046,9 @@ } }, "node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" }, "node-forge": { "version": "0.9.0", @@ -11960,6 +11960,11 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.11.tgz", "integrity": "sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ==" }, + "vue-cookies": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vue-cookies/-/vue-cookies-1.7.0.tgz", + "integrity": "sha512-vuEUm6wYMMrFAHFCrkzIUAy8+MgPAbBGmYXnk2M6X6O2KHbMT1wuDD2izacmsSUp6ZM02e23MJRtPRobl88VMg==" + }, "vue-eslint-parser": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.0.0.tgz", @@ -12068,6 +12073,11 @@ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "dev": true }, + "vuex": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.5.1.tgz", + "integrity": "sha512-w7oJzmHQs0FM9LXodfskhw9wgKBiaB+totOdb8sNzbTB2KDCEEwEs29NzBZFh/lmEK1t5tDmM1vtsO7ubG1DFw==" + }, "watchpack": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.2.tgz", diff --git a/client/package.json b/client/package.json index dea18a1..cb12d49 100644 --- a/client/package.json +++ b/client/package.json @@ -22,9 +22,7 @@ "url": "git+https://github.com/AlexisNP/spellsaurus.git" }, "scripts": { - "serve": "vue-cli-service serve", - "build": "vue-cli-service build", - "lint": "vue-cli-service lint" + "serve": "vue-cli-service serve" }, "dependencies": { "axios": "^0.19.2", @@ -35,7 +33,9 @@ "popper.js": "^1.16.1", "v-clipboard": "^2.2.3", "vue": "^2.6.11", - "vue-masonry": "^0.11.8" + "vue-cookies": "^1.7.0", + "vue-masonry": "^0.11.8", + "vuex": "^3.5.1" }, "devDependencies": { "@vue/cli-plugin-babel": "~4.2.0", diff --git a/client/public/img/favicon.ico b/client/public/favicon.ico similarity index 100% rename from client/public/img/favicon.ico rename to client/public/favicon.ico diff --git a/client/public/index.html b/client/public/index.html index 9cd4214..65749c0 100644 --- a/client/public/index.html +++ b/client/public/index.html @@ -4,10 +4,10 @@ - + + + Auracle - -