.
This commit is contained in:
parent
a513dcb32e
commit
bbc792ed33
@ -15,5 +15,10 @@ module.exports = {
|
|||||||
server: {
|
server: {
|
||||||
hostname: process.env.HOSTNAME || '127.0.0.1',
|
hostname: process.env.HOSTNAME || '127.0.0.1',
|
||||||
port: process.env.PORT || 1337
|
port: process.env.PORT || 1337
|
||||||
|
},
|
||||||
|
|
||||||
|
paginate: {
|
||||||
|
limit: 10,
|
||||||
|
maxLimit: 50
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
118
core/controllers/find.js
Normal file
118
core/controllers/find.js
Normal 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
91
core/controllers/index.js
Normal 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;
|
||||||
@ -10,10 +10,10 @@ const cors = require('cors');
|
|||||||
const helmet = require('helmet');
|
const helmet = require('helmet');
|
||||||
const passport = require('passport');
|
const passport = require('passport');
|
||||||
|
|
||||||
|
const config = require('../config');
|
||||||
const router = require('./router');
|
const router = require('./router');
|
||||||
const error = require('../middlewares/error');
|
const error = require('../middlewares/error');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Express instance
|
* Express instance
|
||||||
* @public
|
* @public
|
||||||
@ -75,7 +75,6 @@ app.use(cors({
|
|||||||
app.use(passport.initialize());
|
app.use(passport.initialize());
|
||||||
require('./passport');
|
require('./passport');
|
||||||
|
|
||||||
|
|
||||||
// Set routes
|
// Set routes
|
||||||
app.use('/api', router());
|
app.use('/api', router());
|
||||||
|
|
||||||
|
|||||||
@ -5,24 +5,8 @@ const express = require('./express');
|
|||||||
const logger = require('./logger');
|
const logger = require('./logger');
|
||||||
const models = require('./models');
|
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 = {
|
module.exports = {
|
||||||
//nestedConfigurations: nested,
|
|
||||||
express,
|
express,
|
||||||
logger,
|
logger,
|
||||||
//appConfigurations: app,
|
|
||||||
//modules,
|
|
||||||
models,
|
models,
|
||||||
//middlewares,
|
|
||||||
//hooks,
|
|
||||||
//plugins,
|
|
||||||
// admin,
|
|
||||||
//store
|
|
||||||
};
|
};
|
||||||
@ -3,7 +3,6 @@ const passport = require('passport');
|
|||||||
const { Strategy: LocalStrategy } = require('passport-local');
|
const { Strategy: LocalStrategy } = require('passport-local');
|
||||||
const { Strategy: JWTStrategy} = require('passport-jwt');
|
const { Strategy: JWTStrategy} = require('passport-jwt');
|
||||||
|
|
||||||
const config = require('../config');
|
|
||||||
const models = require('./models');
|
const models = require('./models');
|
||||||
const securityHelper = require('../helpers/security.helper');
|
const securityHelper = require('../helpers/security.helper');
|
||||||
|
|
||||||
@ -28,7 +27,9 @@ const localOptions = {
|
|||||||
|
|
||||||
passport.use('local', new LocalStrategy(localOptions, async (email, password, done) => {
|
passport.use('local', new LocalStrategy(localOptions, async (email, password, done) => {
|
||||||
try {
|
try {
|
||||||
const user = await models.User.findOne({ where: { email } });
|
const user = await models.User.findOne({
|
||||||
|
where: { email },
|
||||||
|
});
|
||||||
|
|
||||||
if (_.isNull(user)) {
|
if (_.isNull(user)) {
|
||||||
return done(null, false, { message: 'User not found' })
|
return done(null, false, { message: 'User not found' })
|
||||||
@ -38,6 +39,7 @@ passport.use('local', new LocalStrategy(localOptions, async (email, password, do
|
|||||||
if (!isPasswordValid) {
|
if (!isPasswordValid) {
|
||||||
return done(null, false, { message: 'Wrong Password' })
|
return done(null, false, { message: 'Wrong Password' })
|
||||||
} else {
|
} else {
|
||||||
|
delete user.password;
|
||||||
return done(null, user, { message: 'Logged in Successfully' });
|
return done(null, user, { message: 'Logged in Successfully' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,7 +51,11 @@ passport.use('local', new LocalStrategy(localOptions, async (email, password, do
|
|||||||
// JWT
|
// JWT
|
||||||
passport.use('jwt', new JWTStrategy(securityHelper.jwtOptions, async (jwtPayload, done) => {
|
passport.use('jwt', new JWTStrategy(securityHelper.jwtOptions, async (jwtPayload, done) => {
|
||||||
try {
|
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)) {
|
if (_.isNull(user)) {
|
||||||
return done(null, false, { message: 'User not found' })
|
return done(null, false, { message: 'User not found' })
|
||||||
|
|||||||
@ -33,22 +33,95 @@ function buildErrorResponse(nameController, nameMethod, error) {
|
|||||||
return jsonResultFailed;
|
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
|
// 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) {
|
function handleErrorResponse(controllerName, methodName, error, res) {
|
||||||
|
|
||||||
const jsonResultFailed = buildErrorResponse(controllerName, methodName, error);
|
const jsonResultFailed = buildErrorResponse(controllerName, methodName, error);
|
||||||
res.status(httpStatus.INTERNAL_SERVER_ERROR).send(jsonResultFailed);
|
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
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
extractParamsFromRequest,
|
||||||
handleErrorResponse,
|
handleErrorResponse,
|
||||||
|
handleResultResponse,
|
||||||
// for testing
|
// for testing
|
||||||
buildErrorLog,
|
buildErrorLog,
|
||||||
buildErrorResponse
|
buildErrorResponse
|
||||||
|
|||||||
19
helpers/middleware.helper.js
Normal file
19
helpers/middleware.helper.js
Normal 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
206
helpers/service.helper.js
Normal 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
|
||||||
|
}
|
||||||
@ -1,19 +1,24 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const passport = require('passport');
|
const passport = require('passport');
|
||||||
|
const httpStatus = require('http-status');
|
||||||
|
const compose = require('../helpers/middleware.helper');
|
||||||
|
|
||||||
exports.isRegisteresUser = passport.authenticate('local', { session: false });
|
const isRegisteredUser = passport.authenticate('local', { session: false });
|
||||||
exports.isLoggedUser = passport.authenticate('jwt', { session: false });
|
const isLoggedUser = passport.authenticate('jwt', { session: false });
|
||||||
|
const isAdministratorUser = compose([isLoggedUser,
|
||||||
/**
|
(req, res, next) => {
|
||||||
* Authorization Required middleware.
|
const user = req.user;
|
||||||
*/
|
if (user.role >= 8) {
|
||||||
exports.isAuthorized = (req, res, next) => {
|
next();
|
||||||
const provider = req.path.split('/').slice(-1)[0];
|
} else {
|
||||||
const token = req.user.tokens.find(token => token.kind === provider);
|
return res.status(httpStatus.UNAUTHORIZED).send('UNAUTHORIZED');
|
||||||
if (token) {
|
}
|
||||||
next();
|
|
||||||
} else {
|
|
||||||
res.redirect(`/auth/${provider}`);
|
|
||||||
}
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
isRegisteredUser,
|
||||||
|
isLoggedUser,
|
||||||
|
isAdministratorUser
|
||||||
};
|
};
|
||||||
66
middlewares/fields.js
Normal file
66
middlewares/fields.js
Normal 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
122
middlewares/paginate.js
Normal 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
|
||||||
|
}
|
||||||
@ -28,7 +28,7 @@ module.exports = (schema, useJoiError = false) => {
|
|||||||
const _schema = schema
|
const _schema = schema
|
||||||
|
|
||||||
if (_schema) {
|
if (_schema) {
|
||||||
console.log(req.body);
|
|
||||||
// Validate req.body using the schema and validation options
|
// Validate req.body using the schema and validation options
|
||||||
return Joi.validate(req.body, _schema, _validationOptions, (err, data) => {
|
return Joi.validate(req.body, _schema, _validationOptions, (err, data) => {
|
||||||
|
|
||||||
|
|||||||
67
middlewares/sort.js
Normal file
67
middlewares/sort.js
Normal 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
|
||||||
|
}
|
||||||
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const httpStatus = require('http-status');
|
const httpStatus = require('http-status');
|
||||||
const passport = require('passport');
|
|
||||||
const controllerHelper = require('../../helpers/controller.helper');
|
const controllerHelper = require('../../helpers/controller.helper');
|
||||||
const messageHelper = require('../../helpers/message.helper');
|
const messageHelper = require('../../helpers/message.helper');
|
||||||
const securityHelper = require('../../helpers/security.helper');
|
const securityHelper = require('../../helpers/security.helper');
|
||||||
const authService = require('./auth.service');
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const AccessValidator = require('../../middlewares/accessValidator');
|
|||||||
|
|
||||||
routes.post('/auth',
|
routes.post('/auth',
|
||||||
SchemaValidator(authValidation.LoginInputType, true),
|
SchemaValidator(authValidation.LoginInputType, true),
|
||||||
AccessValidator.isRegisteresUser,
|
AccessValidator.isRegisteredUser,
|
||||||
authController.login,
|
authController.login,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,11 @@ module.exports = function (sequelize, DataTypes) {
|
|||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
},
|
},
|
||||||
|
role: {
|
||||||
|
type: DataTypes.TINYINT,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: 0,
|
||||||
|
},
|
||||||
}, {
|
}, {
|
||||||
tableName: 'user',
|
tableName: 'user',
|
||||||
freezeTableName: true,
|
freezeTableName: true,
|
||||||
|
|||||||
21
modules/blog/blog.controller.js
Normal file
21
modules/blog/blog.controller.js
Normal 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);
|
||||||
|
|
||||||
@ -1,35 +1,37 @@
|
|||||||
const routes = require('express').Router();
|
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 postService = require('./post.service')(models.Post);
|
||||||
const postHandler = new ModelHandler(models.Post);
|
const postController = require('./post.controller')(postService);*/
|
||||||
|
|
||||||
routes.use((req, res, next) => {
|
const { isAdministratorUser, isLoggedUser } = require('../../middlewares/accessValidator');
|
||||||
// here we can access the req.params object and make auth checks
|
const PaginateMiddleware = require('../../middlewares/paginate');
|
||||||
next();
|
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) {
|
routes.get('/posts',
|
||||||
postController.find(req).then(data => {
|
isLoggedUser,
|
||||||
console.log(data);
|
FieldMiddleware.middleware({
|
||||||
res.status(200).json(data);
|
invalidFields: ['user', 'created']
|
||||||
})
|
}),
|
||||||
});*/
|
PaginateMiddleware.middleware(),
|
||||||
|
SortMiddleware.middleware({ default: "date" }),
|
||||||
routes.get('/posts/count', function (req, res) {
|
blogController.find);
|
||||||
//res.status(200).json(postController.count(req));
|
|
||||||
});
|
|
||||||
|
|
||||||
routes.get('/posts/:id', function (req, res) {
|
|
||||||
//res.status(200).json(postController.findOne(req));
|
|
||||||
});
|
|
||||||
|
|
||||||
|
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;
|
module.exports = routes;
|
||||||
23
modules/blog/blog.service.js
Normal file
23
modules/blog/blog.service.js
Normal 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);
|
||||||
14
modules/blog/category.controller.js
Normal file
14
modules/blog/category.controller.js
Normal 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);
|
||||||
|
|
||||||
@ -2,6 +2,7 @@ module.exports = function (sequelize, DataTypes) {
|
|||||||
const Category = sequelize.define('Category', {
|
const Category = sequelize.define('Category', {
|
||||||
id: {
|
id: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
|
autoIncrement: true,
|
||||||
primaryKey: true
|
primaryKey: true
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
@ -20,7 +21,7 @@ module.exports = function (sequelize, DataTypes) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Category.beforeCreate((category) => {
|
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) {
|
Category.associate = function (models) {
|
||||||
|
|||||||
17
modules/blog/category.routes.js
Normal file
17
modules/blog/category.routes.js
Normal 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;
|
||||||
10
modules/blog/category.service.js
Normal file
10
modules/blog/category.service.js
Normal 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);
|
||||||
@ -49,7 +49,6 @@
|
|||||||
"pino": "^4.7.1",
|
"pino": "^4.7.1",
|
||||||
"response-time": "^2.3.2",
|
"response-time": "^2.3.2",
|
||||||
"sequelize": "^5.3.5",
|
"sequelize": "^5.3.5",
|
||||||
"sequelize-handlers": "^1.0.7",
|
|
||||||
"vm": "^0.1.0",
|
"vm": "^0.1.0",
|
||||||
"winston": "^3.2.1"
|
"winston": "^3.2.1"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2828,13 +2828,6 @@ send@0.16.2:
|
|||||||
range-parser "~1.2.0"
|
range-parser "~1.2.0"
|
||||||
statuses "~1.4.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:
|
sequelize-pool@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-1.0.2.tgz#89c767882bbdb8a41dac66922ed9820939a5401e"
|
resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-1.0.2.tgz#89c767882bbdb8a41dac66922ed9820939a5401e"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user