Compare commits
No commits in common. "develop" and "master" have entirely different histories.
40 changed files with 0 additions and 9860 deletions
30
.babelrc
30
.babelrc
|
@ -1,30 +0,0 @@
|
||||||
{
|
|
||||||
"plugins": [
|
|
||||||
[
|
|
||||||
"@babel/plugin-transform-runtime",
|
|
||||||
{
|
|
||||||
"regenerator": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"@babel/plugin-proposal-class-properties"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"@babel/preset-env",
|
|
||||||
{
|
|
||||||
"targets": {
|
|
||||||
"node": "current"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"test": {
|
|
||||||
"plugins": [
|
|
||||||
"@babel/plugin-transform-modules-commonjs"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
/node_modules/
|
|
30
.eslintrc.js
30
.eslintrc.js
|
@ -1,30 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
parser: "babel-eslint",
|
|
||||||
extends: ["airbnb-base", "prettier", "plugin:jest/recommended"],
|
|
||||||
plugins: ["prettier", "jest"],
|
|
||||||
env: {
|
|
||||||
es6: true,
|
|
||||||
browser: false,
|
|
||||||
node: true,
|
|
||||||
"jest/globals": true
|
|
||||||
},
|
|
||||||
globals: {
|
|
||||||
__DEV__: true
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
// enable additional rules
|
|
||||||
"no-plusplus": [2, { allowForLoopAfterthoughts: true }],
|
|
||||||
"no-underscore-dangle": "off",
|
|
||||||
indent: ["error", 2, { SwitchCase: 1 }],
|
|
||||||
"linebreak-style": ["error", "unix"],
|
|
||||||
quotes: ["error", "double"],
|
|
||||||
semi: ["error", "always"],
|
|
||||||
// Forbid the use of extraneous packages
|
|
||||||
// https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-extraneous-dependencies.md
|
|
||||||
"import/no-extraneous-dependencies": ["error", { packageDir: "." }],
|
|
||||||
// ESLint plugin for prettier formatting
|
|
||||||
// https://github.com/prettier/eslint-plugin-prettier
|
|
||||||
"prettier/prettier": "error",
|
|
||||||
"func-names": ["error", "never"]
|
|
||||||
}
|
|
||||||
};
|
|
69
.gitignore
vendored
69
.gitignore
vendored
|
@ -1,69 +0,0 @@
|
||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
|
|
||||||
# Runtime data
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
lib-cov
|
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
coverage
|
|
||||||
|
|
||||||
# nyc test coverage
|
|
||||||
.nyc_output
|
|
||||||
/reports/
|
|
||||||
junit.xml
|
|
||||||
|
|
||||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# Bower dependency directory (https://bower.io/)
|
|
||||||
bower_components
|
|
||||||
|
|
||||||
# node-waf configuration
|
|
||||||
.lock-wscript
|
|
||||||
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
||||||
build/Release
|
|
||||||
|
|
||||||
# Dependency directories
|
|
||||||
node_modules/
|
|
||||||
jspm_packages/
|
|
||||||
|
|
||||||
# Typescript v1 declaration files
|
|
||||||
typings/
|
|
||||||
|
|
||||||
# Optional npm cache directory
|
|
||||||
.npm
|
|
||||||
|
|
||||||
# Optional eslint cache
|
|
||||||
.eslintcache
|
|
||||||
|
|
||||||
# Optional REPL history
|
|
||||||
.node_repl_history
|
|
||||||
|
|
||||||
# Output of 'npm pack'
|
|
||||||
*.tgz
|
|
||||||
|
|
||||||
# Yarn Integrity file
|
|
||||||
.yarn-integrity
|
|
||||||
|
|
||||||
# dotenv environment variables file
|
|
||||||
.env
|
|
||||||
|
|
||||||
# next.js build output
|
|
||||||
.next
|
|
||||||
|
|
||||||
/dist/
|
|
||||||
|
|
||||||
# Seeder info, proper to each environment
|
|
||||||
sequelize-data.json
|
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
image: node:latest
|
|
||||||
|
|
||||||
variables:
|
|
||||||
NODE_ENV: "ci"
|
|
||||||
POSTGRES_DB: "postgres"
|
|
||||||
POSTGRES_USER: "postgres"
|
|
||||||
POSTGRES_PASSWORD: "postgres"
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- test
|
|
||||||
- deploy
|
|
||||||
|
|
||||||
cache:
|
|
||||||
paths:
|
|
||||||
- node_modules/
|
|
||||||
|
|
||||||
testing:
|
|
||||||
stage: test
|
|
||||||
services:
|
|
||||||
- postgres:latest
|
|
||||||
script:
|
|
||||||
- yarn install
|
|
||||||
- ./node_modules/.bin/sequelize db:migrate
|
|
||||||
- ./node_modules/.bin/sequelize db:seed:all
|
|
||||||
- yarn test --ci --collectCoverage=true --coverage
|
|
||||||
coverage: /All files[^|]*\|[^|]*\s+([\d\.]+)/
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- junit.xml
|
|
||||||
- coverage/
|
|
||||||
- reports/
|
|
||||||
reports:
|
|
||||||
junit: junit.xml
|
|
||||||
|
|
||||||
pages:
|
|
||||||
stage: deploy
|
|
||||||
dependencies:
|
|
||||||
- testing
|
|
||||||
script:
|
|
||||||
- mv coverage/ public/
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- public
|
|
||||||
expire_in: 30 days
|
|
||||||
only:
|
|
||||||
- develop
|
|
21
LICENCE.txt
21
LICENCE.txt
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2019 Damien Broqua and contributors (https://framagit.org/dbroqua/sequelize-middleware/-/graphs/master)
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
215
README.md
215
README.md
|
@ -1,217 +1,2 @@
|
||||||
# sequelize-middleware
|
# sequelize-middleware
|
||||||
|
|
||||||
[![pipeline status](https://framagit.org/dbroqua/sequelize-middleware/badges/develop/pipeline.svg)](https://framagit.org/dbroqua/sequelize-middleware/commits/develop) [![coverage report](https://framagit.org/dbroqua/sequelize-middleware/badges/develop/coverage.svg)](https://framagit.org/dbroqua/sequelize-middleware/commits/develop)
|
|
||||||
|
|
||||||
Sequelize-middleware est un module NodeJS permettant d'automatiser la création d'une API REST utilisant Sequelize comme SGBD.
|
|
||||||
|
|
||||||
Sequelize-middleware s'appuie également sur Joi pour valider les données reçues ainsi que les appels API effectuées.
|
|
||||||
|
|
||||||
## Fonctionnalités
|
|
||||||
|
|
||||||
Ce module est découpé en 3 fonctionnalités principales :
|
|
||||||
* Le `Middleware`, partie centrale du projet
|
|
||||||
* `ErrorBuilder` qui permet de surcharger la méthode `new Error()`
|
|
||||||
* `ResponseFormater` qui se charge de formater les données retournée au client final
|
|
||||||
|
|
||||||
### Middleware
|
|
||||||
|
|
||||||
Méthode par défaut, permettant de générer tout le code propre à un endpoint.
|
|
||||||
|
|
||||||
```js
|
|
||||||
import Middleware from "sequelize-middleare";
|
|
||||||
|
|
||||||
import models from "../models";
|
|
||||||
import params from "../rules/Endpoint";
|
|
||||||
|
|
||||||
const middleware = new Middleware(params, models);
|
|
||||||
|
|
||||||
middleware.getAll(req, callback);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Initilisation
|
|
||||||
|
|
||||||
Le constructeur doit recevoir 2 paramètres :
|
|
||||||
* params
|
|
||||||
* models
|
|
||||||
|
|
||||||
`params` représente le fichier des règles pour cet endpoint.
|
|
||||||
`models` fait référence au fichier `models/index.js` généré par Sequelize.
|
|
||||||
|
|
||||||
Le fichier params doit ressembler à ceci :
|
|
||||||
|
|
||||||
```js
|
|
||||||
import Joi from "@hapi/joi";
|
|
||||||
const models = require("../models"); // Facultatif
|
|
||||||
|
|
||||||
const Rules = {
|
|
||||||
model: "Areas", // Nom de la collection Sequelize
|
|
||||||
crud: { // Liste des rôles (req.user.roles) autorisés en fonction de l'action
|
|
||||||
read: ["installer", "admin", "user"],
|
|
||||||
write: ["installer", "admin"],
|
|
||||||
edit: ["installer", "admin"],
|
|
||||||
delete: ["installer", "admin"]
|
|
||||||
},
|
|
||||||
includes: [ // Liste des inclusions à faire lors d'un getOne/getAll
|
|
||||||
{
|
|
||||||
collection: "Devices", // Nom de la collection à inclure
|
|
||||||
requiredRole: ["installer", "admin", "user"], // Rôles autorisés à voir cette inclusion
|
|
||||||
required: false, // Sauf cas particulier toujours mettre false
|
|
||||||
model: models.AreasDevices, // Nom du modèle Sequelize à inclure
|
|
||||||
include: [ // Liste des sous-inclusions
|
|
||||||
{
|
|
||||||
collection: "Device",
|
|
||||||
requiredRole: ["installer", "admin", "user"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
format: { // Formatage des données en fonction du rôle de l'utilisateur (dans le cas ou l'on veut surcharger le formatage du modèle)
|
|
||||||
user: {
|
|
||||||
idRetourne: "_idSql", // Clé retournée: Clé du modèle
|
|
||||||
id: "id",
|
|
||||||
nom: "name"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemId: "areaId", // Id de l'item dans la req.params
|
|
||||||
validate: { // Définition des des règles de valeurs acceptées en fonction du verbe
|
|
||||||
// Création d'un nouvele élément
|
|
||||||
create: Joi.object({
|
|
||||||
name: Joi.string().required(),
|
|
||||||
type: Joi.string()
|
|
||||||
.valid("OFFICE", "COMMUNAL-AREAS")
|
|
||||||
.required()
|
|
||||||
}),
|
|
||||||
// Mise à jour d'un élément
|
|
||||||
update: Joi.object({
|
|
||||||
name: Joi.string(),
|
|
||||||
type: Joi.string().valid("OFFICE", "COMMUNAL-AREAS")
|
|
||||||
}),
|
|
||||||
// Sélection d'un élément (req.params)
|
|
||||||
item: Joi.object({
|
|
||||||
areaId: Joi.number().required()
|
|
||||||
}),
|
|
||||||
// Sélection d'une liste d'éléments (req.query)
|
|
||||||
list: Joi.object({
|
|
||||||
limit: Joi.number()
|
|
||||||
.integer()
|
|
||||||
.min(1)
|
|
||||||
.max(50),
|
|
||||||
page: Joi.number()
|
|
||||||
.integer()
|
|
||||||
.min(1),
|
|
||||||
type: Joi.string().valid("OFFICE", "COMMUNAL-AREAS"),
|
|
||||||
sort: Joi.string()
|
|
||||||
.valid("id", "name", "type", "createdAt", "updatedAt")
|
|
||||||
.only(),
|
|
||||||
order: Joi.string()
|
|
||||||
.valid("asc", "desc")
|
|
||||||
.only()
|
|
||||||
})
|
|
||||||
.with("limit", "page")
|
|
||||||
.with("page", "limit")
|
|
||||||
.with("sort", "order")
|
|
||||||
.with("order", "sort")
|
|
||||||
},
|
|
||||||
removeKeys: {
|
|
||||||
// Permet de supprimer automatiquement des valeurs de requêtes
|
|
||||||
item: ["partnerId"] // Sur la sélection d'un item on supprime req.params.partnerId
|
|
||||||
},
|
|
||||||
override: {
|
|
||||||
list: { // Permet de convertir des paramètres reçus via req.query pour en générer des filtres complexes
|
|
||||||
filters: {
|
|
||||||
'category': { // On converti req.query.category
|
|
||||||
$or: [
|
|
||||||
{
|
|
||||||
categoryId: '_TERM_',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
categoriesId: {
|
|
||||||
$contains: '_TERM_',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'countryId': { // On converti req.query pour dire à Sequelize que ça correspond à $Details.countryId$
|
|
||||||
'$Details.countryId$': '_TERM_',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
// Création d'un nouvel item
|
|
||||||
body: [
|
|
||||||
// On modifie req.body
|
|
||||||
{
|
|
||||||
append: "offerId", // On rajoute un attribut offerId
|
|
||||||
from: "params", // Que l'on prends dans req.params
|
|
||||||
value: "offerId" // Et dont la clé est offerId
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
restrictOn: { // Permet de rajouter des restrictions en fonction des rôles
|
|
||||||
update: [ // Lors d'une mise à jour au autorise l'utilisateur à modifier uniquement les éléments donc state est égal à NEW.
|
|
||||||
{
|
|
||||||
roles: ['user'],
|
|
||||||
type: 'raw', // raw permet de forcer une valeur, sinon user/params/body/query
|
|
||||||
field: 'state',
|
|
||||||
value: 'NEW',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
delete: [],
|
|
||||||
list: [],
|
|
||||||
create: []
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Rules;
|
|
||||||
```
|
|
||||||
|
|
||||||
### ErrorBuilder
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { ErrorBuilder } from "sequelize-middleare";
|
|
||||||
```
|
|
||||||
|
|
||||||
Ce module permet de remplacer la méthode `new Error()` de JS en ajoutant la possibilité de générer un code d'erreur qui sera ensuite retourné via `res.status().json()`.
|
|
||||||
|
|
||||||
Le code reçu doit être un `float` dont la partie entière représente un code HTTP valide et la partie réelle représente un code d'erreur plus détaillé de l'erreur.
|
|
||||||
|
|
||||||
Exemples d'utilistion :
|
|
||||||
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { ErrorBuilder } from "sequelize-middleare";
|
|
||||||
|
|
||||||
new ErrorBuilder(406.0, "Erreur générique de type 406");
|
|
||||||
new ErrorBuilder(406.1, "Le champs mot de passe est absent");
|
|
||||||
new ErrorBuilder(406.2, "Le champs mot de passe doit contenir 8 caractères minimum");
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
### ResponseFormater
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { ResponseFormater } from "sequelize-middleare";
|
|
||||||
```
|
|
||||||
|
|
||||||
Ce module permet de formater à la fois le json ainsi que le code http retourné au client une fois que le middleware à fini son traitement.
|
|
||||||
|
|
||||||
Exemples d'utilisation :
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { ResponseFormater } from "sequelize-middleare";
|
|
||||||
|
|
||||||
router
|
|
||||||
.route("/")
|
|
||||||
.get(passport.authenticate(["jwt"]), function(req, res, next) {
|
|
||||||
middleware.getAll(req, (err, response) => {
|
|
||||||
ResponseFormater(req, res, next, err, response);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.post(passport.authenticate(["jwt"]), function(req, res, next) {
|
|
||||||
middleware.createOne(req, (err, response) => {
|
|
||||||
ResponseFormater(req, res, next, err, response);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"test": {
|
|
||||||
"username": "postgres",
|
|
||||||
"password": "postgres",
|
|
||||||
"database": "test",
|
|
||||||
"host": "127.0.0.1",
|
|
||||||
"port": "5666",
|
|
||||||
"dialect": "postgres",
|
|
||||||
"seederStorage": "sequelize"
|
|
||||||
},
|
|
||||||
"ci": {
|
|
||||||
"username": "postgres",
|
|
||||||
"password": "postgres",
|
|
||||||
"database": "postgres",
|
|
||||||
"host": "postgres",
|
|
||||||
"dialect": "postgres",
|
|
||||||
"seederStorage": "sequelize"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
version: "2"
|
|
||||||
|
|
||||||
services:
|
|
||||||
sequelize-middleware-db:
|
|
||||||
image: postgres:latest
|
|
||||||
environment:
|
|
||||||
POSTGRES_USER: postgres
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
POSTGRES_DB: test
|
|
||||||
restart: always
|
|
||||||
ports:
|
|
||||||
- 127.0.0.1:5666:5432
|
|
||||||
sequelize-middleware-adminer:
|
|
||||||
image: adminer
|
|
||||||
restart: always
|
|
||||||
ports:
|
|
||||||
- 127.0.0.1:8666:8080
|
|
7
index.js
7
index.js
|
@ -1,7 +0,0 @@
|
||||||
import _ErrorBuilder from "./libs/ErrorBuilder";
|
|
||||||
import Middleware from "./libs/Middleware";
|
|
||||||
import _ResponseFormater from "./libs/ResponseFormater";
|
|
||||||
|
|
||||||
export default Middleware;
|
|
||||||
export const ErrorBuilder = _ErrorBuilder;
|
|
||||||
export const ResponseFormater = _ResponseFormater;
|
|
|
@ -1,21 +0,0 @@
|
||||||
/**
|
|
||||||
* Classe permettant la gestion des erreurs personilisées
|
|
||||||
*/
|
|
||||||
class ErrorBuilder extends Error {
|
|
||||||
/**
|
|
||||||
* @param {Number} errorCode
|
|
||||||
* @param {Mixed} ...params
|
|
||||||
*/
|
|
||||||
constructor(errorCode, ...params) {
|
|
||||||
super(...params);
|
|
||||||
|
|
||||||
if (Error.captureStackTrace) {
|
|
||||||
Error.captureStackTrace(this, ErrorBuilder);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.errorCode = errorCode.toFixed(1);
|
|
||||||
this.date = new Date();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ErrorBuilder;
|
|
|
@ -1,290 +0,0 @@
|
||||||
import QueryBuilder from "./QueryBuilder";
|
|
||||||
import ErrorBuilder from "./ErrorBuilder";
|
|
||||||
|
|
||||||
class Middleware extends QueryBuilder {
|
|
||||||
/**
|
|
||||||
* Initialisation de la classe
|
|
||||||
* @param {Object} params
|
|
||||||
* @param {Object} models
|
|
||||||
*/
|
|
||||||
constructor(params, models) {
|
|
||||||
super(params, models);
|
|
||||||
this.params = params;
|
|
||||||
this.models = models;
|
|
||||||
this.includes = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de créer un nouvel élément
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {Function} callback
|
|
||||||
* @return {Boolean}
|
|
||||||
*/
|
|
||||||
createOne(req, callback) {
|
|
||||||
// On test les droits
|
|
||||||
if (!this.haveRight(req)) {
|
|
||||||
callback(new ErrorBuilder(401.1, "You're not allowed"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// On teste le body
|
|
||||||
this.checkCreateOneValues(req, (err, value) => {
|
|
||||||
// Il manque un paramètre dans le body
|
|
||||||
if (err) {
|
|
||||||
callback(err, value);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.insertItem(req, value, callback);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de retourner une liste d'items
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {Function} callback
|
|
||||||
*/
|
|
||||||
getAll(req, callback) {
|
|
||||||
// On spécifie le type de requête (list ou item)
|
|
||||||
req.getType = "list";
|
|
||||||
|
|
||||||
this.createQuery(req, (err, query, limit) => {
|
|
||||||
if (err) {
|
|
||||||
callback(err, query);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.models[this.params.model]
|
|
||||||
.findAndCountAll(query)
|
|
||||||
.then(res => {
|
|
||||||
if (!res || res.count === 0) {
|
|
||||||
callback();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const rows = [];
|
|
||||||
for (let i = 0; i < res.rows.length; i += 1) {
|
|
||||||
const current = res.rows[i];
|
|
||||||
let found = false;
|
|
||||||
for (let j = 0; j < rows.length; j += 1) {
|
|
||||||
if (rows[j].id === current.id) {
|
|
||||||
found = true;
|
|
||||||
rows[j].assign({}, rows[j], current);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found || rows.length === 0) {
|
|
||||||
rows.push(current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const total = rows.length;
|
|
||||||
const values = rows.slice(limit.start, limit.start + limit.limit);
|
|
||||||
|
|
||||||
callback(null, {
|
|
||||||
data: this.formatItems(req, values),
|
|
||||||
...QueryBuilder.createPagination(
|
|
||||||
req,
|
|
||||||
total,
|
|
||||||
limit.limit,
|
|
||||||
limit.start
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
.catch(callback);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de retourner un item par son Id
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {Function} callback
|
|
||||||
*/
|
|
||||||
getOne(req, callback) {
|
|
||||||
// On spécifie le type de requête (list ou item)
|
|
||||||
req.getType = "item";
|
|
||||||
|
|
||||||
this.createQuery(req, (err, query) => {
|
|
||||||
if (err) {
|
|
||||||
callback(err, query);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.models[this.params.model]
|
|
||||||
.findOne(query)
|
|
||||||
.then(item => {
|
|
||||||
if (!item) {
|
|
||||||
callback(new ErrorBuilder(404, "Item not found"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let formatedItem = item;
|
|
||||||
if (req.method === "GET") {
|
|
||||||
if (this.params.format) {
|
|
||||||
const formatRules = this.params.format[req.user.role];
|
|
||||||
|
|
||||||
if (formatRules) {
|
|
||||||
formatedItem = this.formatItem(item, formatRules);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(null, formatedItem);
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
.catch(callback);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de mettre à jour un item
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {Function} callback
|
|
||||||
* @return {Boolean}
|
|
||||||
*/
|
|
||||||
patchOne(req, callback) {
|
|
||||||
// On test les droits
|
|
||||||
if (!this.haveRight(req)) {
|
|
||||||
callback(new ErrorBuilder(401.1, "You're not allowed"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// On teste les params
|
|
||||||
const { error, value } = this.params.validate.update.validate(req.body, {
|
|
||||||
abortEarly: false
|
|
||||||
});
|
|
||||||
|
|
||||||
// Un paramètre n'est pas bon dans les params
|
|
||||||
if (error) {
|
|
||||||
callback(new ErrorBuilder(406.1, error));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.getOne(req, (err, item) => {
|
|
||||||
if (err) {
|
|
||||||
callback(err, item);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
item
|
|
||||||
.update(value)
|
|
||||||
.then(updated => {
|
|
||||||
if (this.params.belongsToMany) {
|
|
||||||
const needCreate = [];
|
|
||||||
let created = 0;
|
|
||||||
const _next = errNext => {
|
|
||||||
if (errNext) {
|
|
||||||
// TODO: break and revert
|
|
||||||
} else {
|
|
||||||
created += 1;
|
|
||||||
|
|
||||||
if (created === needCreate.length) {
|
|
||||||
callback(null, updated);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Object.keys(this.params.belongsToMany).map(key => {
|
|
||||||
if (value[key]) {
|
|
||||||
needCreate.push(key);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (needCreate.length > 0) {
|
|
||||||
for (let i = 0; i < needCreate.length; i += 1) {
|
|
||||||
const currentKey = needCreate[i];
|
|
||||||
const currentValue = value[currentKey];
|
|
||||||
this.createBelonsTo(
|
|
||||||
updated,
|
|
||||||
currentKey,
|
|
||||||
currentValue,
|
|
||||||
"add",
|
|
||||||
_next
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback(null, updated);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback(null, updated);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(callback);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de supprimer un item
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {Function} callback
|
|
||||||
* @return {Boolean}
|
|
||||||
*/
|
|
||||||
deleteOne(req, callback) {
|
|
||||||
// On test les droits
|
|
||||||
if (!this.haveRight(req)) {
|
|
||||||
callback(new ErrorBuilder(401.1, "You're not allowed"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.getOne(req, (err, item) => {
|
|
||||||
if (err) {
|
|
||||||
callback(err, item);
|
|
||||||
} else {
|
|
||||||
let deletedBelongs = 0;
|
|
||||||
const needToDeleteBelongs = [];
|
|
||||||
|
|
||||||
const _deleteItem = () => {
|
|
||||||
item
|
|
||||||
.destroy()
|
|
||||||
.then(() => {
|
|
||||||
callback(null, {});
|
|
||||||
})
|
|
||||||
.catch(callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
const _next = () => {
|
|
||||||
deletedBelongs += 1;
|
|
||||||
|
|
||||||
if (deletedBelongs === needToDeleteBelongs.length) {
|
|
||||||
_deleteItem();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.params.belongsToMany) {
|
|
||||||
Object.keys(this.params.belongsToMany).map(key => {
|
|
||||||
const collection = this.params.belongsToMany[key];
|
|
||||||
if (item[collection].length) {
|
|
||||||
needToDeleteBelongs.push(key);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (needToDeleteBelongs.length > 0) {
|
|
||||||
for (let i = 0; i < needToDeleteBelongs.length; i += 1) {
|
|
||||||
const currentKey = needToDeleteBelongs[i];
|
|
||||||
const collection = this.params.belongsToMany[currentKey];
|
|
||||||
const valuesToDelete = [];
|
|
||||||
for (let j = 0; j < item[collection].length; j += 1) {
|
|
||||||
valuesToDelete.push(item[collection][j].id);
|
|
||||||
}
|
|
||||||
this.deleteBelongsTo(item, currentKey, valuesToDelete, _next);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_deleteItem();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_deleteItem();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Middleware;
|
|
|
@ -1,666 +0,0 @@
|
||||||
import ErrorBuilder from "./ErrorBuilder";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Classe permettant de gérer les tables simples
|
|
||||||
*/
|
|
||||||
class QueryBuilder {
|
|
||||||
/**
|
|
||||||
* Initialisation de la classe
|
|
||||||
* @param {Object} params
|
|
||||||
* @param {Object} models
|
|
||||||
*/
|
|
||||||
constructor(params, models) {
|
|
||||||
this.params = params;
|
|
||||||
this.models = models;
|
|
||||||
this.includes = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Méthode permettant de générer le lien vers une ressource
|
|
||||||
* @param {String} href
|
|
||||||
* @param {Number} currentPage
|
|
||||||
* @param {Number} maxPage
|
|
||||||
* @param {String} page
|
|
||||||
*/
|
|
||||||
static createLink(href, currentPage, maxPage, page) {
|
|
||||||
if (
|
|
||||||
(page === "first" && currentPage > 1) ||
|
|
||||||
(page === "last" && currentPage < maxPage) ||
|
|
||||||
(page === "prev" && currentPage > 1) ||
|
|
||||||
(page === "next" && currentPage < maxPage)
|
|
||||||
) {
|
|
||||||
let newIndex = 0;
|
|
||||||
// eslint-disable-next-line default-case
|
|
||||||
switch (page) {
|
|
||||||
case "first":
|
|
||||||
newIndex = 1;
|
|
||||||
break;
|
|
||||||
case "last":
|
|
||||||
newIndex = maxPage;
|
|
||||||
break;
|
|
||||||
case "prev":
|
|
||||||
newIndex = currentPage - 1;
|
|
||||||
break;
|
|
||||||
case "next":
|
|
||||||
newIndex = currentPage + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
href: href.replace(`page=${currentPage}`, `page=${newIndex}`),
|
|
||||||
methdod: "GET"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Méthde permettant de générer les élements de pagination
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {Number} total
|
|
||||||
* @param {Number} limit
|
|
||||||
* @param {Number} skip
|
|
||||||
* @return {Object}
|
|
||||||
*/
|
|
||||||
static createPagination(req, total, limit, skip) {
|
|
||||||
const maxPage = Math.ceil(total / limit); // Nombre total de pages
|
|
||||||
const currentPage = Math.ceil(skip / limit) + 1; // Numéro de la page courante
|
|
||||||
const href = `${req.protocol}://${req.get("host")}${req.originalUrl}`; // Lien vers la page actuelle
|
|
||||||
|
|
||||||
return {
|
|
||||||
paging: {
|
|
||||||
first: QueryBuilder.createLink(href, currentPage, maxPage, "first"),
|
|
||||||
prev: QueryBuilder.createLink(href, currentPage, maxPage, "prev"),
|
|
||||||
next: QueryBuilder.createLink(href, currentPage, maxPage, "next"),
|
|
||||||
last: QueryBuilder.createLink(href, currentPage, maxPage, "last")
|
|
||||||
},
|
|
||||||
total,
|
|
||||||
maxPage
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de remplacer les attributs du genre $lte pat Op.lte
|
|
||||||
* @param {Object} obj
|
|
||||||
* @return {Object}
|
|
||||||
*/
|
|
||||||
replaceKeys(obj) {
|
|
||||||
const { Op } = this.models.Sequelize;
|
|
||||||
let newObject = {};
|
|
||||||
|
|
||||||
if (Array.isArray(obj)) {
|
|
||||||
newObject = [];
|
|
||||||
for (let i = 0; i < obj.length; i += 1) {
|
|
||||||
const value =
|
|
||||||
typeof obj[i] === "object" ? this.replaceKeys(obj[i]) : obj[i];
|
|
||||||
newObject.push(value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Object.keys(obj).map(key => {
|
|
||||||
const value =
|
|
||||||
typeof obj[key] === "object" ? this.replaceKeys(obj[key]) : obj[key];
|
|
||||||
if (key.indexOf("$") === 0 && key.slice(-1) !== "$") {
|
|
||||||
switch (key) {
|
|
||||||
case "$or":
|
|
||||||
newObject[Op.or] = value;
|
|
||||||
break;
|
|
||||||
case "$lte":
|
|
||||||
newObject[Op.lte] = value;
|
|
||||||
break;
|
|
||||||
case "$gte":
|
|
||||||
newObject[Op.gte] = value;
|
|
||||||
break;
|
|
||||||
case "$contains":
|
|
||||||
newObject[Op.contains] = [value];
|
|
||||||
break;
|
|
||||||
case "$in":
|
|
||||||
newObject[Op.in] = value.split(",");
|
|
||||||
break;
|
|
||||||
case "$like":
|
|
||||||
newObject[Op.like] = value;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
newObject[key] = [value];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newObject[key] = value;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return newObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de savoir si un utilisateur a assez de droit pour effectuer une action
|
|
||||||
* @param {Object} req
|
|
||||||
* @return {Boolean}
|
|
||||||
*/
|
|
||||||
haveRight(req) {
|
|
||||||
let allowedRole = "all";
|
|
||||||
if (!req.user) {
|
|
||||||
req.user = {};
|
|
||||||
}
|
|
||||||
if (!req.user.role) {
|
|
||||||
req.user.role = "guest";
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line default-case
|
|
||||||
switch (req.method) {
|
|
||||||
case "POST":
|
|
||||||
allowedRole = this.params.crud.write;
|
|
||||||
break;
|
|
||||||
case "PATCH":
|
|
||||||
case "PUT":
|
|
||||||
allowedRole = this.params.crud.edit;
|
|
||||||
break;
|
|
||||||
case "GET":
|
|
||||||
allowedRole = this.params.crud.read;
|
|
||||||
break;
|
|
||||||
case "DELETE":
|
|
||||||
allowedRole = this.params.crud.delete;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return allowedRole === "all" || allowedRole.indexOf(req.user.role) !== -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant d'ajouter des restructions sur un get
|
|
||||||
* @param {Object} req
|
|
||||||
* @return {Object}
|
|
||||||
*/
|
|
||||||
restrictOn(req) {
|
|
||||||
const where = {};
|
|
||||||
if (!this.params || !this.params.restrictOn) {
|
|
||||||
return where;
|
|
||||||
}
|
|
||||||
|
|
||||||
const _overrideWhere = restrictions => {
|
|
||||||
if (!restrictions) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (let i = 0; i < restrictions.length; i += 1) {
|
|
||||||
const restrict = restrictions[i];
|
|
||||||
|
|
||||||
const value =
|
|
||||||
restrict.type === "raw"
|
|
||||||
? restrict.value
|
|
||||||
: req[restrict.type][restrict.value];
|
|
||||||
|
|
||||||
if (restrict.roles.indexOf(req.user.role) !== -1) {
|
|
||||||
where[restrict.field] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
_overrideWhere(this.params.restrictOn[req.getType]);
|
|
||||||
|
|
||||||
switch (req.method) {
|
|
||||||
case "PATCH":
|
|
||||||
_overrideWhere(this.params.restrictOn.update);
|
|
||||||
break;
|
|
||||||
case "DELETE":
|
|
||||||
_overrideWhere(this.params.restrictOn.delete);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
return where;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de surcharger des valeurs
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {String} method
|
|
||||||
* @return {Object}
|
|
||||||
*/
|
|
||||||
override(req, method) {
|
|
||||||
let overrideValues = {};
|
|
||||||
if (!this.params.override) {
|
|
||||||
return overrideValues;
|
|
||||||
}
|
|
||||||
const params = this.params.override ? this.params.override[method] : {};
|
|
||||||
|
|
||||||
if (!params) {
|
|
||||||
return overrideValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
// On surcharge certains paramètres passé en query
|
|
||||||
if (params.filters) {
|
|
||||||
Object.keys(params.filters).map(column => {
|
|
||||||
if (req.query[column]) {
|
|
||||||
const value = req.query[column];
|
|
||||||
|
|
||||||
const query = JSON.parse(
|
|
||||||
JSON.stringify(params.filters[column]).replace(
|
|
||||||
new RegExp("_TERM_", "g"),
|
|
||||||
value
|
|
||||||
)
|
|
||||||
);
|
|
||||||
overrideValues = Object.assign(
|
|
||||||
overrideValues,
|
|
||||||
this.replaceKeys(query)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// On rajoute des paramètres à la requête
|
|
||||||
if (params.params) {
|
|
||||||
for (let i = 0; i < params.params.length; i += 1) {
|
|
||||||
const currentParam = params.params[i];
|
|
||||||
overrideValues[currentParam.append] =
|
|
||||||
req[currentParam.from][currentParam.value];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return overrideValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de charger la liste des relations à inclures lors d'un get
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {Array} include
|
|
||||||
* @return {Mixed}
|
|
||||||
*/
|
|
||||||
setInclusions(req, include) {
|
|
||||||
if (!req.user) {
|
|
||||||
req.user = {};
|
|
||||||
}
|
|
||||||
if (!req.user.role) {
|
|
||||||
req.user.role = "guest";
|
|
||||||
}
|
|
||||||
|
|
||||||
const includes = [];
|
|
||||||
|
|
||||||
const listOfIncludes = include || this.params.includes;
|
|
||||||
|
|
||||||
for (let i = 0; i < listOfIncludes.length; i += 1) {
|
|
||||||
const current = listOfIncludes[i];
|
|
||||||
// const include = current.collection;
|
|
||||||
|
|
||||||
if (
|
|
||||||
!current.requiredRole ||
|
|
||||||
current.requiredRole.indexOf(req.user.role) !== -1
|
|
||||||
) {
|
|
||||||
let currentInclude = null;
|
|
||||||
|
|
||||||
if (!current.model) {
|
|
||||||
currentInclude = current.collection;
|
|
||||||
} else {
|
|
||||||
currentInclude = {
|
|
||||||
as: current.collection,
|
|
||||||
model: current.model,
|
|
||||||
required: current.required || false
|
|
||||||
};
|
|
||||||
|
|
||||||
// Pour cette inclusion il y a des filtres à appliquer
|
|
||||||
if (current.restrictOn || current.include) {
|
|
||||||
currentInclude.where = {};
|
|
||||||
|
|
||||||
if (current.include) {
|
|
||||||
currentInclude.include = this.setInclusions(req, current.include);
|
|
||||||
}
|
|
||||||
|
|
||||||
// On parcours la liste des règles d'inclusion pour ce modèle
|
|
||||||
if (current.restrictOn) {
|
|
||||||
for (let j = 0; j < current.restrictOn.length; j += 1) {
|
|
||||||
const currentRestriction = current.restrictOn[j];
|
|
||||||
// Cette restriction s'applique à tout le monde (pas de field roles)
|
|
||||||
// ou alors elle s'applique juste sur une liste de groupes
|
|
||||||
if (
|
|
||||||
!currentRestriction.roles ||
|
|
||||||
currentRestriction.roles.indexOf(req.user.role) !== -1
|
|
||||||
) {
|
|
||||||
if (currentRestriction.type === "raw") {
|
|
||||||
currentInclude.where[currentRestriction.field] =
|
|
||||||
currentRestriction.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
includes.push(currentInclude);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mode reccursif
|
|
||||||
if (include) {
|
|
||||||
return includes;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.includes = includes;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de peupler une table de jointure (belongsToMany)
|
|
||||||
* @param {Object} item
|
|
||||||
* @param {String} key
|
|
||||||
* @param {Array} values
|
|
||||||
* @param {String} mode
|
|
||||||
* @param {Function} callback
|
|
||||||
*/
|
|
||||||
createBelonsTo(item, key, values, mode, callback) {
|
|
||||||
const collection = this.params.belongsToMany[key];
|
|
||||||
const action = `${mode}${collection}`;
|
|
||||||
|
|
||||||
item[action](values)
|
|
||||||
.then(() => {
|
|
||||||
callback();
|
|
||||||
})
|
|
||||||
.catch(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteBelongsTo(item, key, values, callback) {
|
|
||||||
const collection = this.params.belongsToMany[key];
|
|
||||||
const action = `remove${collection}`;
|
|
||||||
|
|
||||||
item[action](values)
|
|
||||||
.then(() => {
|
|
||||||
callback();
|
|
||||||
})
|
|
||||||
.catch(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Méthode interne permettant de créer un item
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {Object} value
|
|
||||||
* @param {Function} callback
|
|
||||||
*/
|
|
||||||
insertItem(req, value, callback) {
|
|
||||||
const values = {};
|
|
||||||
const _done = item => {
|
|
||||||
let createdItem = item;
|
|
||||||
if (this.params.format) {
|
|
||||||
const formatRules = req.user ? this.params.format[req.user.role] : null;
|
|
||||||
|
|
||||||
if (formatRules) {
|
|
||||||
createdItem = this.formatItem(item, formatRules);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback(null, createdItem);
|
|
||||||
};
|
|
||||||
// On converti les 'null' en null (formData par exemple)
|
|
||||||
Object.keys(value).map(key => {
|
|
||||||
if (value[key] === "null") {
|
|
||||||
values[key] = null;
|
|
||||||
} else {
|
|
||||||
values[key] = value[key];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Création de l'élément
|
|
||||||
this.models[this.params.model]
|
|
||||||
.create(values)
|
|
||||||
.then(item => {
|
|
||||||
if (this.params.belongsToMany) {
|
|
||||||
const needCreate = [];
|
|
||||||
let created = 0;
|
|
||||||
const _next = err => {
|
|
||||||
if (err) {
|
|
||||||
// TODO: break and revert
|
|
||||||
} else {
|
|
||||||
created += 1;
|
|
||||||
|
|
||||||
if (created === needCreate.length) {
|
|
||||||
_done(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Object.keys(this.params.belongsToMany).map(key => {
|
|
||||||
if (values[key]) {
|
|
||||||
needCreate.push(key);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (needCreate.length > 0) {
|
|
||||||
for (let i = 0; i < needCreate.length; i += 1) {
|
|
||||||
const currentKey = needCreate[i];
|
|
||||||
this.createBelonsTo(
|
|
||||||
item,
|
|
||||||
currentKey,
|
|
||||||
values[currentKey],
|
|
||||||
"set",
|
|
||||||
_next
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_done(item);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_done(item);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
switch (err.name) {
|
|
||||||
case "SequelizeUniqueConstraintError":
|
|
||||||
callback(new ErrorBuilder(409.1, "Duplicate item"));
|
|
||||||
break;
|
|
||||||
case "SequelizeForeignKeyConstraintError":
|
|
||||||
callback(new ErrorBuilder(406.2, "Bad foreign key"));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
callback(new ErrorBuilder(500, err));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de formater un item en fonction du user
|
|
||||||
* @param {Object} item
|
|
||||||
* @param {Object} formatRule
|
|
||||||
* @return {Object}
|
|
||||||
*/
|
|
||||||
formatItem(item, formatRule) {
|
|
||||||
const formated = {};
|
|
||||||
|
|
||||||
Object.keys(formatRule).map(key => {
|
|
||||||
// TODO: revoir ce switch
|
|
||||||
switch (typeof formatRule[key]) {
|
|
||||||
case "string":
|
|
||||||
if (item) {
|
|
||||||
formated[key] = item[key] || null;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "object":
|
|
||||||
if (Array.isArray(item[key])) {
|
|
||||||
formated[key] = [];
|
|
||||||
for (let i = 0; i < item[key].length; i += 1) {
|
|
||||||
formated[key].push(
|
|
||||||
this.formatItem(item[key][i], formatRule[key])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
formated[key] = this.formatItem(item[key], formatRule[key]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
return formated;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de formater une liste d'items en fonction du user
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {Object} items
|
|
||||||
* @return {Object}
|
|
||||||
*/
|
|
||||||
formatItems(req, items) {
|
|
||||||
if (!this.params.format) {
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatRules = this.params.format[req.user.role];
|
|
||||||
|
|
||||||
if (!formatRules) {
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
const formated = [];
|
|
||||||
for (let i = 0; i < items.length; i += 1) {
|
|
||||||
formated.push(this.formatItem(items[i], formatRules));
|
|
||||||
}
|
|
||||||
|
|
||||||
return formated;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Méthode permettant de vérifier que les valeurs reçues dans le body sont valides
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {Function} callback
|
|
||||||
*/
|
|
||||||
checkCreateOneValues(req, callback) {
|
|
||||||
// On regarde s'il faut surcharger les valeurs du body avec des valeurs dérivées (req.user, req.params...)
|
|
||||||
if (this.params.override && this.params.override.create) {
|
|
||||||
if (this.params.override.create.body) {
|
|
||||||
for (let i = 0; i < this.params.override.create.body.length; i += 1) {
|
|
||||||
const override = this.params.override.create.body[i];
|
|
||||||
req.body[override.append] = req[override.from][override.value];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// On teste le body
|
|
||||||
const { error, value } = this.params.validate.create.validate(req.body, {
|
|
||||||
abortEarly: false
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
callback(new ErrorBuilder(406.1, error));
|
|
||||||
} else {
|
|
||||||
callback(null, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonction permettant de vérifier et de surcharger des valeurs lors d'un get
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {Function} callback
|
|
||||||
* @return {Boolean}
|
|
||||||
*/
|
|
||||||
createQuery(req, callback) {
|
|
||||||
this.setInclusions(req);
|
|
||||||
const query = {};
|
|
||||||
let where = {};
|
|
||||||
let order = [];
|
|
||||||
|
|
||||||
// On test les droits
|
|
||||||
if (!this.haveRight(req)) {
|
|
||||||
callback(new ErrorBuilder(401.1, "You're not allowed"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// On teste la query (ou les params)
|
|
||||||
const toValidate = req.getType === "list" ? req.query : req.params;
|
|
||||||
|
|
||||||
if (!toValidate) {
|
|
||||||
callback(
|
|
||||||
new ErrorBuilder(
|
|
||||||
406.0,
|
|
||||||
`Missing ${req.getType === "list" ? "query" : "params"}`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const { error, value } = this.params.validate[
|
|
||||||
req.getType
|
|
||||||
].validate(toValidate, { abortEarly: false });
|
|
||||||
|
|
||||||
// Un paramètre n'est pas bon dans la query
|
|
||||||
if (error) {
|
|
||||||
callback(new ErrorBuilder(406.1, error));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// On vire, pour le moment la liste des filtres un peu particuliers
|
|
||||||
let listOfIgnoredFilters = [
|
|
||||||
"limit",
|
|
||||||
"page",
|
|
||||||
"sort",
|
|
||||||
"order",
|
|
||||||
this.params.itemId
|
|
||||||
];
|
|
||||||
if (this.params.removeKeys && this.params.removeKeys[req.getType]) {
|
|
||||||
listOfIgnoredFilters = listOfIgnoredFilters.concat(
|
|
||||||
this.params.removeKeys[req.getType]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
this.params.override &&
|
|
||||||
this.params.override[req.getType] &&
|
|
||||||
this.params.override[req.getType].filters
|
|
||||||
) {
|
|
||||||
Object.keys(this.params.override[req.getType].filters).map(key => {
|
|
||||||
listOfIgnoredFilters.push(key);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// On rajoute les filtres autorisés
|
|
||||||
Object.keys(value).map(key => {
|
|
||||||
if (listOfIgnoredFilters.indexOf(key) === -1) {
|
|
||||||
where[key] = value[key];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (req.getType === "list") {
|
|
||||||
// Aucune pagination n'est passée, on set celle par défaut
|
|
||||||
if (!value.page || !value.limit) {
|
|
||||||
value.page = 1;
|
|
||||||
value.limit = 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Un tri est spécifié
|
|
||||||
if (value.order && value.sort) {
|
|
||||||
order = [[value.sort, value.order.toUpperCase()]];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// On get un item. on set son id
|
|
||||||
where.id = value[this.params.itemId];
|
|
||||||
}
|
|
||||||
|
|
||||||
// S'il y a des restrictions (genre un utilisateur n'a le droit de voir que tel ou tel items)
|
|
||||||
const restrict = this.restrictOn(req);
|
|
||||||
where = Object.assign(where, restrict);
|
|
||||||
|
|
||||||
// On regarde s'il n'y a pas des valeurs à overrider
|
|
||||||
const override = this.override(req, req.getType);
|
|
||||||
where = Object.assign(where, override);
|
|
||||||
|
|
||||||
if (order) {
|
|
||||||
query.order = order;
|
|
||||||
}
|
|
||||||
|
|
||||||
query.distinct = true; // On supprime les id en double (jointure de type hasmany)
|
|
||||||
query.where = where; // On rajoute des filtres
|
|
||||||
if (this.includes) {
|
|
||||||
query.include = this.includes; // On set la liste des modèles à inclure
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hack pour faire un recherche dans les nested de type hasMany
|
|
||||||
query.subQuery = false;
|
|
||||||
|
|
||||||
callback(null, query, {
|
|
||||||
start: value.page * value.limit - value.limit,
|
|
||||||
limit: value.limit
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = QueryBuilder;
|
|
|
@ -1,53 +0,0 @@
|
||||||
/**
|
|
||||||
* Fonction permettant de formater une réponse API
|
|
||||||
* @param {Object} req
|
|
||||||
* @param {Object} res
|
|
||||||
* @param {Functiont} next
|
|
||||||
* @param {Object} err
|
|
||||||
* @param {Object} response {code: Integer, res: Array/Object}
|
|
||||||
*/
|
|
||||||
const ResponseFormater = (req, res, next, err, response) => {
|
|
||||||
if (err) {
|
|
||||||
const code = err.errorCode || 500;
|
|
||||||
|
|
||||||
res
|
|
||||||
.status(Math.trunc(code))
|
|
||||||
.json({
|
|
||||||
code,
|
|
||||||
message: err.message
|
|
||||||
})
|
|
||||||
.end();
|
|
||||||
} else {
|
|
||||||
switch (req.method) {
|
|
||||||
case "GET":
|
|
||||||
res
|
|
||||||
.status(response ? 200 : 204)
|
|
||||||
.json(response)
|
|
||||||
.end();
|
|
||||||
break;
|
|
||||||
case "PATCH":
|
|
||||||
res
|
|
||||||
.status(200)
|
|
||||||
.json(response)
|
|
||||||
.end();
|
|
||||||
break;
|
|
||||||
case "DELETE":
|
|
||||||
res
|
|
||||||
.status(200)
|
|
||||||
.json(response)
|
|
||||||
.end();
|
|
||||||
break;
|
|
||||||
case "POST":
|
|
||||||
res
|
|
||||||
.status(201)
|
|
||||||
.json(response)
|
|
||||||
.end();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
next(new Error("Not implemented"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ResponseFormater;
|
|
|
@ -1,28 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
up: (queryInterface, Sequelize) => {
|
|
||||||
return queryInterface.createTable("Brands", {
|
|
||||||
id: {
|
|
||||||
allowNull: false,
|
|
||||||
autoIncrement: true,
|
|
||||||
primaryKey: true,
|
|
||||||
type: Sequelize.INTEGER
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: Sequelize.STRING,
|
|
||||||
allowNull: false,
|
|
||||||
unique: true
|
|
||||||
},
|
|
||||||
createdAt: {
|
|
||||||
allowNull: false,
|
|
||||||
type: Sequelize.DATE
|
|
||||||
},
|
|
||||||
updatedAt: {
|
|
||||||
allowNull: false,
|
|
||||||
type: Sequelize.DATE
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
down: queryInterface => {
|
|
||||||
return queryInterface.dropTable("Brands");
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,40 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
up: (queryInterface, Sequelize) => {
|
|
||||||
return queryInterface.createTable("Cars", {
|
|
||||||
id: {
|
|
||||||
allowNull: false,
|
|
||||||
autoIncrement: true,
|
|
||||||
primaryKey: true,
|
|
||||||
type: Sequelize.INTEGER
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: Sequelize.STRING
|
|
||||||
},
|
|
||||||
year: {
|
|
||||||
type: Sequelize.INTEGER
|
|
||||||
},
|
|
||||||
active: {
|
|
||||||
type: Sequelize.BOOLEAN
|
|
||||||
},
|
|
||||||
brandId: {
|
|
||||||
type: Sequelize.INTEGER,
|
|
||||||
allowNull: true,
|
|
||||||
references: {
|
|
||||||
model: "Brands",
|
|
||||||
key: "id"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
createdAt: {
|
|
||||||
allowNull: false,
|
|
||||||
type: Sequelize.DATE
|
|
||||||
},
|
|
||||||
updatedAt: {
|
|
||||||
allowNull: false,
|
|
||||||
type: Sequelize.DATE
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
down: queryInterface => {
|
|
||||||
return queryInterface.dropTable("Cars");
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,26 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
up: (queryInterface, Sequelize) => {
|
|
||||||
return queryInterface.createTable("Colors", {
|
|
||||||
id: {
|
|
||||||
allowNull: false,
|
|
||||||
autoIncrement: true,
|
|
||||||
primaryKey: true,
|
|
||||||
type: Sequelize.INTEGER
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: Sequelize.STRING
|
|
||||||
},
|
|
||||||
createdAt: {
|
|
||||||
allowNull: false,
|
|
||||||
type: Sequelize.DATE
|
|
||||||
},
|
|
||||||
updatedAt: {
|
|
||||||
allowNull: false,
|
|
||||||
type: Sequelize.DATE
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
down: queryInterface => {
|
|
||||||
return queryInterface.dropTable("Colors");
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,39 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
up: (queryInterface, Sequelize) => {
|
|
||||||
return queryInterface.createTable("CarsColors", {
|
|
||||||
id: {
|
|
||||||
allowNull: false,
|
|
||||||
autoIncrement: true,
|
|
||||||
primaryKey: true,
|
|
||||||
type: Sequelize.INTEGER
|
|
||||||
},
|
|
||||||
CarId: {
|
|
||||||
type: Sequelize.INTEGER,
|
|
||||||
allowNull: true,
|
|
||||||
references: {
|
|
||||||
model: "Cars",
|
|
||||||
key: "id"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ColorId: {
|
|
||||||
type: Sequelize.INTEGER,
|
|
||||||
allowNull: true,
|
|
||||||
references: {
|
|
||||||
model: "Colors",
|
|
||||||
key: "id"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
createdAt: {
|
|
||||||
allowNull: false,
|
|
||||||
type: Sequelize.DATE
|
|
||||||
},
|
|
||||||
updatedAt: {
|
|
||||||
allowNull: false,
|
|
||||||
type: Sequelize.DATE
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
down: queryInterface => {
|
|
||||||
return queryInterface.dropTable("CarsColors");
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,15 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
up: queryInterface => {
|
|
||||||
return queryInterface.addConstraint("CarsColors", ["CarId", "ColorId"], {
|
|
||||||
type: "unique",
|
|
||||||
name: "CarsColors_unique_carId_colorId"
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
down: queryInterface => {
|
|
||||||
return queryInterface.removeConstraint(
|
|
||||||
"CarsColors",
|
|
||||||
"CarsColors_unique_carId_colorId"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,19 +0,0 @@
|
||||||
module.exports = (sequelize, DataTypes) => {
|
|
||||||
const Brands = sequelize.define(
|
|
||||||
"Brands",
|
|
||||||
{
|
|
||||||
name: DataTypes.STRING
|
|
||||||
},
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
|
|
||||||
Brands.associate = function(models) {
|
|
||||||
Brands.hasMany(models.Cars, {
|
|
||||||
as: "Cars",
|
|
||||||
foreignKey: "brandId",
|
|
||||||
sourceKey: "id"
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return Brands;
|
|
||||||
};
|
|
|
@ -1,28 +0,0 @@
|
||||||
module.exports = (sequelize, DataTypes) => {
|
|
||||||
const Cars = sequelize.define(
|
|
||||||
"Cars",
|
|
||||||
{
|
|
||||||
name: DataTypes.STRING,
|
|
||||||
year: DataTypes.INTEGER,
|
|
||||||
active: DataTypes.BOOLEAN,
|
|
||||||
brandId: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
references: {
|
|
||||||
model: "Brands",
|
|
||||||
key: "id"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
|
|
||||||
Cars.associate = function(models) {
|
|
||||||
Cars.belongsTo(models.Brands, {
|
|
||||||
as: "Brand",
|
|
||||||
foreignKey: "brandId"
|
|
||||||
});
|
|
||||||
Cars.belongsToMany(models.Colors, { through: models.CarsColors });
|
|
||||||
};
|
|
||||||
|
|
||||||
return Cars;
|
|
||||||
};
|
|
|
@ -1,24 +0,0 @@
|
||||||
module.exports = (sequelize, DataTypes) => {
|
|
||||||
const CarsColors = sequelize.define(
|
|
||||||
"CarsColors",
|
|
||||||
{
|
|
||||||
CarId: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
references: {
|
|
||||||
model: "Cars",
|
|
||||||
key: "id"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ColorId: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
references: {
|
|
||||||
model: "Colors",
|
|
||||||
key: "id"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
|
|
||||||
return CarsColors;
|
|
||||||
};
|
|
|
@ -1,11 +0,0 @@
|
||||||
module.exports = (sequelize, DataTypes) => {
|
|
||||||
const Colors = sequelize.define(
|
|
||||||
"Colors",
|
|
||||||
{
|
|
||||||
name: DataTypes.STRING
|
|
||||||
},
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
|
|
||||||
return Colors;
|
|
||||||
};
|
|
|
@ -1,38 +0,0 @@
|
||||||
const fs = require("fs");
|
|
||||||
const path = require("path");
|
|
||||||
const Sequelize = require("sequelize");
|
|
||||||
|
|
||||||
const basename = path.basename(__filename);
|
|
||||||
const env = process.env.NODE_ENV;
|
|
||||||
// eslint-disable-next-line import/no-dynamic-require
|
|
||||||
const config = require(`${__dirname}/../config/config.json`)[env];
|
|
||||||
const db = {};
|
|
||||||
|
|
||||||
const sequelize = new Sequelize(
|
|
||||||
config.database,
|
|
||||||
config.username,
|
|
||||||
config.password,
|
|
||||||
config
|
|
||||||
);
|
|
||||||
|
|
||||||
fs.readdirSync(__dirname)
|
|
||||||
.filter(file => {
|
|
||||||
return (
|
|
||||||
file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js"
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.forEach(file => {
|
|
||||||
const model = sequelize.import(path.join(__dirname, file));
|
|
||||||
db[model.name] = model;
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(db).forEach(modelName => {
|
|
||||||
if (db[modelName].associate) {
|
|
||||||
db[modelName].associate(db);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
db.sequelize = sequelize;
|
|
||||||
db.Sequelize = Sequelize;
|
|
||||||
|
|
||||||
module.exports = db;
|
|
116
package.json
116
package.json
|
@ -1,116 +0,0 @@
|
||||||
{
|
|
||||||
"name": "sequelize-middleware",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "Middleware to automate tasks with Sequelize",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"undo:seed": "./node_modules/.bin/sequelize db:seed:undo:all",
|
|
||||||
"undo:migrate": "./node_modules/.bin/sequelize db:migrate:undo:all",
|
|
||||||
"undo:all": "yarn undo:seed && yarn undo:migrate",
|
|
||||||
"do:migrate": "./node_modules/.bin/sequelize db:migrate",
|
|
||||||
"do:seed": "./node_modules/.bin/sequelize db:seed:all",
|
|
||||||
"do:all": "yarn do:migrate && yarn do:seed",
|
|
||||||
"pretest": "yarn undo:all && yarn do:all",
|
|
||||||
"lint": "./node_modules/.bin/eslint . --fix",
|
|
||||||
"test": "jest --forceExit --detectOpenHandles --maxWorkers=10 --ci --coverage"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git@framagit.org:dbroqua/sequelize-middleware.git"
|
|
||||||
},
|
|
||||||
"author": "Damien Broqua <contact@darkou.fr>",
|
|
||||||
"license": "ISC",
|
|
||||||
"engines": {
|
|
||||||
"node": "13.x",
|
|
||||||
"yarn": "1.x"
|
|
||||||
},
|
|
||||||
"husky": {
|
|
||||||
"hooks": {
|
|
||||||
"pre-commit": "lint-staged"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lint-staged": {
|
|
||||||
"*.js": [
|
|
||||||
"./node_modules/.bin/eslint --fix",
|
|
||||||
"git add"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"jest": {
|
|
||||||
"moduleFileExtensions": [
|
|
||||||
"js"
|
|
||||||
],
|
|
||||||
"verbose": true,
|
|
||||||
"roots": [
|
|
||||||
"<rootDir>",
|
|
||||||
"<rootDir>/test/"
|
|
||||||
],
|
|
||||||
"transform": {
|
|
||||||
"^.+\\.js$": "babel-jest"
|
|
||||||
},
|
|
||||||
"transformIgnorePatterns": [
|
|
||||||
"<rootDir>/node_modules/(?!(jest-test))"
|
|
||||||
],
|
|
||||||
"testEnvironment": "node",
|
|
||||||
"setupFilesAfterEnv": [
|
|
||||||
"<rootDir>/test/utils/setup.js"
|
|
||||||
],
|
|
||||||
"collectCoverage": true,
|
|
||||||
"collectCoverageFrom": [
|
|
||||||
"**/*.js",
|
|
||||||
"*.js",
|
|
||||||
"!**/coverage/**",
|
|
||||||
"!**/migrations/**",
|
|
||||||
"!**/seeders/**",
|
|
||||||
"!**/node_modules/**",
|
|
||||||
"!**/test/**"
|
|
||||||
],
|
|
||||||
"coverageReporters": [
|
|
||||||
"text",
|
|
||||||
"html",
|
|
||||||
"cobertura"
|
|
||||||
],
|
|
||||||
"reporters": [
|
|
||||||
"default",
|
|
||||||
"jest-junit",
|
|
||||||
[
|
|
||||||
"./node_modules/jest-html-reporter",
|
|
||||||
{
|
|
||||||
"pageTitle": "Test Report",
|
|
||||||
"outputPath": "reports/html/test-results.html",
|
|
||||||
"includeFailureMsg": true,
|
|
||||||
"includeConsoleLog": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nodemonConfig": {
|
|
||||||
"ext": "*.js,*.json,*yaml"
|
|
||||||
},
|
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
|
||||||
"@babel/plugin-transform-runtime": "^7.8.3",
|
|
||||||
"@babel/preset-env": "^7.8.4",
|
|
||||||
"@hapi/joi": "^16.1.8",
|
|
||||||
"babel-eslint": "^10.0.3",
|
|
||||||
"eslint": "^6.8.0",
|
|
||||||
"eslint-config-airbnb-base": "^14.0.0",
|
|
||||||
"eslint-config-prettier": "^6.10.0",
|
|
||||||
"eslint-plugin-import": "^2.20.1",
|
|
||||||
"eslint-plugin-jest": "^23.7.0",
|
|
||||||
"eslint-plugin-prettier": "^3.1.2",
|
|
||||||
"husky": "^4.2.1",
|
|
||||||
"jest": "^25.1.0",
|
|
||||||
"jest-html-reporter": "^2.8.0",
|
|
||||||
"jest-junit": "^10.0.0",
|
|
||||||
"lint-staged": "^10.0.7",
|
|
||||||
"pg": "^7.18.1",
|
|
||||||
"pg-hstore": "^2.3.3",
|
|
||||||
"prettier": "^1.19.1",
|
|
||||||
"sequelize": "^5.21.3",
|
|
||||||
"sequelize-cli": "^5.5.1",
|
|
||||||
"sinon": "^8.1.1",
|
|
||||||
"supertest": "^4.0.2",
|
|
||||||
"uuid": "^3.4.0"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
import Joi from "@hapi/joi";
|
|
||||||
|
|
||||||
const Rules = {
|
|
||||||
model: "Brands",
|
|
||||||
crud: {
|
|
||||||
read: ["admin", "user"],
|
|
||||||
write: ["admin"],
|
|
||||||
edit: ["admin"],
|
|
||||||
delete: ["admin"]
|
|
||||||
},
|
|
||||||
includes: [
|
|
||||||
{
|
|
||||||
collection: "Cars",
|
|
||||||
requiredRole: ["admin", "user"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
format: {
|
|
||||||
user: {
|
|
||||||
id: "id",
|
|
||||||
name: "name"
|
|
||||||
},
|
|
||||||
admin: {
|
|
||||||
id: "id",
|
|
||||||
name: "name",
|
|
||||||
created: "createdAt",
|
|
||||||
updated: "updatedAt",
|
|
||||||
Cars: {
|
|
||||||
id: "id",
|
|
||||||
name: "name",
|
|
||||||
year: "year",
|
|
||||||
created: "createdAt",
|
|
||||||
updated: "updatedAt"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemId: "brandId",
|
|
||||||
validate: {
|
|
||||||
create: Joi.object({
|
|
||||||
name: Joi.string().required()
|
|
||||||
}),
|
|
||||||
update: Joi.object({
|
|
||||||
name: Joi.string()
|
|
||||||
}),
|
|
||||||
item: Joi.object({
|
|
||||||
brandId: Joi.number().required()
|
|
||||||
}),
|
|
||||||
list: Joi.object({
|
|
||||||
limit: Joi.number()
|
|
||||||
.integer()
|
|
||||||
.min(1)
|
|
||||||
.max(50),
|
|
||||||
page: Joi.number()
|
|
||||||
.integer()
|
|
||||||
.min(1),
|
|
||||||
sort: Joi.string()
|
|
||||||
.valid("id", "name", "createdAt", "updatedAt")
|
|
||||||
.only(),
|
|
||||||
order: Joi.string()
|
|
||||||
.valid("asc", "desc")
|
|
||||||
.only()
|
|
||||||
})
|
|
||||||
.with("limit", "page")
|
|
||||||
.with("page", "limit")
|
|
||||||
.with("sort", "order")
|
|
||||||
.with("order", "sort")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Rules;
|
|
130
rules/Cars.js
130
rules/Cars.js
|
@ -1,130 +0,0 @@
|
||||||
import Joi from "@hapi/joi";
|
|
||||||
|
|
||||||
const Rules = {
|
|
||||||
model: "Cars",
|
|
||||||
crud: {
|
|
||||||
read: ["admin", "user"],
|
|
||||||
write: ["admin"],
|
|
||||||
edit: ["admin"],
|
|
||||||
delete: ["admin"]
|
|
||||||
},
|
|
||||||
includes: [
|
|
||||||
{
|
|
||||||
collection: "Brand",
|
|
||||||
requiredRole: ["admin", "user"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
collection: "Colors"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
format: {
|
|
||||||
user: {
|
|
||||||
id: "id",
|
|
||||||
model: "model",
|
|
||||||
Brand: {
|
|
||||||
name: "name"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemId: "carId",
|
|
||||||
validate: {
|
|
||||||
create: Joi.object({
|
|
||||||
name: Joi.string().required(),
|
|
||||||
colorsId: Joi.array().items(Joi.number().integer()),
|
|
||||||
active: Joi.boolean(),
|
|
||||||
year: Joi.number()
|
|
||||||
.integer()
|
|
||||||
.required(),
|
|
||||||
brandId: Joi.number().integer()
|
|
||||||
}),
|
|
||||||
update: Joi.object({
|
|
||||||
name: Joi.string(),
|
|
||||||
year: Joi.number().integer(),
|
|
||||||
colorsId: Joi.array().items(Joi.number().integer())
|
|
||||||
}),
|
|
||||||
item: Joi.object({
|
|
||||||
carId: Joi.number().required()
|
|
||||||
}),
|
|
||||||
list: Joi.object({
|
|
||||||
weirdfilter: Joi.string(),
|
|
||||||
"name.lk": Joi.string(),
|
|
||||||
name: Joi.string(),
|
|
||||||
year: Joi.number().integer(),
|
|
||||||
"year.lte": Joi.number().integer(),
|
|
||||||
"year.gte": Joi.number().integer(),
|
|
||||||
limit: Joi.number()
|
|
||||||
.integer()
|
|
||||||
.min(1)
|
|
||||||
.max(50),
|
|
||||||
page: Joi.number()
|
|
||||||
.integer()
|
|
||||||
.min(1),
|
|
||||||
sort: Joi.string()
|
|
||||||
.valid("id", "name", "createdAt", "updatedAt")
|
|
||||||
.only(),
|
|
||||||
order: Joi.string()
|
|
||||||
.valid("asc", "desc")
|
|
||||||
.only()
|
|
||||||
})
|
|
||||||
.with("year.lte", "year.gte")
|
|
||||||
.with("year.gte", "year.lte")
|
|
||||||
.with("limit", "page")
|
|
||||||
.with("page", "limit")
|
|
||||||
.with("sort", "order")
|
|
||||||
.with("order", "sort")
|
|
||||||
},
|
|
||||||
restrictOn: {
|
|
||||||
list: [
|
|
||||||
{
|
|
||||||
roles: ["user"],
|
|
||||||
type: "raw",
|
|
||||||
field: "active",
|
|
||||||
value: "true"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
item: [
|
|
||||||
{
|
|
||||||
roles: ["user"],
|
|
||||||
type: "raw",
|
|
||||||
field: "active",
|
|
||||||
value: "true"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
override: {
|
|
||||||
list: {
|
|
||||||
filters: {
|
|
||||||
weirdfilter: {
|
|
||||||
$or: [
|
|
||||||
{
|
|
||||||
active: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
year: 2003
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"name.lk": {
|
|
||||||
name: {
|
|
||||||
$like: "%_TERM_%"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"year.lte": {
|
|
||||||
year: {
|
|
||||||
$lte: "_TERM_"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"year.gte": {
|
|
||||||
year: {
|
|
||||||
$gte: "_TERM_"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
belongsToMany: {
|
|
||||||
colorsId: "Colors"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Rules;
|
|
|
@ -1,47 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
up: queryInterface => {
|
|
||||||
return queryInterface.bulkInsert(
|
|
||||||
"Colors",
|
|
||||||
[
|
|
||||||
{
|
|
||||||
name: "Red",
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Miami blue",
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Sirius yellow",
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Sunflower yellow",
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Royal blue",
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "White",
|
|
||||||
createdAt: new Date(),
|
|
||||||
updatedAt: new Date()
|
|
||||||
}
|
|
||||||
],
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
down: queryInterface => {
|
|
||||||
return Promise.all([
|
|
||||||
queryInterface.bulkDelete("CarsColors", null, {}),
|
|
||||||
queryInterface.bulkDelete("Colors", null, {})
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
};
|
|
5
test.sh
5
test.sh
|
@ -1,5 +0,0 @@
|
||||||
#! /bin/bash
|
|
||||||
|
|
||||||
export NODE_ENV="test";
|
|
||||||
|
|
||||||
yarn test
|
|
|
@ -1,286 +0,0 @@
|
||||||
/* eslint-disable jest/no-test-callback */
|
|
||||||
import uuid from "uuid/v4";
|
|
||||||
import { truncate } from "./utils/common";
|
|
||||||
|
|
||||||
import models from "../models";
|
|
||||||
import Cars from "../rules/Cars";
|
|
||||||
import Middelware from "../index";
|
|
||||||
|
|
||||||
const { Op } = models.Sequelize;
|
|
||||||
|
|
||||||
let colors = [];
|
|
||||||
const colorsId = [];
|
|
||||||
let car = {};
|
|
||||||
|
|
||||||
describe("createOne", () => {
|
|
||||||
beforeAll(done => {
|
|
||||||
models.Colors.findAll({
|
|
||||||
where: {
|
|
||||||
[Op.or]: [
|
|
||||||
{
|
|
||||||
name: "White"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Miami blue"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Sunflower yellow"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(items => {
|
|
||||||
colors = items;
|
|
||||||
colorsId.push(items[0].id);
|
|
||||||
colorsId.push(items[1].id);
|
|
||||||
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch(done);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(done => {
|
|
||||||
truncate(["Cars"], done);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return new item after creation", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "POST",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
name: uuid(),
|
|
||||||
year: 2004,
|
|
||||||
active: true,
|
|
||||||
colorsId
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.createOne(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
|
|
||||||
expect(res.name).toBe(req.body.name);
|
|
||||||
expect(res.year).toBe(2004);
|
|
||||||
expect(res.active).toBe(true);
|
|
||||||
|
|
||||||
car = res;
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return item with relations", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "POST",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
carId: car.id
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getOne(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
|
|
||||||
expect(res.name).toBe(car.name);
|
|
||||||
expect(res.Colors.length).toBe(2);
|
|
||||||
expect(res.year).toBe(2004);
|
|
||||||
expect(res.Colors[0].id).toBe(colorsId[0]);
|
|
||||||
expect(res.Colors[1].id).toBe(colorsId[1]);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return all items ", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "POST",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
|
|
||||||
expect(res.data[0].name).toBe(car.name);
|
|
||||||
expect(res.data[0].Colors.length).toBe(2);
|
|
||||||
expect(res.data[0].Colors[0].id).toBe(colorsId[0]);
|
|
||||||
expect(res.data[0].Colors[1].id).toBe(colorsId[1]);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return ok when update item", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "PATCH",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
carId: car.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
body: {
|
|
||||||
year: 1998,
|
|
||||||
colorsId: [colors[2].id]
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.patchOne(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
|
|
||||||
expect(res.name).toBe(car.name);
|
|
||||||
expect(res.year).toBe(1998);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return updated item", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "PATCH",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
carId: car.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
body: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getOne(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
|
|
||||||
expect(res.name).toBe(car.name);
|
|
||||||
expect(res.year).toBe(1998);
|
|
||||||
expect(res.Colors.length).toBe(3);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return empty object after delete", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "DELETE",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
carId: car.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
body: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.deleteOne(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res).toEqual({});
|
|
||||||
|
|
||||||
models.CarsColors.findAll({
|
|
||||||
where: {
|
|
||||||
CarId: car.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(carsColors => {
|
|
||||||
expect(carsColors.length).toBe(0);
|
|
||||||
|
|
||||||
models.Cars.findAll({
|
|
||||||
where: {
|
|
||||||
id: car.id
|
|
||||||
}
|
|
||||||
}).then(items => {
|
|
||||||
expect(items.length).toBe(0);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return empty item when delete item with empty belongsTo collection", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "POST",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
name: uuid(),
|
|
||||||
year: 2004,
|
|
||||||
active: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.createOne(req, (err, newCar) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
|
|
||||||
expect(newCar.name).toBe(req.body.name);
|
|
||||||
expect(newCar.year).toBe(2004);
|
|
||||||
expect(newCar.active).toBe(true);
|
|
||||||
|
|
||||||
const reqItem = {
|
|
||||||
method: "PATCH",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
carId: newCar.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
body: {
|
|
||||||
year: 1998
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.patchOne(reqItem, errPatch => {
|
|
||||||
expect(errPatch).toBeNull();
|
|
||||||
|
|
||||||
reqItem.method = "DELETE";
|
|
||||||
|
|
||||||
middleware.deleteOne(reqItem, errDelete => {
|
|
||||||
expect(errDelete).toBeNull();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,177 +0,0 @@
|
||||||
/* eslint-disable jest/no-test-callback */
|
|
||||||
import uuid from "uuid/v4";
|
|
||||||
import { truncate } from "./utils/common";
|
|
||||||
|
|
||||||
import models from "../models";
|
|
||||||
import Brands from "../rules/Brands";
|
|
||||||
import Cars from "../rules/Cars";
|
|
||||||
import Middelware from "../index";
|
|
||||||
|
|
||||||
let createdBrand = null;
|
|
||||||
|
|
||||||
describe("createOne", () => {
|
|
||||||
afterAll(done => {
|
|
||||||
truncate(["Brands", "Cars"], done);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return a 401 when guest tries to create new item", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "POST",
|
|
||||||
user: null,
|
|
||||||
body: {
|
|
||||||
name: uuid()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.createOne(req, (err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(401.1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return a 401 when unauthorized role tries to create new item", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
|
|
||||||
middleware.createOne(
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
user: {
|
|
||||||
role: "user"
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
name: uuid()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(401.1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return a 406 when authorized role tries to create new item with missing required values", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
|
|
||||||
middleware.createOne(
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
body: {}
|
|
||||||
},
|
|
||||||
(err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(406.1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return new item when authorized role create new item", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const name = uuid();
|
|
||||||
|
|
||||||
middleware.createOne(
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
name
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res).toHaveProperty("id");
|
|
||||||
expect(res).toHaveProperty("created");
|
|
||||||
expect(res).toHaveProperty("updated");
|
|
||||||
expect(res).not.toHaveProperty("createdAt");
|
|
||||||
expect(res).not.toHaveProperty("updatedAt");
|
|
||||||
expect(res.name).toBe(name);
|
|
||||||
|
|
||||||
createdBrand = res;
|
|
||||||
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return errorCode 409.1 when authorized role tries to create new item with same unique field", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
|
|
||||||
middleware.createOne(
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
name: createdBrand.name
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(409.1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return errorCode 406.2 when authorized role tries to create new item with bad foreign id", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const name = uuid();
|
|
||||||
|
|
||||||
middleware.createOne(
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
name,
|
|
||||||
year: 2004,
|
|
||||||
brandId: createdBrand.id + 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(406.2);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return errorCode 500 when authorized role tries to create new item with too long value", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
|
|
||||||
middleware.createOne(
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
name:
|
|
||||||
"ThohWaigohhieHogahthoxohpheeDah0geetai0cieNgu1The2foQueeloochoH9eulizieshuf1nivohkied8jei5oph2Lajem6ohviijai6booTh8ienaic9eipheixa4ki1iek2pheihe7een7nei7epahngaerieghoe3ahbeil3yied0ievee1moh8jeeN5quoh6uiph6HaeZ0Eiyohshafohniewaer7gaegiefi5eiquiequoow5ohtheiw6ZeihieMoM8Ejoh7leiNeavi7uapheiwoophitoi3queiBeVeip5too8cah9Ohpaetaogahw1tei0eibuyaef3aht8aighuma6ahK4huP4cew6ohd0aiSh2umeeng7Hizahtoo6xoocePhu4ahtheex3jaijooph9iexaiqu3Nu0Ebeich6iTe",
|
|
||||||
year: 2004
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(500.0);
|
|
||||||
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,133 +0,0 @@
|
||||||
/* eslint-disable jest/no-test-callback */
|
|
||||||
import { createBrand, truncate } from "./utils/common";
|
|
||||||
|
|
||||||
import models from "../models";
|
|
||||||
import Brands from "../rules/Brands";
|
|
||||||
import Middelware from "../index";
|
|
||||||
|
|
||||||
let brand = {};
|
|
||||||
|
|
||||||
describe("deleteOne", () => {
|
|
||||||
beforeAll(done => {
|
|
||||||
createBrand((err, item) => {
|
|
||||||
if (err) {
|
|
||||||
done(err);
|
|
||||||
} else {
|
|
||||||
brand = item;
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(done => {
|
|
||||||
truncate(["Brands"], done);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 401.1 if guest tries to delete item", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "DELETE",
|
|
||||||
user: null,
|
|
||||||
params: {
|
|
||||||
brandId: brand.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.deleteOne(req, (err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(401.1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 401.1 if bad role tries to delete item", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "DELETE",
|
|
||||||
user: {
|
|
||||||
role: "user"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
brandId: brand.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.deleteOne(req, (err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(401.1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return empty item if allowed user delete item", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "DELETE",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
brandId: brand.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
body: {
|
|
||||||
name: "TEST"
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.deleteOne(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res).toEqual({});
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 404.0 if allowed user tries to delete not found item", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "DELETE",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
brandId: brand.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
body: {
|
|
||||||
name: "TEST"
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.deleteOne(req, (err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(404.0);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,436 +0,0 @@
|
||||||
/* eslint-disable jest/no-test-callback */
|
|
||||||
import { createBrands, createBrand, createCar, truncate } from "./utils/common";
|
|
||||||
|
|
||||||
import models from "../models";
|
|
||||||
import Cars from "../rules/Cars";
|
|
||||||
import Brands from "../rules/Brands";
|
|
||||||
import Middelware from "../index";
|
|
||||||
|
|
||||||
const createdCars = [];
|
|
||||||
|
|
||||||
describe("getAll (with inclusions)", () => {
|
|
||||||
beforeAll(done => {
|
|
||||||
createBrands(6, err => {
|
|
||||||
if (err) {
|
|
||||||
done(err);
|
|
||||||
} else {
|
|
||||||
createBrand((errBrand, createdBrand) => {
|
|
||||||
if (errBrand) {
|
|
||||||
done(errBrand);
|
|
||||||
} else {
|
|
||||||
createCar(createdBrand.id, true, 2004, (errCar, car) => {
|
|
||||||
if (errCar) {
|
|
||||||
done(errCar);
|
|
||||||
}
|
|
||||||
createdCars.push(car);
|
|
||||||
createCar(createdBrand.id, false, 2004, (errCar2, car2) => {
|
|
||||||
if (errCar2) {
|
|
||||||
done(errCar2);
|
|
||||||
}
|
|
||||||
createdCars.push(car2);
|
|
||||||
createCar(createdBrand.id, true, 2003, (errCar3, car3) => {
|
|
||||||
if (errCar3) {
|
|
||||||
done(errCar3);
|
|
||||||
}
|
|
||||||
createdCars.push(car3);
|
|
||||||
createCar(createdBrand.id, true, 1998, (errCar4, car4) => {
|
|
||||||
if (errCar4) {
|
|
||||||
done(errCar4);
|
|
||||||
}
|
|
||||||
createdCars.push(car4);
|
|
||||||
createCar(createdBrand.id, false, 1998, (errCar5, car5) => {
|
|
||||||
if (errCar5) {
|
|
||||||
done(errCar5);
|
|
||||||
}
|
|
||||||
createdCars.push(car5);
|
|
||||||
createBrands(2, errLastBrand => {
|
|
||||||
if (errLastBrand) {
|
|
||||||
done(errLastBrand);
|
|
||||||
} else {
|
|
||||||
models.Cars.create({
|
|
||||||
name: "la renault fuego",
|
|
||||||
year: 1980,
|
|
||||||
active: false
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
done();
|
|
||||||
})
|
|
||||||
.catch(done);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
afterAll(done => {
|
|
||||||
truncate(["Brands", "Cars"], done);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return all items when allowed role call getAll without filters (except inactive)", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "user"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res).toHaveProperty("data");
|
|
||||||
expect(res).toHaveProperty("paging");
|
|
||||||
expect(res).toHaveProperty("total");
|
|
||||||
expect(res).toHaveProperty("maxPage");
|
|
||||||
|
|
||||||
expect(res.data.length).toBe(3);
|
|
||||||
expect(res.total).toBe(3);
|
|
||||||
expect(res.maxPage).toBe(1);
|
|
||||||
|
|
||||||
expect(res.paging.first).toBeUndefined();
|
|
||||||
expect(res.paging.prev).toBeUndefined();
|
|
||||||
expect(res.paging.next).toBeUndefined();
|
|
||||||
expect(res.paging.last).toBeUndefined();
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return all items when allowed role call getAll without filters", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res).toHaveProperty("data");
|
|
||||||
expect(res).toHaveProperty("paging");
|
|
||||||
expect(res).toHaveProperty("total");
|
|
||||||
expect(res).toHaveProperty("maxPage");
|
|
||||||
|
|
||||||
expect(res.data.length).toBe(6);
|
|
||||||
expect(res.total).toBe(6);
|
|
||||||
expect(res.maxPage).toBe(1);
|
|
||||||
|
|
||||||
expect(res.paging.first).toBeUndefined();
|
|
||||||
expect(res.paging.prev).toBeUndefined();
|
|
||||||
expect(res.paging.next).toBeUndefined();
|
|
||||||
expect(res.paging.last).toBeUndefined();
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 2 items when set complex filters", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {
|
|
||||||
"year.lte": 2005,
|
|
||||||
"year.gte": 2004
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res).toHaveProperty("data");
|
|
||||||
expect(res).toHaveProperty("paging");
|
|
||||||
expect(res).toHaveProperty("total");
|
|
||||||
expect(res).toHaveProperty("maxPage");
|
|
||||||
|
|
||||||
expect(res.data.length).toBe(2);
|
|
||||||
expect(res.total).toBe(2);
|
|
||||||
expect(res.maxPage).toBe(1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 1 item when set complex filters", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "user"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {
|
|
||||||
"year.lte": 2005,
|
|
||||||
"year.gte": 2004
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res).toHaveProperty("data");
|
|
||||||
expect(res).toHaveProperty("paging");
|
|
||||||
expect(res).toHaveProperty("total");
|
|
||||||
expect(res).toHaveProperty("maxPage");
|
|
||||||
|
|
||||||
expect(res.data.length).toBe(1);
|
|
||||||
expect(res.total).toBe(1);
|
|
||||||
expect(res.maxPage).toBe(1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 1 item when get all brands", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {
|
|
||||||
sort: "id",
|
|
||||||
order: "asc"
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res).toHaveProperty("data");
|
|
||||||
expect(res).toHaveProperty("paging");
|
|
||||||
expect(res).toHaveProperty("total");
|
|
||||||
expect(res).toHaveProperty("maxPage");
|
|
||||||
|
|
||||||
expect(res.data.length).toBe(9);
|
|
||||||
expect(res.total).toBe(9);
|
|
||||||
expect(res.maxPage).toBe(1);
|
|
||||||
|
|
||||||
expect(res.data[6].Cars.length).toBe(5);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 1 item when get all brands (without cars)", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {
|
|
||||||
sort: "id",
|
|
||||||
order: "asc"
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res).toHaveProperty("data");
|
|
||||||
expect(res).toHaveProperty("paging");
|
|
||||||
expect(res).toHaveProperty("total");
|
|
||||||
expect(res).toHaveProperty("maxPage");
|
|
||||||
|
|
||||||
expect(res.data.length).toBe(9);
|
|
||||||
expect(res.total).toBe(9);
|
|
||||||
expect(res.maxPage).toBe(1);
|
|
||||||
|
|
||||||
expect(res.data[6].Cars).not.toHaveProperty("Cars");
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 3 items when admin send weirdfilter", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {
|
|
||||||
sort: "id",
|
|
||||||
order: "asc",
|
|
||||||
weirdfilter: "letsgo"
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res).toHaveProperty("data");
|
|
||||||
expect(res).toHaveProperty("paging");
|
|
||||||
expect(res).toHaveProperty("total");
|
|
||||||
expect(res).toHaveProperty("maxPage");
|
|
||||||
|
|
||||||
expect(res.data.length).toBe(3);
|
|
||||||
expect(res.total).toBe(3);
|
|
||||||
expect(res.maxPage).toBe(1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return errorCode 406.1 when trying to send unallowed filter", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {
|
|
||||||
sort: "id",
|
|
||||||
order: "asc",
|
|
||||||
id: 65
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(406.1);
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return one item when trying to get item with name contains 'renault'", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {
|
|
||||||
sort: "id",
|
|
||||||
order: "asc",
|
|
||||||
"name.lk": "renault"
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res.data.length).toBe(1);
|
|
||||||
expect(res.total).toBe(1);
|
|
||||||
expect(res.maxPage).toBe(1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return one item when trying to get item filtered by name", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {
|
|
||||||
sort: "id",
|
|
||||||
order: "asc",
|
|
||||||
name: "la renault fuego"
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res.data.length).toBe(1);
|
|
||||||
expect(res.total).toBe(1);
|
|
||||||
expect(res.maxPage).toBe(1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return empty data when trying to get item filtered by name", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {
|
|
||||||
sort: "id",
|
|
||||||
order: "asc",
|
|
||||||
name: "Clio"
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeUndefined();
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,142 +0,0 @@
|
||||||
/* eslint-disable jest/no-test-callback */
|
|
||||||
import { createBrands, truncate } from "./utils/common";
|
|
||||||
|
|
||||||
import models from "../models";
|
|
||||||
import Brands from "../rules/Brands";
|
|
||||||
import Cars from "../rules/Cars";
|
|
||||||
import Middelware from "../index";
|
|
||||||
|
|
||||||
describe("getAll", () => {
|
|
||||||
beforeAll(done => {
|
|
||||||
createBrands(40, done);
|
|
||||||
});
|
|
||||||
afterAll(done => {
|
|
||||||
truncate(["Brands", "Cars"], done);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return a 401 when guest tries to get all item", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: null,
|
|
||||||
params: {},
|
|
||||||
query: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(401.1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return a empty result allowed role get items from empty collection", async done => {
|
|
||||||
const middleware = new Middelware(Cars, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "user"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeUndefined();
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return all items when allowed role call getAll without filters", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "user"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res).toHaveProperty("data");
|
|
||||||
expect(res).toHaveProperty("paging");
|
|
||||||
expect(res).toHaveProperty("total");
|
|
||||||
expect(res).toHaveProperty("maxPage");
|
|
||||||
|
|
||||||
expect(res.data.length).toBe(40);
|
|
||||||
expect(res.total).toBe(40);
|
|
||||||
expect(res.maxPage).toBe(1);
|
|
||||||
|
|
||||||
expect(res.paging.first).toBeUndefined();
|
|
||||||
expect(res.paging.prev).toBeUndefined();
|
|
||||||
expect(res.paging.next).toBeUndefined();
|
|
||||||
expect(res.paging.last).toBeUndefined();
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 5 items when allowed role call getAll with limit filter", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "user"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {
|
|
||||||
limit: 5,
|
|
||||||
page: 3
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/?page=3&limit=5"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getAll(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res).toHaveProperty("data");
|
|
||||||
expect(res).toHaveProperty("paging");
|
|
||||||
expect(res).toHaveProperty("total");
|
|
||||||
expect(res).toHaveProperty("maxPage");
|
|
||||||
|
|
||||||
expect(res.data.length).toBe(5);
|
|
||||||
expect(res.total).toBe(40);
|
|
||||||
expect(res.maxPage).toBe(8);
|
|
||||||
|
|
||||||
expect(res.data[0]).toHaveProperty("id");
|
|
||||||
expect(res.data[0]).toHaveProperty("name");
|
|
||||||
expect(res.data[0]).not.toHaveProperty("createdAt");
|
|
||||||
expect(res.data[0]).not.toHaveProperty("created");
|
|
||||||
expect(res.data[0]).not.toHaveProperty("updatedAt");
|
|
||||||
expect(res.data[0]).not.toHaveProperty("updated");
|
|
||||||
|
|
||||||
expect(res.paging.first.href).toBe(
|
|
||||||
"http://internal.test/v1/?page=1&limit=5"
|
|
||||||
);
|
|
||||||
expect(res.paging.prev.href).toBe(
|
|
||||||
"http://internal.test/v1/?page=2&limit=5"
|
|
||||||
);
|
|
||||||
expect(res.paging.next.href).toBe(
|
|
||||||
"http://internal.test/v1/?page=4&limit=5"
|
|
||||||
);
|
|
||||||
expect(res.paging.last.href).toBe(
|
|
||||||
"http://internal.test/v1/?page=8&limit=5"
|
|
||||||
);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,166 +0,0 @@
|
||||||
/* eslint-disable jest/no-test-callback */
|
|
||||||
import { createBrands, createCar, truncate } from "./utils/common";
|
|
||||||
|
|
||||||
import models from "../models";
|
|
||||||
import Brands from "../rules/Brands";
|
|
||||||
import Middelware from "../index";
|
|
||||||
|
|
||||||
const createdCars = [];
|
|
||||||
let createdBrand = {};
|
|
||||||
|
|
||||||
describe("getOne", () => {
|
|
||||||
beforeAll(done => {
|
|
||||||
createBrands(4, (err, res) => {
|
|
||||||
if (err) {
|
|
||||||
done(err);
|
|
||||||
} else {
|
|
||||||
// eslint-disable-next-line prefer-destructuring
|
|
||||||
createdBrand = res[1];
|
|
||||||
createCar(createdBrand.id, true, 2004, (errCar, car) => {
|
|
||||||
if (errCar) {
|
|
||||||
done(errCar);
|
|
||||||
}
|
|
||||||
createdCars.push(car);
|
|
||||||
createCar(createdBrand.id, false, 2004, (errCar2, car2) => {
|
|
||||||
if (errCar2) {
|
|
||||||
done(errCar2);
|
|
||||||
}
|
|
||||||
createdCars.push(car2);
|
|
||||||
createCar(createdBrand.id, true, 2003, (errCar3, car3) => {
|
|
||||||
if (errCar3) {
|
|
||||||
done(errCar3);
|
|
||||||
}
|
|
||||||
createdCars.push(car3);
|
|
||||||
createCar(createdBrand.id, true, 1998, (errCar4, car4) => {
|
|
||||||
if (errCar4) {
|
|
||||||
done(errCar4);
|
|
||||||
}
|
|
||||||
createdCars.push(car4);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
afterAll(done => {
|
|
||||||
truncate(["Brands", "Cars"], done);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return one item with missing part", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "user"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
brandId: createdBrand.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getOne(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
|
|
||||||
expect(res.id).toBe(createdBrand.id);
|
|
||||||
expect(res.name).toBe(createdBrand.name);
|
|
||||||
expect(res).not.toHaveProperty("Cars");
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return one item with all part", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
brandId: createdBrand.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getOne(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
|
|
||||||
expect(res.id).toBe(createdBrand.id);
|
|
||||||
expect(res.name).toBe(createdBrand.name);
|
|
||||||
expect(res).toHaveProperty("Cars");
|
|
||||||
expect(res.Cars.length).toBe(4);
|
|
||||||
expect(res.Cars[0]).toHaveProperty("id");
|
|
||||||
expect(res.Cars[0]).toHaveProperty("name");
|
|
||||||
expect(res.Cars[0]).toHaveProperty("year");
|
|
||||||
expect(res.Cars[0]).toHaveProperty("created");
|
|
||||||
expect(res.Cars[0]).toHaveProperty("updated");
|
|
||||||
expect(res.Cars[0]).not.toHaveProperty("createdAt");
|
|
||||||
expect(res.Cars[0]).not.toHaveProperty("updatedAt");
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return errorCode 406.1 when missing itemId", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {},
|
|
||||||
query: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getOne(req, (err, res) => {
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(406.1);
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return empty result when item not found", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "GET",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
brandId: createdBrand.id + 666
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.getOne(req, (err, res) => {
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(404.0);
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,163 +0,0 @@
|
||||||
/* eslint-disable jest/no-test-callback */
|
|
||||||
import { createBrand, truncate } from "./utils/common";
|
|
||||||
|
|
||||||
import models from "../models";
|
|
||||||
import Brands from "../rules/Brands";
|
|
||||||
import Middelware from "../index";
|
|
||||||
|
|
||||||
let brand = {};
|
|
||||||
|
|
||||||
describe("patchOne", () => {
|
|
||||||
beforeAll(done => {
|
|
||||||
createBrand((err, item) => {
|
|
||||||
if (err) {
|
|
||||||
done(err);
|
|
||||||
} else {
|
|
||||||
brand = item;
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(done => {
|
|
||||||
truncate(["Brands"], done);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 401.1 if guest tries to update item", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "PATCH",
|
|
||||||
user: null,
|
|
||||||
params: {
|
|
||||||
brandId: brand.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.patchOne(req, (err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(401.1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 401.1 if bad role tries to update item", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "PATCH",
|
|
||||||
user: {
|
|
||||||
role: "user"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
brandId: brand.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.patchOne(req, (err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(401.1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 406.1 if allowed user tries to patch item with unallowed values", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "PATCH",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
brandId: brand.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
body: {
|
|
||||||
created: "test",
|
|
||||||
name: "TEST"
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.patchOne(req, (err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseFloat(err.errorCode)).toBe(406.1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return updated item if allowed user patch item", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "PATCH",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
brandId: brand.id
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
body: {
|
|
||||||
name: "TEST"
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.patchOne(req, (err, res) => {
|
|
||||||
expect(err).toBeNull();
|
|
||||||
expect(res.name).toBe("TEST");
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("It should return 404.1 if allowed user tries to patch not found item", async done => {
|
|
||||||
const middleware = new Middelware(Brands, models);
|
|
||||||
const req = {
|
|
||||||
method: "PATCH",
|
|
||||||
user: {
|
|
||||||
role: "admin"
|
|
||||||
},
|
|
||||||
params: {
|
|
||||||
brandId: brand.id + 1
|
|
||||||
},
|
|
||||||
query: {},
|
|
||||||
body: {
|
|
||||||
name: "TEST"
|
|
||||||
},
|
|
||||||
protocol: "http",
|
|
||||||
get: () => {
|
|
||||||
return "internal.test/";
|
|
||||||
},
|
|
||||||
originalUrl: "v1/"
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.patchOne(req, (err, res) => {
|
|
||||||
expect(res).toBeUndefined();
|
|
||||||
expect(parseInt(err.errorCode, 10)).toBe(404);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,49 +0,0 @@
|
||||||
import uuid from "uuid/v4";
|
|
||||||
import models from "../../models";
|
|
||||||
import truncateDefault from "./truncate";
|
|
||||||
|
|
||||||
const _createCar = (brandId, active, year, done) => {
|
|
||||||
models.Cars.create({
|
|
||||||
name: uuid(),
|
|
||||||
year,
|
|
||||||
active,
|
|
||||||
brandId
|
|
||||||
})
|
|
||||||
.then(item => {
|
|
||||||
done(null, item);
|
|
||||||
})
|
|
||||||
.catch(done);
|
|
||||||
};
|
|
||||||
|
|
||||||
const _createBrand = done => {
|
|
||||||
models.Brands.create({
|
|
||||||
name: uuid()
|
|
||||||
})
|
|
||||||
.then(item => {
|
|
||||||
done(null, item);
|
|
||||||
})
|
|
||||||
.catch(done);
|
|
||||||
};
|
|
||||||
|
|
||||||
const _createBrands = (total, done) => {
|
|
||||||
const created = [];
|
|
||||||
const next = () => {
|
|
||||||
if (total === created.length) {
|
|
||||||
done(null, created);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (let i = 0; i < total; i += 1) {
|
|
||||||
_createBrand((err, res) => {
|
|
||||||
if (!err) {
|
|
||||||
created.push(res);
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createBrand = _createBrand;
|
|
||||||
export const createBrands = _createBrands;
|
|
||||||
export const createCar = _createCar;
|
|
||||||
export const truncate = truncateDefault;
|
|
|
@ -1,5 +0,0 @@
|
||||||
jest.setTimeout(3000);
|
|
||||||
|
|
||||||
afterAll(done => {
|
|
||||||
done();
|
|
||||||
});
|
|
|
@ -1,45 +0,0 @@
|
||||||
import models from "../../models";
|
|
||||||
|
|
||||||
const _truncateCars = (tables, done) => {
|
|
||||||
if (tables.indexOf("Cars") === -1) {
|
|
||||||
done(null);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
models.CarsColors.destroy({
|
|
||||||
where: {}
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
models.Cars.destroy({
|
|
||||||
where: {}
|
|
||||||
}).then(() => done(null));
|
|
||||||
})
|
|
||||||
.catch(err => done(err));
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const _truncateBrands = (tables, done) => {
|
|
||||||
if (tables.indexOf("Brands") === -1) {
|
|
||||||
done(null);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
models.Brands.destroy({
|
|
||||||
where: {}
|
|
||||||
})
|
|
||||||
.then(() => done(null))
|
|
||||||
.catch(err => done(err));
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default (tables, done) => {
|
|
||||||
_truncateCars(tables, errCars => {
|
|
||||||
if (errCars) {
|
|
||||||
done(errCars);
|
|
||||||
} else {
|
|
||||||
_truncateBrands(tables, errBrands => {
|
|
||||||
done(errBrands);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
Loading…
Reference in a new issue