This commit is contained in:
David Arranz 2019-05-09 18:23:54 +02:00
parent a513dcb32e
commit bbc792ed33
26 changed files with 916 additions and 72 deletions

View File

@ -15,5 +15,10 @@ module.exports = {
server: {
hostname: process.env.HOSTNAME || '127.0.0.1',
port: process.env.PORT || 1337
},
paginate: {
limit: 10,
maxLimit: 50
}
}

118
core/controllers/find.js Normal file
View File

@ -0,0 +1,118 @@
function extractFindOptions(req, res, targetAttributes) {
const result = {};
result.params = (req && req.params) ? req.params : null;
if (res && res.locals) {
Object.keys(res.locals).forEach(key => {
result[key] = res.locals[key]
})
}
console.log(result);
return result;
}
function parseFindOptions(findOptions, targetAttributes) {
const result = {};
// Where
if (findOptions.params) {
result.where = findOptions.params
}
// Paginate
if (findOptions.paginate) {
result.page = findOptions.paginate.page;
result.limit = findOptions.paginate.limit;
}
// Order
if (findOptions.sort) {
result.order = [];
Object.keys(findOptions.sort).forEach(key => {
let dir = findOptions.sort[key] ? 'ASC' : 'DESC';
result.order.push([key, dir])
});
}
// Attributes
if (findOptions.fields) {
if (findOptions.fields.validFields) {
result.attributes = findOptions.fields.validFields
}
if (findOptions.fields.invalidFields && Array.isArray(findOptions.fields.invalidFields)) {
result.attributes = targetAttributes.filter(attr => !findOptions.fields.invalidFields.includes(attr));
}
}
return result;
}
function checkIsModel(target) {
return !!target.getTableName;
}
function checkIsAssociation(target) {
return !!target.associationType;
}
function resultIsAList(params) {
const _params = Object.keys(params);
if (_params && Array.isArray(_params) && model.primaryKeyAttributes && Array.isArray(model.primaryKeyAttributes)) {
return !model.primaryKeyAttributes.every(field => _params.includes(field));
} else {
return true;
}
}
function _find(modelMaybeThunk, options = {}) {
/*if (typeof modelMaybeThunk != 'function' && !checkIsModel(modelMaybeThunk) && !checkIsAssociation(modelMaybeThunk)) {
throw new Error('resolverFactory should be called with a model, an association or a function (which resolves to a model or an association)');
}*/
if (options.before === undefined) options.before = (options) => options;
if (options.after === undefined) options.after = (result) => result;
return async function (req, res, next) {
let target = typeof modelMaybeThunk === 'function' && !checkIsModel(modelMaybeThunk) ?
await Promise.resolve(modelMaybeThunk(req, res, next)) : modelMaybeThunk;
let isModel = checkIsModel(target),
isAssociation = checkIsAssociation(target),
association = isAssociation && target,
isList = options.list || resultIsAList(req.params),
model = isAssociation && target.target || isModel && target;
let findOptions = extractFindOptions(req, res);
let targetAttributes = Object.keys(model.rawAttributes);
findOptions = parseFindOptions(findOptions, targetAttributes);
console.log(findOptions);
return Promise.resolve(options.before(findOptions, req, res))
.then(findOptions => {
return model[isList ? 'fetchAll' : 'fetch'](findOptions);
})
.then(result => {
return options.after(result, req, res);
});
}
}
const defaultOptions = {
//before: optimizeAttributes,
}
const find = (model, options = defaultOptions) => {
return async function (req, res, next) {
return _find(model, options)(req, res, next)
}
}
module.exports = find;

91
core/controllers/index.js Normal file
View File

