.
This commit is contained in:
parent
1f6d27f220
commit
a28814a420
@ -9,7 +9,7 @@ module.exports = {
|
||||
|
||||
session: {
|
||||
secret_token: process.env.SECRET_TOKEN || "B57J=7B`NQ$y98|~5;hc715bo09^5oz8NR+]n9r~215B91Nd9P%25_N6r!GHcOKp|18y5-73Dr5^@9k7n]5l<-41D1o",
|
||||
token_expires_in: 86400000
|
||||
token_expires_in: '99d'
|
||||
},
|
||||
|
||||
server: {
|
||||
|
||||
@ -9,7 +9,7 @@ module.exports = {
|
||||
|
||||
session: {
|
||||
secret_token: process.env.SECRET_TOKEN || "B57J=7B`NQ$y98|~5;hc715bo09^5oz8NR+]n9r~215B91Nd9P%25_N6r!GHcOKp|18y5-73Dr5^@9k7n]5l<-41D1o",
|
||||
token_expires_in: 86400000
|
||||
token_expires_in: '24h'
|
||||
},
|
||||
|
||||
server: {
|
||||
|
||||
@ -12,7 +12,7 @@ const passport = require('passport');
|
||||
|
||||
const router = require('./router');
|
||||
const error = require('../middlewares/error');
|
||||
const access = require('../middlewares/access');
|
||||
|
||||
|
||||
/**
|
||||
* Express instance
|
||||
@ -42,12 +42,14 @@ app.use(methodOverride());
|
||||
// secure apps by setting various HTTP headers
|
||||
app.use(helmet());
|
||||
|
||||
|
||||
// enable CORS - Cross Origin Resource Sharing
|
||||
app.use(cors({
|
||||
exposeHeaders: [
|
||||
"WWW-Authenticate",
|
||||
"Server-Authorization"
|
||||
"Server-Authorization",
|
||||
"Content-Disposition",
|
||||
"Content-Type",
|
||||
"Content-Length"
|
||||
],
|
||||
maxAge: 31536000,
|
||||
credentials: true,
|
||||
@ -71,7 +73,7 @@ app.use(cors({
|
||||
|
||||
// Access validator
|
||||
app.use(passport.initialize());
|
||||
passport.use('jwt', access.jwt);
|
||||
require('./passport');
|
||||
|
||||
|
||||
// Set routes
|
||||
|
||||
@ -5,9 +5,7 @@ const Sequelize = require('sequelize');
|
||||
const config = require('../config');
|
||||
const log = require('./logger');
|
||||
|
||||
|
||||
const modulesDir = path.resolve(__dirname + '/../modules/')
|
||||
const basename = path.basename(__dirname);
|
||||
const globOptions = {
|
||||
cwd: modulesDir,
|
||||
nocase: true,
|
||||
|
||||
63
core/passport.js
Normal file
63
core/passport.js
Normal file
@ -0,0 +1,63 @@
|
||||
const _ = require('lodash');
|
||||
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');
|
||||
|
||||
|
||||
passport.serializeUser((user, done) => {
|
||||
done(null, user.id);
|
||||
});
|
||||
|
||||
passport.deserializeUser((id, done) => {
|
||||
models.User.findById(id, (err, user) => {
|
||||
done(err, user);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Sign in using Email and Password.
|
||||
*/
|
||||
const localOptions = {
|
||||
usernameField: 'email',
|
||||
passwordField: 'password'
|
||||
}
|
||||
|
||||
passport.use('local', new LocalStrategy(localOptions, async (email, password, done) => {
|
||||
try {
|
||||
const user = await models.User.findOne({ where: { email } });
|
||||
|
||||
if (_.isNull(user)) {
|
||||
return done(null, false, { message: 'User not found' })
|
||||
} else {
|
||||
const isPasswordValid = await user.comparePassword(password);
|
||||
|
||||
if (!isPasswordValid) {
|
||||
return done(null, false, { message: 'Wrong Password' })
|
||||
} else {
|
||||
return done(null, user, { message: 'Logged in Successfully' });
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return done(error);
|
||||
}
|
||||
}));
|
||||
|
||||
// JWT
|
||||
passport.use('jwt', new JWTStrategy(securityHelper.jwtOptions, async (jwtPayload, done) => {
|
||||
try {
|
||||
const user = await models.User.findOne({ where: { id: jwtPayload.id } });
|
||||
|
||||
if (_.isNull(user)) {
|
||||
return done(null, false, { message: 'User not found' })
|
||||
} else {
|
||||
return done(null, user, { message: 'User found' });
|
||||
}
|
||||
} catch (error) {
|
||||
return done(error);
|
||||
}
|
||||
}));
|
||||
|
||||
55
helpers/controller.helper.js
Normal file
55
helpers/controller.helper.js
Normal file
@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const httpStatus = require('http-status');
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE FUNCTIONS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function buildErrorLog(err) {
|
||||
let errorLog;
|
||||
if (_.isUndefined(err)) {
|
||||
errorLog = 'Error not defined';
|
||||
} else if (!_.isUndefined(err.message)) {
|
||||
errorLog = err.message;
|
||||
} else if (!_.isUndefined(err.stack)) {
|
||||
errorLog = err.stack;
|
||||
} else {
|
||||
errorLog = JSON.stringify(err);
|
||||
}
|
||||
return errorLog;
|
||||
}
|
||||
|
||||
function buildErrorResponse(nameController, nameMethod, error) {
|
||||
|
||||
const errorDescription = buildErrorLog(error);
|
||||
|
||||
const jsonResultFailed = {
|
||||
code: httpStatus.INTERNAL_SERVER_ERROR,
|
||||
message: 'Internal Server Error',
|
||||
description: `Internal Application Error in ${nameController}:${nameMethod}. ${errorDescription}`
|
||||
}
|
||||
return jsonResultFailed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function handleErrorResponse(controllerName, methodName, error, res) {
|
||||
|
||||
const jsonResultFailed = buildErrorResponse(controllerName, methodName, error);
|
||||
res.status(httpStatus.INTERNAL_SERVER_ERROR).send(jsonResultFailed);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// MODULE EXPORTS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module.exports = {
|
||||
handleErrorResponse,
|
||||
// for testing
|
||||
buildErrorLog,
|
||||
buildErrorResponse
|
||||
};
|
||||
37
helpers/message.helper.js
Normal file
37
helpers/message.helper.js
Normal file
@ -0,0 +1,37 @@
|
||||
'use strict';
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// CONSTANTS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const TITLE_ERROR = 'error';
|
||||
const TITLE_MESSAGE = 'message';
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE FUNCTIONS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function buildGenericMessage(nameMessage, textMessage) {
|
||||
const jsonMessageResult = {};
|
||||
jsonMessageResult[nameMessage] = textMessage;
|
||||
return jsonMessageResult;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function buildErrorMessage(text) {
|
||||
return buildGenericMessage(TITLE_ERROR, text)
|
||||
}
|
||||
|
||||
function buildMessage(text) {
|
||||
return buildGenericMessage(TITLE_MESSAGE, text)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
buildErrorMessage,
|
||||
buildMessage,
|
||||
//For testing
|
||||
buildGenericMessage
|
||||
}
|
||||
111
helpers/security.helper.js
Normal file
111
helpers/security.helper.js
Normal file
@ -0,0 +1,111 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const bCrypt = require('bcrypt');
|
||||
const config = require('../config');
|
||||
|
||||
const privateKEY = fs.readFileSync(path.join(__dirname, '..', 'private.key'), 'utf8');
|
||||
const publicKEY = fs.readFileSync(path.join(__dirname, '..', 'public.key'), 'utf8');
|
||||
|
||||
const signOptions = {
|
||||
issuer: 'Fundación LQDVI',
|
||||
subject: 'info@loquedeverdadimporta.org',
|
||||
audience: 'htts://www.loquedeverdadimporta.org',
|
||||
};
|
||||
|
||||
const _genSalt = (rounds = 10) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
bCrypt.genSalt(rounds, function (err, salt) {
|
||||
if (err) return reject(err);
|
||||
return resolve(salt);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const _hashPassword = (password, salt) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
bCrypt.hash(password, salt, function (err, hash) {
|
||||
if (err) return reject(err);
|
||||
return resolve(hash);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// https://medium.com/@siddharthac6/json-web-token-jwt-the-right-way-of-implementing-with-node-js-65b8915d550e
|
||||
|
||||
const _sign = (payload, options) => {
|
||||
/*
|
||||
options = {
|
||||
issuer: "Authorizaxtion/Resource/This server",
|
||||
subject: "iam@user.me",
|
||||
audience: "Client_Identity" // this should be provided by client
|
||||
}
|
||||
*/
|
||||
|
||||
// Token signing options
|
||||
const signOptions = {
|
||||
issuer: options.issuer,
|
||||
subject: options.subject,
|
||||
audience: options.audience,
|
||||
expiresIn: config.session.token_expires_in,
|
||||
algorithm: "RS256"
|
||||
};
|
||||
|
||||
return jwt.sign(payload, privateKEY, signOptions);
|
||||
}
|
||||
|
||||
const _verify = (token, options) => {
|
||||
/*
|
||||
options = {
|
||||
issuer: "Authorization/Resource/This server",
|
||||
subject: "iam@user.me",
|
||||
audience: "Client_Identity" // this should be provided by client
|
||||
}
|
||||
*/
|
||||
|
||||
const verifyOptions = {
|
||||
issuer: options.issuer,
|
||||
subject: options.subject,
|
||||
audience: options.audience,
|
||||
expiresIn: config.session.token_expires_in,
|
||||
algorithm: ["RS256"]
|
||||
};
|
||||
|
||||
try {
|
||||
return jwt.verify(token, publicKEY, verifyOptions);
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const _decode = (token) => {
|
||||
//returns null if token is invalid
|
||||
return jwt.decode(token, { complete: true });
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
jwtOptions: {
|
||||
jwtFromRequest: (req) => ((req && req.headers && req.headers['x-access-token']) ? req.headers['x-access-token'] : null),
|
||||
secretOrKey: publicKEY,
|
||||
...signOptions,
|
||||
},
|
||||
|
||||
generateHashPassword: async (password) => {
|
||||
const salt = await _genSalt();
|
||||
return _hashPassword(password, salt)
|
||||
},
|
||||
|
||||
isValidPassword: async (password, candidate) => {
|
||||
return await bCrypt.compareSync(candidate, password);
|
||||
},
|
||||
|
||||
generateToken: (payload) => {
|
||||
return _sign(payload, signOptions);
|
||||
},
|
||||
|
||||
verify: (token) => {
|
||||
return _verify(token, signOptions);
|
||||
}
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const config = require('../config');
|
||||
const { logger } = require('../core');
|
||||
|
||||
const JwtStrategy = require('passport-jwt').Strategy;
|
||||
const { ExtractJwt } = require('passport-jwt');
|
||||
//const User = this.models.User;
|
||||
|
||||
const jwtOptions = {
|
||||
secretOrKey: config.session.secret_token,
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
|
||||
};
|
||||
|
||||
const jwt = async (payload, done) => {
|
||||
logger.info(payload);
|
||||
try {
|
||||
//const user = await User.findById(payload.sub);
|
||||
//if (user) return done(null, user);
|
||||
return done(null, false);
|
||||
} catch (error) {
|
||||
return done(error, false);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.jwt = new JwtStrategy(jwtOptions, jwt);
|
||||
29
middlewares/accessValidator.js
Normal file
29
middlewares/accessValidator.js
Normal file
@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
const passportJWT = require("passport-jwt");
|
||||
const JWTStrategy = passportJWT.Strategy;
|
||||
const ExtractJWT = passportJWT.ExtractJwt;
|
||||
const config = require('../config');
|
||||
|
||||
/**
|
||||
* Login Required middleware.
|
||||
*/
|
||||
exports.isAuthenticated = (req, res, next) => {
|
||||
if (req.isAuthenticated()) {
|
||||
return next();
|
||||
}
|
||||
res.redirect('/login');
|
||||
};
|
||||
|
||||
/**
|
||||
* 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}`);
|
||||
}
|
||||
};
|
||||
@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const httpStatus = require('http-status');
|
||||
const expressValidation = require('express-validation');
|
||||
const APIError = require('./APIError');
|
||||
|
||||
|
||||
/**
|
||||
* Error handler. Send stacktrace only during development
|
||||
* @public
|
||||
@ -28,14 +28,7 @@ exports.handler = handler;
|
||||
exports.converter = (err, req, res, next) => {
|
||||
let convertedError = err;
|
||||
|
||||
if (err instanceof expressValidation.ValidationError) {
|
||||
convertedError = new APIError({
|
||||
message: 'Error de validación',
|
||||
errors: err.errors,
|
||||
status: err.status,
|
||||
stack: err.stack,
|
||||
});
|
||||
} else if (!(err instanceof APIError)) {
|
||||
if (!(err instanceof APIError)) {
|
||||
convertedError = new APIError({
|
||||
message: err.message,
|
||||
status: err.status,
|
||||
|
||||
73
middlewares/schemaValidator.js
Normal file
73
middlewares/schemaValidator.js
Normal file
@ -0,0 +1,73 @@
|
||||
const _ = require('lodash');
|
||||
const Joi = require('joi');
|
||||
|
||||
module.exports = (schema, useJoiError = false) => {
|
||||
// useJoiError determines if we should respond with the base Joi error
|
||||
// boolean: defaults to false
|
||||
const _useJoiError = _.isBoolean(useJoiError) && useJoiError;
|
||||
|
||||
// enabled HTTP methods for request data validation
|
||||
const _supportedMethods = ['post', 'put'];
|
||||
|
||||
// Joi validation options
|
||||
const _validationOptions = {
|
||||
abortEarly: false, // abort after the last validation error
|
||||
allowUnknown: true, // allow unknown keys that will be ignored
|
||||
stripUnknown: true // remove unknown keys from the validated data
|
||||
};
|
||||
|
||||
// return the validation middleware
|
||||
return (req, res, next) => {
|
||||
|
||||
const route = req.route.path;
|
||||
const method = req.method.toLowerCase();
|
||||
|
||||
if (_.includes(_supportedMethods, method)) {
|
||||
|
||||
// get schema for the current route
|
||||
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) => {
|
||||
|
||||
if (err) {
|
||||
|
||||
// Joi Error
|
||||
const JoiError = {
|
||||
status: 'failed',
|
||||
error: {
|
||||
original: err._object,
|
||||
|
||||
// fetch only message and type from each error
|
||||
details: _.map(err.details, ({ message, type }) => ({
|
||||
message: message.replace(/['"]/g, ''),
|
||||
type
|
||||
}))
|
||||
}
|
||||
};
|
||||
|
||||
// Custom Error
|
||||
const CustomError = {
|
||||
status: 'failed',
|
||||
error: 'Invalid request data. Please review request and try again.'
|
||||
};
|
||||
|
||||
// Send back the JSON error response
|
||||
res.status(422).json(_useJoiError ? JoiError : CustomError);
|
||||
|
||||
} else {
|
||||
// Replace req.body with the data after Joi validation
|
||||
req.body = data;
|
||||
next();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
72
modules/auth/auth.controller.js
Normal file
72
modules/auth/auth.controller.js
Normal file
@ -0,0 +1,72 @@
|
||||
'use strict';
|
||||
|
||||
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');
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// CONSTANTS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Module Name
|
||||
const MODULE_NAME = '[auth.controller]';
|
||||
|
||||
// Error Messages
|
||||
const NOT_FOUND = 'Videogame not found';
|
||||
|
||||
// Success Messages
|
||||
const VG_CT_VIDEOGAME_DELETED_SUCCESSFULLY = 'Videogame deleted successfully';
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC METHODS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
async function login(req, res, next) {
|
||||
try {
|
||||
passport.authenticate('local', { session: false }, async (error, user, info) => {
|
||||
try {
|
||||
if (!user) {
|
||||
return res.status(httpStatus.NOT_FOUND).json(messageHelper.buildMessage(NOT_FOUND));
|
||||
}
|
||||
|
||||
req.login(user, { session: false }, async (error) => {
|
||||
if (error) {
|
||||
return controllerHelper.handleErrorResponse(MODULE_NAME, login.name, error, res);
|
||||
}
|
||||
|
||||
//We don't want to store the sensitive information such as the
|
||||
//user password in the token so we pick only the email and id
|
||||
const data = {
|
||||
id: user.id,
|
||||
email: user.email
|
||||
};
|
||||
|
||||
//Send back the token to the user
|
||||
return res.json({
|
||||
token: securityHelper.generateToken({ user: data }),
|
||||
user: {
|
||||
id: data.id,
|
||||
email: data.email
|
||||
},
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
})(req, res, next);
|
||||
|
||||
} catch (error) {
|
||||
controllerHelper.handleErrorResponse(MODULE_NAME, login.name, error, res)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
login,
|
||||
MODULE_NAME
|
||||
}
|
||||
35
modules/auth/auth.routes.js
Normal file
35
modules/auth/auth.routes.js
Normal file
@ -0,0 +1,35 @@
|
||||
const routes = require('express').Router();
|
||||
const passport = require('passport');
|
||||
const authController = require('./auth.controller');
|
||||
const authValidation = require('./auth.validations');
|
||||
const securityHelper = require('../../helpers/security.helper');
|
||||
const SchemaValidator = require('../../middlewares/schemaValidator');
|
||||
|
||||
//const postService = require('./post.service')(models.Post);
|
||||
//const postController = require('./post.controller')(postService);
|
||||
|
||||
//const { ModelHandler } = require('sequelize-handlers');
|
||||
//const postHandler = new ModelHandler(models.Post);
|
||||
|
||||
routes.post('/auth',
|
||||
SchemaValidator(authValidation.login, true),
|
||||
passport.authenticate('local'),
|
||||
function (req, res, next) {
|
||||
const data = {
|
||||
id: req.user.id,
|
||||
email: req.user.email
|
||||
};
|
||||
|
||||
return res.json({
|
||||
token: securityHelper.generateToken(data),
|
||||
user: data,
|
||||
});
|
||||
}
|
||||
//authController.login
|
||||
);
|
||||
|
||||
routes.get('/pepepe', passport.authenticate('jwt', { session: false }), function (req, res, next) {
|
||||
res.send(req.user.email);
|
||||
});
|
||||
|
||||
module.exports = routes;
|
||||
17
modules/auth/auth.service.js
Normal file
17
modules/auth/auth.service.js
Normal file
@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
//const JwtHelper = require('../../helpers/jwt.helper');
|
||||
const models = require('../../core/models');
|
||||
|
||||
function findOne(params) {
|
||||
return models.User.findOne({
|
||||
where: params
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
findOne,
|
||||
login: async (params) => {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
15
modules/auth/auth.validations.js
Normal file
15
modules/auth/auth.validations.js
Normal file
@ -0,0 +1,15 @@
|
||||
const Joi = require('joi');
|
||||
|
||||
const LoginInputType = Joi.object().keys({
|
||||
email: Joi.string().email().required(),
|
||||
password: Joi.string().required()
|
||||
});
|
||||
|
||||
const LoginOutputType = Joi.object().keys({
|
||||
token: Joi.string().required()
|
||||
});
|
||||
|
||||
|
||||
module.exports = {
|
||||
login: LoginInputType,
|
||||
};
|
||||
60
modules/auth/user.model.js
Normal file
60
modules/auth/user.model.js
Normal file
@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
|
||||
const { isValidPassword, generateHashPassword } = require('../../helpers/security.helper');
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
const User = sequelize.define('User', {
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
},
|
||||
email: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
validate: { isEmail: true }
|
||||
},
|
||||
password: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
}, {
|
||||
tableName: 'user',
|
||||
freezeTableName: true,
|
||||
timestamps: true,
|
||||
});
|
||||
|
||||
User.associate = function (models) {
|
||||
/*User.Categories = User.belongsToMany(models.Category, {
|
||||
through: models.UserCategory,
|
||||
foreignKey: 'UserId'
|
||||
});*/
|
||||
//User.Comments = User.hasMany(models.UserComment, { foreignKey: 'UserId' });
|
||||
//User.Reactions = User.hasMany(models.UserReaction, { foreignKey: 'UserId' });
|
||||
//User.User = User.belongsTo(models.User, { foreignKey: 'userId' });
|
||||
};
|
||||
|
||||
|
||||
User.beforeCreate(async function (model, options) {
|
||||
const encrypted = await generateHashPassword(model.password)
|
||||
model.password = encrypted;
|
||||
return model;
|
||||
});
|
||||
|
||||
// Instance Methods
|
||||
// InventoryLevel.prototype.someMethod = function () {...}
|
||||
|
||||
User.prototype.comparePassword = async function (candidatePassword) {
|
||||
|
||||
const user = this;
|
||||
|
||||
if (user.password) {
|
||||
return await isValidPassword(user.password, candidatePassword)
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return User;
|
||||
};
|
||||
@ -1,16 +1,35 @@
|
||||
const routes = require('express').Router();
|
||||
const models = require('../../core/models');
|
||||
const postService = require('./post.service')(models.Post);
|
||||
const postController = require('./post.controller')(postService);
|
||||
//const postService = require('./post.service')(models.Post);
|
||||
//const postController = require('./post.controller')(postService);
|
||||
|
||||
const { ModelHandler } = require('sequelize-handlers');
|
||||
const postHandler = new ModelHandler(models.Post);
|
||||
|
||||
routes.use((req, res, next) => {
|
||||
// here we can access the req.params object and make auth checks
|
||||
next();
|
||||
});
|
||||
|
||||
routes.get('/posts', function (req, res) {
|
||||
data = postController.find(req)
|
||||
res.status(200).json(data);
|
||||
routes.get('/posts', postHandler.query());
|
||||
|
||||
/*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));
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = routes;
|
||||
@ -9,8 +9,6 @@ module.exports = function (sequelize, DataTypes) {
|
||||
allowNull: false
|
||||
},
|
||||
sort: {
|
||||
// Se cambia el nombre del campo de 'order' a 'sort' porque 'order' es una palabra reservada SQL y da problemas al generar las consultas SQL.
|
||||
field: 'order', // <- Chapuza!! El nombre del campo en MySQL es una palabra reservada en SQL.
|
||||
type: DataTypes.INTEGER,
|
||||
defaultValue: 0,
|
||||
allowNull: false,
|
||||
|
||||
@ -7,13 +7,6 @@ module.exports = function (sequelize, DataTypes) {
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true,
|
||||
},
|
||||
/*userId: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: true,
|
||||
primaryKey: false,
|
||||
unique: false,
|
||||
foreignKey: true
|
||||
},*/
|
||||
date: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
@ -35,7 +28,6 @@ module.exports = function (sequelize, DataTypes) {
|
||||
tableName: 'post',
|
||||
freezeTableName: true,
|
||||
timestamps: true,
|
||||
updatedAt: false,
|
||||
});
|
||||
|
||||
Post.associate = function (models) {
|
||||
|
||||
@ -19,7 +19,7 @@ module.exports = function (Post) {
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
||||
fetchAll: (params) => {
|
||||
fetchAll: async (params) => {
|
||||
// Convert `params` object to filters compatible with Bookshelf.
|
||||
const filters = []; //strapi.utils.models.convertParams('post', params);
|
||||
// Select field to populate.
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
"dependencies": {
|
||||
"args-list": "^0.3.3",
|
||||
"async": "^2.6.2",
|
||||
"bcrypt": "^3.0.6",
|
||||
"body-parser": "^1.18.3",
|
||||
"buffer": "^5.2.1",
|
||||
"cheerio": "^1.0.0-rc.3",
|
||||
@ -35,6 +36,7 @@
|
||||
"helmet": "^3.16.0",
|
||||
"http": "^0.0.0",
|
||||
"http-status": "^1.3.2",
|
||||
"joi": "^14.3.1",
|
||||
"lodash": "^4.17.11",
|
||||
"method-override": "^3.0.0",
|
||||
"moment": "^2.24.0",
|
||||
@ -42,10 +44,12 @@
|
||||
"os": "^0.1.1",
|
||||
"passport": "^0.4.0",
|
||||
"passport-jwt": "^4.0.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"path": "^0.12.7",
|
||||
"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"
|
||||
}
|
||||
|
||||
9
private.key
Normal file
9
private.key
Normal file
@ -0,0 +1,9 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIBOQIBAAJBANHIOJ5cQCp97Je11BqiyOrPauRnc26mHFMEua3a35vdNxpkJnLi
|
||||
2/3JxhBRDGj0buvmQDO3Pc2BbfoV1lJRwF8CAwEAAQJAU7skziBoBA3K1yreA9uh
|
||||
cgdj1NJtwmZOu9wQ+JF52s2Ryrz+CS7R1NNNa39ujJgVdNv/DbS6RIVmaM1KN69j
|
||||
gQIhAPARxNtaVhB1d7EVVd9DZqxcjbGoDfnQXULDy9TO4Go/AiEA37PwsP48KZYC
|
||||
ybGDlSjG8+8utbb6q+Q/SdKk4AON4eECIC42vXachUTV2By2xrkb+H/lsUEp4Mbe
|
||||
XZWkq3BkAr9xAiA6iv2/ZBlcjLyYChO0cmJ2ri6cMZGycF47tJufYG6+IQIgPEx/
|
||||
Un8VU2psMTSmRDFp5f3l9Rx39BAghBf7CTqyWSk=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
4
public.key
Normal file
4
public.key
Normal file
@ -0,0 +1,4 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANHIOJ5cQCp97Je11BqiyOrPauRnc26m
|
||||
HFMEua3a35vdNxpkJnLi2/3JxhBRDGj0buvmQDO3Pc2BbfoV1lJRwF8CAwEAAQ==
|
||||
-----END PUBLIC KEY-----
|
||||
73
yarn.lock
73
yarn.lock
@ -203,6 +203,14 @@ base@^0.11.1:
|
||||
mixin-deep "^1.2.0"
|
||||
pascalcase "^0.1.1"
|
||||
|
||||
bcrypt@^3.0.6:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-3.0.6.tgz#f607846df62d27e60d5e795612c4f67d70206eb2"
|
||||
integrity sha512-taA5bCTfXe7FUjKroKky9EXpdhkVvhE5owfxfLYodbrAR1Ul3juLmIQmIQBK4L9a5BuUcE6cqmwT+Da20lF9tg==
|
||||
dependencies:
|
||||
nan "2.13.2"
|
||||
node-pre-gyp "0.12.0"
|
||||
|
||||
binary-extensions@^1.0.0:
|
||||
version "1.13.1"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
|
||||
@ -1414,6 +1422,11 @@ hide-powered-by@1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/hide-powered-by/-/hide-powered-by-1.0.0.tgz#4a85ad65881f62857fc70af7174a1184dccce32b"
|
||||
integrity sha1-SoWtZYgfYoV/xwr3F0oRhNzM4ys=
|
||||
|
||||
hoek@6.x.x:
|
||||
version "6.1.3"
|
||||
resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c"
|
||||
integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==
|
||||
|
||||
hpkp@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/hpkp/-/hpkp-2.0.0.tgz#10e142264e76215a5d30c44ec43de64dee6d1672"
|
||||
@ -1749,6 +1762,13 @@ isarray@1.0.0, isarray@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
isemail@3.x.x:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.2.0.tgz#59310a021931a9fb06bbb51e155ce0b3f236832c"
|
||||
integrity sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==
|
||||
dependencies:
|
||||
punycode "2.x.x"
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
@ -1766,6 +1786,15 @@ isobject@^3.0.0, isobject@^3.0.1:
|
||||
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
|
||||
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
|
||||
|
||||
joi@^14.3.1:
|
||||
version "14.3.1"
|
||||
resolved "https://registry.yarnpkg.com/joi/-/joi-14.3.1.tgz#164a262ec0b855466e0c35eea2a885ae8b6c703c"
|
||||
integrity sha512-LQDdM+pkOrpAn4Lp+neNIFV3axv1Vna3j38bisbQhETPMANYRbFJFUyOZcOClYvM/hppMhGWuKSFEK9vjrB+bQ==
|
||||
dependencies:
|
||||
hoek "6.x.x"
|
||||
isemail "3.x.x"
|
||||
topo "3.x.x"
|
||||
|
||||
js-tokens@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
|
||||
@ -2103,7 +2132,7 @@ mute-stream@0.0.7:
|
||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
|
||||
integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
|
||||
|
||||
nan@^2.9.2:
|
||||
nan@2.13.2, nan@^2.9.2:
|
||||
version "2.13.2"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7"
|
||||
integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==
|
||||
@ -2154,6 +2183,22 @@ node-fetch@^2.3.0:
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.3.0.tgz#1a1d940bbfb916a1d3e0219f037e89e71f8c5fa5"
|
||||
integrity sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==
|
||||
|
||||
node-pre-gyp@0.12.0:
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149"
|
||||
integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==
|
||||
dependencies:
|
||||
detect-libc "^1.0.2"
|
||||
mkdirp "^0.5.1"
|
||||
needle "^2.2.1"
|
||||
nopt "^4.0.1"
|
||||
npm-packlist "^1.1.6"
|
||||
npmlog "^4.0.2"
|
||||
rc "^1.2.7"
|
||||
rimraf "^2.6.1"
|
||||
semver "^5.3.0"
|
||||
tar "^4"
|
||||
|
||||
node-pre-gyp@^0.10.0:
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc"
|
||||
@ -2389,6 +2434,13 @@ passport-jwt@^4.0.0:
|
||||
jsonwebtoken "^8.2.0"
|
||||
passport-strategy "^1.0.0"
|
||||
|
||||
passport-local@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee"
|
||||
integrity sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=
|
||||
dependencies:
|
||||
passport-strategy "1.x.x"
|
||||
|
||||
passport-strategy@1.x.x, passport-strategy@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
|
||||
@ -2530,6 +2582,11 @@ pump@^3.0.0:
|
||||
end-of-stream "^1.1.0"
|
||||
once "^1.3.1"
|
||||
|
||||
punycode@2.x.x:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
qs@6.5.2:
|
||||
version "6.5.2"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||
@ -2771,6 +2828,13 @@ 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"
|
||||
@ -3127,6 +3191,13 @@ to-regex@^3.0.1, to-regex@^3.0.2:
|
||||
regex-not "^1.0.2"
|
||||
safe-regex "^1.1.0"
|
||||
|
||||
topo@3.x.x:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/topo/-/topo-3.0.3.tgz#d5a67fb2e69307ebeeb08402ec2a2a6f5f7ad95c"
|
||||
integrity sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==
|
||||
dependencies:
|
||||
hoek "6.x.x"
|
||||
|
||||
toposort-class@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user