@ -0,0 +1,91 @@
const _find = require('./find');
const httpStatus = require('http-status');
const { extractParamsFromRequest, handleErrorResponse, handleResultResponse } = require('../../helpers/controller.helper');
function buildContext(req, res) {
return {
user: req.user
}
}
const defaultOptions = {
MODULE_NAME: 'default'
}
const generateControllers = (service, extraControllers = {}, options = defaultOptions) => {
const defaultControllers = {
find: async (req, res, next) => {
const params = extractParamsFromRequest(req, res);
try {
const result = await service.fetchAll(params, buildContext(req, res));
return handleResultResponse(result.rows, result.count, params, res);
} catch (error) {
handleErrorResponse(options.MODULE_NAME, 'find', error, res)
}
},
findOne: async (req, res, next) => {
const params = extractParamsFromRequest(req, res);
try {
const result = await service.fetchOne(params, buildContext(req, res));
console.log(result);
return handleResultResponse(result, null, params, res, (result === null) ? httpStatus.NOT_FOUND : httpStatus.OK);
} catch (error) {
handleErrorResponse(options.MODULE_NAME, 'findOne', error, res)
}
},
count: async(req, res, next) => {
const params = extractParamsFromRequest(req, res);
try {
const result = await service.count(params, buildContext(req, res));
return handleResultResponse(result, null, params, res);
} catch (error) {
handleErrorResponse(options.MODULE_NAME, 'count', error, res)
}
},
create: async (req, res, next) => {
try {
const result = await service.create(req.body, buildContext(req, res));
return handleResultResponse(result, null, null, res, httpStatus.CREATED)
} catch (error) {
handleErrorResponse(options.MODULE_NAME, 'create', error, res)
}
},
update: async (req, res, next) => {
try {
const result = await service.update(req.params, req.body, buildContext(req, res));
return handleResultResponse(result, null, req.params, res, httpStatus.OK)
} catch (error) {
handleErrorResponse(options.MODULE_NAME, 'update', error, res)
}
},
delete: async (req, res, next) => {
try {
const result = await service.delete(req.params, buildContext(req, res));
return handleResultResponse(result, null, req.params, res, httpStatus.NO_CONTENT);
} catch (error) {
handleErrorResponse(options.MODULE_NAME, 'delete', error, res)
}
},
}
//const associationControllers = generateAssociationControllers(model, options);
//console.log(associationControllers);
return {
...defaultControllers,
//...associationControllers
...extraControllers
}
}
module.exports = generateControllers;

View File

@ -10,10 +10,10 @@ const cors = require('cors');
const helmet = require('helmet');
const passport = require('passport');
const config = require('../config');
const router = require('./router');
const error = require('../middlewares/error');
/**
* Express instance
* @public
@ -75,7 +75,6 @@ app.use(cors({
app.use(passport.initialize());
require('./passport');
// Set routes
app.use('/api', router());

View File

@ -5,24 +5,8 @@ const express = require('./express');
const logger = require('./logger');
const models = require('./models');
//const modules = require('./modules');
//const middlewares = require('./middlewares');
//const hooks = require('./hooks');
//const plugins = require('./plugins');
// const admin = require('./admin');
//const store = require('./store');
module.exports = {
//nestedConfigurations: nested,
express,
logger,
//appConfigurations: app,
//modules,
models,
//middlewares,
//hooks,
//plugins,
// admin,
//store
};

View File

@ -3,7 +3,6 @@ const passport = require('passport');
const { Strategy: LocalStrategy } = require('passport-local');
const { Strategy: JWTStrategy} = require('passport-jwt');
const config = require('../config');
const models = require('./models');
const securityHelper = require('../helpers/security.helper');
@ -28,7 +27,9 @@ const localOptions = {
passport.use('local', new LocalStrategy(localOptions, async (email, password, done) => {
try {
const user = await models.User.findOne({ where: { email } });
const user = await models.User.findOne({
where: { email },
});
if (_.isNull(user)) {
return done(null, false, { message: 'User not found' })
@ -38,6 +39,7 @@ passport.use('local', new LocalStrategy(localOptions, async (email, password, do
if (!isPasswordValid) {
return done(null, false, { message: 'Wrong Password' })
} else {
delete user.password;
return done(null, user, { message: 'Logged in Successfully' });
}
}
@ -49,7 +51,11 @@ passport.use('local', new LocalStrategy(localOptions, async (email, password, do
// JWT
passport.use('jwt', new JWTStrategy(securityHelper.jwtOptions, async (jwtPayload, done) => {
try {
const user = await models.User.findOne({ where: { id: jwtPayload.id } });
const user = await models.User.findOne({
attributes: { exclude: [ 'password' ] },
where: { id: jwtPayload.id },
raw: true
});
if (_.isNull(user)) {
return done(null, false, { message: 'User not found' })

View File

@ -33,22 +33,95 @@ function buildErrorResponse(nameController, nameMethod, error) {
return jsonResultFailed;
}
function getTotalCount(result) {
const toType = function (obj) {
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
switch (toType(result)) {
case 'boolean':
return 1;
case 'object':
return 1;
case 'array':
return result.length;
case 'null':
return 0;
default:
return 0;
}
}
function setPaginationInfo(totalCount, res) {
res.set({
'X-Total-Count': totalCount,
});
const params = extractParamsFromRequest(null, res);
console.log(params);
if (params.paginate) {
const
page = (params.paginate && params.paginate.page) ? params.paginate.page : null,
limit = (params.paginate && params.paginate.limit) ? params.paginate.limit : null,
count = (limit) ? Math.ceil(totalCount / limit) : null;
if (params.paginate.hasNextPages(count)) {
const nextPage = params.paginate.href();
res.set('Link', nextPage + '; rel=next');
res.set('Pagination-Next-Page', true);
} else {
res.set('Pagination-Next-Page', false);
}
res.set({
'Pagination-Count': count,
'Pagination-Page': page,
'Pagination-Limit': limit,
});
}
}
////////////////////////////////////////////////////////////////////////////////
// PUBLIC FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
function extractParamsFromRequest(req, res) {
const result = {};
result.params = (req && req.params) ? req.params : null;
result.query = (req && req.query) ? req.params : null;
if (res && res.locals) {
Object.keys(res.locals).forEach(key => {
result[key] = res.locals[key]
})
}
return result;
}
function handleErrorResponse(controllerName, methodName, error, res) {
const jsonResultFailed = buildErrorResponse(controllerName, methodName, error);
res.status(httpStatus.INTERNAL_SERVER_ERROR).send(jsonResultFailed);
}
function handleResultResponse(result, totalCount = null, params, res, statusCode = httpStatus.OK) {
setPaginationInfo((totalCount) ? totalCount : getTotalCount(result), res);
res.status(statusCode).send(result);
}
////////////////////////////////////////////////////////////////////////////////
// MODULE EXPORTS
////////////////////////////////////////////////////////////////////////////////
module.exports = {
extractParamsFromRequest,
handleErrorResponse,
handleResultResponse,
// for testing
buildErrorLog,
buildErrorResponse

View File

@ -0,0 +1,19 @@
'use strict';
function compose(middlewareArray) {
if (!middlewareArray.length) {
return function (_req, _res, next) { next(); };
}
let head = middlewareArray[0];
let tail = middlewareArray.slice(1);
return function (req, res, next) {
head(req, res, function (err) {
if (err) return next(err);
compose(tail)(req, res, next);
});
};
}
module.exports = compose;

206
helpers/service.helper.js Normal file
View File

@ -0,0 +1,206 @@
const _ = require('lodash');
const parseParamsToFindOptions = (params) => {
const result = {};
// Query
if (params.query) {
result.query = params.query
}
// Where
if (params.params) {
result.where = params.params
}
// Paginate
if (params.paginate) {
result.offset = params.paginate.limit * (params.paginate.page - 1);
result.limit = result.offset + params.paginate.limit;
}
// Order
if (params.sort) {
result.order = [];
Object.keys(params.sort).forEach(key => {
let dir = params.sort[key] ? 'ASC' : 'DESC';
result.order.push([key, dir])
});
}
// Attributes
if (params.fields) {
if (params.fields.validFields) {
result.attributes = params.fields.validFields
}
if (params.fields.invalidFields && Array.isArray(params.fields.invalidFields)) {
result.attributes = {
...result.attributes,
exclude: params.fields.invalidFields
}
}
}
return result;
}
const defaultOptions = {};
const generateService = (model, extraMethods = {}, options = defaultOptions) => {
const defaultService = {
fetchAll: async (params, context) => {
const findOptions = parseParamsToFindOptions(params);
return await model.findAndCountAll(findOptions);
},
fetchOne: async (params, context) => {
return await model.findOne({ where: { 'id': params.id } });
},
count: async (params, context) => {
// Convert `params` object to filters compatible with Bookshelf.
//const filters = strapi.utils.models.convertParams('post', params);
return await model.count(params);
},
create: async (values, context) => {
return await model.create(values);
},
update: async (params, values, context) => {
// Extract values related to relational data.
const relations = _.pick(values, Post.associations.map(ast => ast.alias));
const data = _.omit(values, Post.associations.map(ast => ast.alias));
// Create entry with no-relational data.
const entry = await Post.forge(params).save(data);
// Create relational data and return the entry.
return Post.updateRelations(Object.assign(params, {
values: relations
}));
},
delete: async (params, context) => {
const numAffectedRows = await model.destroy({ where: { 'id': params.id } });
return (numAffectedRows > 0);
/*params.values = {};
Post.associations.map(association => {
switch (association.nature) {
case 'oneWay':
case 'oneToOne':
case 'manyToOne':
case 'oneToManyMorph':
params.values[association.alias] = null;
break;
case 'oneToMany':
case 'manyToMany':
case 'manyToManyMorph':
params.values[association.alias] = [];
break;
default:
}
});
await Post.updateRelations(params);
return Post.forge(params).destroy();*/
},
search: async (params, context) => {
// Convert `params` object to filters compatible with Bookshelf.
const filters = strapi.utils.models.convertParams('post', params);
// Select field to populate.
const populate = Post.associations
.filter(ast => ast.autoPopulate !== false)
.map(ast => ast.alias);
const associations = Post.associations.map(x => x.alias);
const searchText = Object.keys(Post._attributes)
.filter(attribute => attribute !== Post.primaryKey && !associations.includes(attribute))
.filter(attribute => ['string', 'text'].includes(Post._attributes[attribute].type));
const searchNoText = Object.keys(Post._attributes)
.filter(attribute => attribute !== Post.primaryKey && !associations.includes(attribute))
.filter(attribute => !['string', 'text', 'boolean', 'integer', 'decimal', 'float'].includes(Post._attributes[attribute].type));
const searchInt = Object.keys(Post._attributes)
.filter(attribute => attribute !== Post.primaryKey && !associations.includes(attribute))
.filter(attribute => ['integer', 'decimal', 'float'].includes(Post._attributes[attribute].type));
const searchBool = Object.keys(Post._attributes)
.filter(attribute => attribute !== Post.primaryKey && !associations.includes(attribute))
.filter(attribute => ['boolean'].includes(Post._attributes[attribute].type));
const query = (params._q || '').replace(/[^a-zA-Z0-9.-\s]+/g, '');
return Post.query(qb => {
// Search in columns which are not text value.
searchNoText.forEach(attribute => {
qb.orWhereRaw(`LOWER(${attribute}) LIKE '%${_.toLower(query)}%'`);
});
if (!_.isNaN(_.toNumber(query))) {
searchInt.forEach(attribute => {
qb.orWhereRaw(`${attribute} = ${_.toNumber(query)}`);
});
}
if (query === 'true' || query === 'false') {
searchBool.forEach(attribute => {
qb.orWhereRaw(`${attribute} = ${_.toNumber(query === 'true')}`);
});
}
// Search in columns with text using index.
switch (Post.client) {
case 'mysql':
qb.orWhereRaw(`MATCH(${searchText.join(',')}) AGAINST(? IN BOOLEAN MODE)`, `*${query}*`);
break;
case 'pg':
{
const searchQuery = searchText.map(attribute =>
_.toLower(attribute) === attribute ?
`to_tsvector(${attribute})` :
`to_tsvector('${attribute}')`
);
qb.orWhereRaw(`${searchQuery.join(' || ')} @@ to_tsquery(?)`, query);
break;
}
}
if (filters.sort) {
qb.orderBy(filters.sort.key, filters.sort.order);
}
if (filters.skip) {
qb.offset(_.toNumber(filters.skip));
}
if (filters.limit) {
qb.limit(_.toNumber(filters.limit));
}
}).fetchAll({
withRelated: populate
});
}
}
return {
...defaultService,
//...associationControllers
...extraMethods
}
}
module.exports = {
generateService,
parseParamsToFindOptions,
defaultOptions
}

View File

@ -1,19 +1,24 @@
'use strict';
const passport = require('passport');
const httpStatus = require('http-status');
const compose = require('../helpers/middleware.helper');
exports.isRegisteresUser = passport.authenticate('local', { session: false });
exports.isLoggedUser = passport.authenticate('jwt', { session: false });
/**
* Authorization Required middleware.
*/
exports.isAuthorized = (req, res, next) => {
const provider = req.path.split('/').slice(-1)[0];
const token = req.user.tokens.find(token => token.kind === provider);
if (token) {
next();
} else {
res.redirect(`/auth/${provider}`);
const isRegisteredUser = passport.authenticate('local', { session: false });
const isLoggedUser = passport.authenticate('jwt', { session: false });
const isAdministratorUser = compose([isLoggedUser,
(req, res, next) => {
const user = req.user;
if (user.role >= 8) {
next();
} else {
return res.status(httpStatus.UNAUTHORIZED).send('UNAUTHORIZED');
}
}
]);
module.exports = {
isRegisteredUser,
isLoggedUser,
isAdministratorUser
};

66
middlewares/fields.js Normal file
View File

@ -0,0 +1,66 @@
"use strict";
/*
Fields middleware
This module exports a function that takes an optional configuration object parameter with the following
properties:
{
validFields: Array of strings (case sensitive),
invalidFields: Array of strings (case sensitive),
}
and returns an express compatible middleware function (req, res, next) that parses the following
parameters from the req.query object and sets an object on the res.locals.fields having the following
properties:
Object - with fields for the attributes value fields
*/
const middleware = (config) => {
config = config || {
validFields: null,
invalidFields: null,
};
if (config.validFields && (!Array.isArray(config.validFields))) {
throw new Error("config.validFields should be a non empty array of strings");
}
if (config.invalidFields && (!Array.isArray(config.invalidFields))) {
throw new Error("config.invalidFields should be a non empty array of strings");
}
return function (req, res, next) {
const fieldNames = Array.isArray(req.query.fields)
? req.query.fields
: req.query.fields
? [req.query.fields]
: [];
const fieldObject = fieldNames.filter(field => {
let isOk = true;
if (config.validFields) {
isOk = config.validFields.includes(field)
}
if (config.invalidFields) {
isOk = !config.invalidFields.includes(field)
}
return isOk;
});
res.locals.fields = {};
(Object.keys(fieldObject).length > 0) ? res.locals.fields['fields'] = fieldObject : null;
config.invalidFields ? res.locals.fields['invalidFields'] = config.invalidFields : null;
config.validFields ? res.locals.fields['validFields'] = config.validFields : null,
next();
};
}
module.exports = {
middleware
}

122
middlewares/paginate.js Normal file
View File

@ -0,0 +1,122 @@
'use strict';
// Node.js pagination middleware and view helpers.
// * Author: [@niftylettuce](https://twitter.com/#!/niftylettuce)
// * Source: <https://github.com/niftylettuce/middleware paginate>
const qs = require('qs');
const url = require('url');
const _ = require('lodash');
//const util = require('util');
const href = (req) => {
return function (prev, params) {
const query = _.clone(req.query);
if (typeof prev === 'object') {
params = prev;
prev = false;
} else {
prev = (typeof prev === 'boolean') ? prev : false;
query.page = parseInt(query.page, 10);
query.page = prev ? query.page -= 1 : query.page += 1;
query.page = (query.page < 1) ? 1 : query.page;
}
// allow overriding querystring params
// (useful for sorting and filtering)
// another alias for `_.assign` is `_.extend`
if (_.isObject(params))
query = _.assign(query, params);
return url.parse(req.originalUrl).pathname + '?' + qs.stringify(query);
};
};
const hasNextPages = (req) => {
return function (pageCount) {
if (typeof pageCount !== 'number' || pageCount < 0)
throw new Error('middleware paginate: `pageCount` is not a number >= 0');
return req.query.page < pageCount;
};
};
const getArrayPages = (req) => {
return function (limit, pageCount, currentPage) {
const maxPage = pageCount;
// limit default is 3
limit = limit || 3;
if (typeof limit !== 'number' || limit < 0)
throw new Error('middleware paginate: `limit` is not a number >= 0');
if (typeof pageCount !== 'number' || pageCount < 0)
throw new Error('middleware paginate: `pageCount` is not a number >= 0');
currentPage = parseInt(currentPage, 10);
if (Number.isNaN(currentPage) || currentPage < 0)
throw new Error('middleware paginate: `currentPage` is not a number >= 0');
if (limit > 0) {
let end = Math.min(Math.max(currentPage + Math.floor(limit / 2), limit), pageCount);
let start = Math.max(1, (currentPage < (limit - 1)) ? 1 : (end - limit) + 1);
let pages = [];
for (let i = start; i <= end; i++) {
pages.push({
number: i,
url: href(req)()
.replace('page=' + (currentPage + 1), 'page=' + i)
});
}
return pages;
}
}
}
const middleware = (limit = 10, maxLimit = 50) => {
const _limit = (typeof limit === 'number') ? parseInt(limit, 10) : 10;
const _maxLimit = (typeof maxLimit === 'number') ? parseInt(maxLimit, 10) : 50;
return function _middleware(req, res, next) {
req.query.page = (typeof req.query.page === 'string') ? parseInt(req.query.page, 10) || 1 : 1;
req.query.limit = (typeof req.query.limit === 'string') ? parseInt(req.query.limit, 10) || 0 : _limit;
if (req.query.limit > _maxLimit)
req.query.limit = _maxLimit;
if (req.query.page < 1)
req.query.page = 1;
if (req.query.limit < 0)
req.query.limit = 0;
//req.skip = req.offset = (req.query.page * req.query.limit) - req.query.limit;
res.locals.paginate = res.locals.paginate ? res.locals.paginate : {};
res.locals.paginate.page = req.query.page;
res.locals.paginate.limit = req.query.limit;
res.locals.paginate.href = href(req);
res.locals.paginate.hasPreviousPages = req.query.page > 1;
res.locals.paginate.hasNextPages = hasNextPages(req);
res.locals.paginate.getArrayPages = getArrayPages(req);
next();
};
};
module.exports = {
href,
hasNextPages,
getArrayPages,
middleware
}

View File

@ -28,7 +28,7 @@ module.exports = (schema, useJoiError = false) => {
const _schema = schema
if (_schema) {
console.log(req.body);
// Validate req.body using the schema and validation options
return Joi.validate(req.body, _schema, _validationOptions, (err, data) => {

67
middlewares/sort.js Normal file
View File

@ -0,0 +1,67 @@
"use strict";
/*
Sort middleware
This module exports a function that takes a configuration object parameter with the following
properties:
{
validKeys: Array of strings (case sensitive),
default: String (optional, by default assigned to the first element of the
validKeys array with ascending sorting order unless prefixed by a "-")
}
and returns an express compatible middleware function (req, res, next) that parses the following
parameters from the req.query object and sets an object on the res.locals.sort having the following
properties:
Object - with keys for the sort value fields and value a boolean denoting ascending order
or not
*/
const middleware = (config) => {
if (typeof config !== "object" || config === null) {
throw new Error("The config parameter is mandatory and should be an object!");
}
config = config || {};
if (!config.default && (!Array.isArray(config.validKeys) || config.validKeys.length === 0)) {
throw new Error("config.validKeys should be a non empty array of strings or a config.default key should be defined!");
}
config.default = config.default || config.validKeys[0];
const defaultSortIsAscending = config.default.substring(0, 1) !== "-";
return function (req, res, next) {
const sortKeys = Array.isArray(req.query.sort)
? req.query.sort
: req.query.sort
? [req.query.sort]
: [];
const sortObject = sortKeys.reduce(function (c, key) {
const ascending = key.substring(0, 1) !== "-";
if (!ascending) {
key = key.substr(1);
}
if (key && config.validKeys && config.validKeys.indexOf(key) !== -1 ) {
c[key] = ascending;
}
return c;
}, {});
if (Object.keys(sortObject).length === 0) {
sortObject[
defaultSortIsAscending
? config.default
: config.default.substr(1)
] = defaultSortIsAscending;
}
res.locals.sort = sortObject;
next();
};
}
module.exports = {
middleware
}

View File

@ -2,11 +2,9 @@
const _ = require('lodash');
const httpStatus = require('http-status');
const passport = require('passport');
const controllerHelper = require('../../helpers/controller.helper');
const messageHelper = require('../../helpers/message.helper');
const securityHelper = require('../../helpers/security.helper');
const authService = require('./auth.service');
////////////////////////////////////////////////////////////////////////////////

View File

@ -13,7 +13,7 @@ const AccessValidator = require('../../middlewares/accessValidator');
routes.post('/auth',
SchemaValidator(authValidation.LoginInputType, true),
AccessValidator.isRegisteresUser,
AccessValidator.isRegisteredUser,
authController.login,
);

View File

@ -19,6 +19,11 @@ module.exports = function (sequelize, DataTypes) {
type: DataTypes.STRING,
allowNull: false,
},
role: {
type: DataTypes.TINYINT,
allowNull: false,
defaultValue: 0,
},
}, {
tableName: 'user',
freezeTableName: true,

View File

@ -0,0 +1,21 @@
'use strict';
const generateControllers = require('../../core/controllers');
const blogService = require('./blog.service');
// Module Name
const MODULE_NAME = '[blog.controller]';
// Error Messages
//const NOT_FOUND = 'Videogame not found';
// Success Messages
//const VG_CT_VIDEOGAME_DELETED_SUCCESSFULLY = 'Videogame deleted successfully';
const controllerOptions = { MODULE_NAME };
const extraControllers = {};
module.exports = generateControllers(blogService, extraControllers, controllerOptions);

View File

@ -1,35 +1,37 @@
const routes = require('express').Router();
const models = require('../../core/models');
//const postService = require('./post.service')(models.Post);
//const postController = require('./post.controller')(postService);
const { ModelHandler } = require('sequelize-handlers');
const postHandler = new ModelHandler(models.Post);
/*const postService = require('./post.service')(models.Post);
const postController = require('./post.controller')(postService);*/
routes.use((req, res, next) => {
// here we can access the req.params object and make auth checks
next();
});
const { isAdministratorUser, isLoggedUser } = require('../../middlewares/accessValidator');
const PaginateMiddleware = require('../../middlewares/paginate');
const SortMiddleware = require('../../middlewares/sort');
const FieldMiddleware = require('../../middlewares/fields');
routes.get('/posts', postHandler.query());
const blogController = require('./blog.controller')
/*routes.get('/posts', function (req, res) {
postController.find(req).then(data => {
console.log(data);
res.status(200).json(data);
})
});*/
routes.get('/posts/count', function (req, res) {
//res.status(200).json(postController.count(req));
});
routes.get('/posts/:id', function (req, res) {
//res.status(200).json(postController.findOne(req));
});
routes.get('/posts',
isLoggedUser,
FieldMiddleware.middleware({
invalidFields: ['user', 'created']
}),
PaginateMiddleware.middleware(),
SortMiddleware.middleware({ default: "date" }),
blogController.find);
routes.post('/posts', isAdministratorUser, blogController.create);
routes.get('/posts/:id',
isLoggedUser,
FieldMiddleware.middleware({
invalidFields: ['updatedAt', 'createdAt']
}),
//PaginateMiddleware.middleware(),
//SortMiddleware.middleware({ default: "date" }),
blogController.findOne);
routes.put('/posts/:id', isAdministratorUser, blogController.update);
routes.delete('/posts/:id', isAdministratorUser, blogController.delete);
module.exports = routes;

View File

@ -0,0 +1,23 @@
/* global Post */
'use strict';
const _ = require('lodash');
const { generateService, parseParamsToFindOptions } = require('../../helpers/service.helper');
const models = require('../../core/models');
const extraMethods = {
fetchOne: async (params, context) => {
const findOptions = parseParamsToFindOptions(params);
console.log(findOptions);
const result = await models.Post.findByPk(findOptions.query.id, {
include: [{ all: true }]
});
console.log(result);
return result;
},
}
module.exports = generateService(models.Post, extraMethods);

View File

@ -0,0 +1,14 @@
'use strict';
const generateControllers = require('../../core/controllers');
const categoryService = require('./category.service');
// Module Name
const MODULE_NAME = '[category.controller]';
const controllerOptions = { MODULE_NAME };
const extraControllers = {};
module.exports = generateControllers(categoryService, extraControllers, controllerOptions);

View File

@ -2,6 +2,7 @@ module.exports = function (sequelize, DataTypes) {
const Category = sequelize.define('Category', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
@ -11,7 +12,7 @@ module.exports = function (sequelize, DataTypes) {
sort: {
type: DataTypes.INTEGER,
defaultValue: 0,
allowNull: false,
allowNull: false,
}
}, {
tableName: 'category',
@ -20,7 +21,7 @@ module.exports = function (sequelize, DataTypes) {
});
Category.beforeCreate((category) => {
category.dataValues.id = Math.floor(Math.random() * (999 - 8)) + 8;
//category.dataValues.id = Math.floor(Math.random() * (999 - 8)) + 8;
})
Category.associate = function (models) {

View File

@ -0,0 +1,17 @@
const routes = require('express').Router();
const { isAdministratorUser, isLoggedUser } = require('../../middlewares/accessValidator');
/*const PaginateMiddleware = require('../../middlewares/paginate');
const SortMiddleware = require('../../middlewares/sort');
const FieldMiddleware = require('../../middlewares/fields');*/
const categoryController = require('./category.controller');
routes.get('/categories', isLoggedUser, categoryController.find);
routes.get('/categories/:id', isLoggedUser, categoryController.findOne);
routes.post('/categories/', isAdministratorUser, categoryController.create);
routes.put('/categories/:id', isAdministratorUser, categoryController.update);
routes.delete('/categories/:id', isAdministratorUser, categoryController.delete);
module.exports = routes;

View File

@ -0,0 +1,10 @@
/* global Post */
'use strict';
const _ = require('lodash');
const { generateService, parseParamsToFindOptions } = require('../../helpers/service.helper');
const models = require('../../core/models');
const extraMethods = {};
module.exports = generateService(models.Category, extraMethods);

View File

@ -49,7 +49,6 @@
"pino": "^4.7.1",
"response-time": "^2.3.2",
"sequelize": "^5.3.5",
"sequelize-handlers": "^1.0.7",
"vm": "^0.1.0",
"winston": "^3.2.1"
}

View File

@ -2828,13 +2828,6 @@ send@0.16.2:
range-parser "~1.2.0"
statuses "~1.4.0"
sequelize-handlers@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/sequelize-handlers/-/sequelize-handlers-1.0.7.tgz#1ef1d81447bdcd608ae42f5855d7fc2d978bf57a"
integrity sha512-fyNPYLSF03mRwy/gyJJOxH7fN3R6os5Ptsj18Gezfpt/T6mLFwOvxHp+dWd6O1KDNBr0JZi4kIj8FuDq55upbw==
dependencies:
lodash "^4.17.11"
sequelize-pool@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-1.0.2.tgz#89c767882bbdb8a41dac66922ed9820939a5401e"