I have a model like this:
const User = db.Model.extend({
tableName: 'users',
hasSecurePassword: true
});
module.exports = User;
With this I can do things like
const User = require("../models/user");
User.fetchAll({columns:['id','email']}).then((data) => {
res.json(data);
}).catch(err => {
res.json(err);
});
What if I want to add costume functions to my model such as:
var connection = require('./dbconnection.js');
var User = db.Model.extend({
tableName: 'users',
hasSecurePassword: true
});
User.getUsers = (callback) => {
if (connection) {
const newLocal = "select * FROM users";
connection.query(newLocal, (err,rows,fields) => {
if (err) {
return res.sendStatus(500);
} else {
callback(null,rows);
}
});
}
};
module.exports = User;
And then do something like:
const User = require("../models/user");
User.getUsers((err,data) => {
res.status(200).json(data);
});
Is this posible? Or should I just conform with the bookshelf functions?
Right now the error I get is connection.query is not a function
And models/dbconnection.js is:
const mysql = require('mysql');
port = process.env.PORT || 3333;
if (port == 3333) {
var connection = mysql.createConnection({
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
insecureAuth: true
});
} else {
console.log("Error");
}
connection.connect();
module.exports.connection = connection;
Yes, you can add your custom functions to bookshelf models in two different ways.
Instance methods
For example, you want to return user's full name, your User model will look something like this
const User = db.Model.extend({
tableName: 'users',
hasSecurePassword: true,
//be careful here, if you use arrow function `this` context will change
//and your function won't work as expected
returnFullName: function() {
return this.get('firstname') + this.get('lastname');
}
});
module.exports = User;
then you will call this function like this
User.forge().where({id: SOME_ID}).fetch()
.then(function(user) {
var fullName = user.returnFullName();
});
Class methods
For example, you want to return user's email based on username, your User model will look something like this
const User = db.Model.extend({
tableName: 'users',
hasSecurePassword: true
}, {
getUserEmail: function(SOME_USERNAME) {
return User.forge().where({username: SOME_USERNAME}).fetch()
.then(function (user) {
if(user) {
return Promise.resolve(user.get('email'));
} else {
return Promise.resolve(null);
}
});
}
});
module.exports = User;
then you can call this function like
User.getUserEmail(SOME_USERNAME)
.then(function(email) {
console.log(email);
});
Related
In a hook I want to confirm whether a password has changed before executing encryption process.
Mongoose has a function "isModified" and I believe Sequelize's "changed" function servers the same purpose.
I cannot get the "changed" function to work. I am looking for an example of how it is used.
*******Snippet of code
{
hooks: {
beforeCreate: async (user) => {
if (changed([user.password]) === false) return next();
const salt = await bcrypt.genSalt(12);
user.password = await bcrypt.hash(user.password, salt);
user.passwordConfirmed = undefined;
},
},
instanceMethods: {
validPassword: function (password) {
return bcrypt.compare(password, this.password);
},
},
}
You must to use hook beforeUpdate with previous function. Try something like that:
let { Sequelize, DataTypes } = require('sequelize');
let sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'database.sqlite',
});
(async () => {
try {
await sequelize.authenticate();
console.log('connected');
let Person = sequelize.define('Person', { name: DataTypes.STRING, age: DataTypes.INTEGER });
Person.addHook('beforeUpdate', (person) => {
if (person.previous('name') != person.name) {
console.log('name changed', person.previous('name'), person.name);
}
});
await Person.sync({ force: true });
await Person.create({ name: 'John', age: 30 });
let [person] = await Person.findAll();
person.name = 'Paul';
await person.save();
} catch (error) {
console.error('Unable to connect to the database:', error);
}
})();
Not able to save the data in Google Datastore DB not getting any error, can somebody help me to find the fix
Console.log result as below
entityKey: Key { namespace: undefined, kind: 'User', path: [Getter] },
entityData:
{ firstname: 'Abcd',
lastname: 'Abcd',
email: 'abcd#gmail.com',
password: '123454',
createdOn: 'Abcd',
[Symbol(KEY)]: Key { namespace: undefined, kind: 'User', path: [Getter] } },
Ref - https://www.npmjs.com/package/gstore-node
const express = require('express');
const router = express.Router();
const { check, validationResult } = require('express-validator');
var User =require('../models/user');
//get register page
router.get('/register',function(req,res){
res.render('register')
});
//get login page
router.get('/login',function(req,res){
res.render('login')
});
router.post('/register', [
check('Name').isEmpty().withMessage('The Name is required'),
check('Email').isEmail().withMessage('Email is requried'),
//check('Password').isEmpty().withMessage('pass is requried'),
//check('Password','Password is Requried').isEmpty(),
// check('Password2','Password Not Match').equals('password2'),
], (req, res,next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.render('register',{
error:errors.mapped()
})
}else{
console.log()
const newUser = new User ({
firstname:req.body.name,
lastname:req.body.name,
email :req.body.Email,
password :req.body.Password,
createdOn:req.body.name
});
console.log("Data1",newUser)
const createUser = (req, res) => {
const entityData = User.sanitize(req.body);
const user = new User(entityData);
console.log("Data2",createUser)
user.save()
.then((entity) => {
res.json(entity.plain());
})
.catch((err) => {
// If there are any validation error on the schema
// they will be in this error object
res.status(400).json(err);
})
};
req.flash('success_msg','you are registered and can login now');
res.redirect('/users/login');
}
});
module.exports=router;
const { Gstore, instances } = require('gstore-node');
const { Datastore } = require('#google-cloud/datastore');
const gstore = new Gstore();
const datastore = new Datastore({
projectId: 'sinuous250616',
});
gstore.connect(datastore);
// Save the gstore instance
instances.set('unique-id', gstore);
const bcrypt = require('bcrypt');
// Retrieve the gstore instance
const ggstore = instances.get('unique-id');
const { Schema } = ggstore;
/**
* A custom validation function for an embedded entity
*/
const validateAccessList = (value, validator) => {
if (!Array.isArray(value)) {
return false;
}
return value.some((item) => {
const isValidIp = !validator.isEmpty(item.ip) && validator.isIP(item.ip, 4);
const isValidHostname = !validator.isEmpty(item.hostname);
return isValidHostname && isValidIp;
});
}
//Create the schema for the User Model
const userSchema = new Schema({
firstname: { type: String, required: true },
lastname: { type: String, optional: true },
email: { type: String, validate: 'isEmail', required: true },
password: { type: String, read: false, required: true },
createdOn: { type: String, default: gstore.defaultValues.NOW, write: false, read: false }
});
/**
* List entities query shortcut
*/
const listSettings = {
limit: 15,
order: { property: 'lastname' }
};
userSchema.queries('list', listSettings);
/**
* Pre "save" middleware
* Each time the entity is saved or updated, if there is a password passed, it will be hashed
*/
function hashPassword() {
// scope *this* is the entity instance
const _this = this;
const password = this.password;
if (!password) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
bcrypt.genSalt(5, function onSalt(err, salt) {
if (err) {
return reject(err);
};
bcrypt.hash(password, salt, null, function onHash(err, hash) {
if (err) {
// reject will *not* save the entity
return reject(err);
};
_this.password = hash;
// resolve to go to next middleware or save method
return resolve();
});
});
});
// add the "pre" middleware to the save method
userSchema.pre('save', hashPassword);
/**
* Export the User Model
* It will generate "User" entity kind in the Datastore
*/
module.exports = gstore.model('User', userSchema);
*I think there is a problem with User model **
You should have a User model like this in /models/user.js (put models at the root of your application) to define User:
const { instances } = require('gstore-node');
const bscrypt = require('bcrypt-nodejs');
// Retrieve the gstore instance
const gstore = instances.get('unique-id');
const { Schema } = gstore;
var usersSchema = new Schema({
firstname:{type:String},
lastname:{type:String},
email:{type:String},
password :{type:String},
createdOn: Date
})
var User = gstore.model('User', usersSchema);
module.exports = User;
And you forgot to use to save with save()
var newUser = new User ({
firstname:req.body.name,
lastname:req.body.name,
email :req.body.Email,
password :req.body.Password,
createdOn: new Date() // there is a problem here.... use new Date()
});
newUser.save(); //<======= it is abscent so it won't save
I'm having problem with bcrypt-nodejs' compare function.
The compare function is returning the false value even the password is the right one.
I've tried everything I could and I don't know the what is wrong with my code.
My Folder Structure
src
-config
-config.js
-controller
-AuthenticationController.js
-models
-index.js
-User.js
-policies
-AuthenticationControllerPolicy.js
app.js
routes.js
package.json
I think the problem is with the User.js in models folder.
User.js
const Promise = require('bluebird')
const bcrypt = Promise.promisifyAll(require('bcrypt-nodejs'))
function hashPassword (user, options) {
const SALT_FACTOR = 8
if (!user.changed('password')) {
return
}
return bcrypt
.genSaltAsync(SALT_FACTOR)
.then(salt => bcrypt.hashAsync(user.password, salt, null))
.then(hash => {
user.setDataValue('password', hash)
})
}
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
}, {
hooks: {
beforeCreate: hashPassword,
beforeUpdate: hashPassword,
beforeSave: hashPassword
}
})
User.prototype.comparePassword = function (password) {
return bcrypt.compareAsync(password, this.password)
}
User.associate = function (models) {
}
return User
}
AuthenticationController.js
const {User} = require('../models')
const jwt = require('jsonwebtoken')
const config = require('../config/config')
function jwtSignUser (user) {
const ONE_WEEK = 60 * 60 * 24 * 7
return jwt.sign(user, config.authentication.jwtSecret, {
expiresIn: ONE_WEEK
})
}
module.exports = {
async register (req, res) {
try {
const user = await User.create(req.body)
const userJson = user.toJSON()
res.send({
user: userJson
})
} catch (err) {
res.status(400).send({
error: 'This email account is already in use.'
})
}
},
async login (req, res) {
try {
const {email, password} = req.body
const user = await User.findOne({
where: {
email: email
}
})
console.log('user BEFORE', user)
if (!user) {
console.log('!user')
return res.status(403).send({
error: 'The login information was incorrect'
})
}
console.log('user AFTER', user)
const isPasswordValid = await user.comparePassword(password)
console.log('isPasswordValid BEFORE : ', isPasswordValid)
if (!isPasswordValid) {
console.log('isPasswordValid AFTER : ', isPasswordValid)
return res.status(403).send({
error: 'The login information was incorrect'
})
}
const userJson = user.toJSON()
res.send({
user: userJson,
token: jwtSignUser(userJson)
})
} catch (err) {
res.status(500).send({
error: 'An error has occured trying to log in'
})
}
}
}
route.js
const AuthenticationController = require('./controller/AuthenticationController')
const AuthenticationControllerPolicy = require('./policies/AuthenticationControllerPolicy')
module.exports = (app) => {
app.post('/register',
AuthenticationControllerPolicy.register,
AuthenticationController.register)
app.post('/login',
AuthenticationController.login)
}
You can also check the repo if you want.
GitHubRepo
The usage of bcrypt-nodejs appears to be correct. I would verify that both the password coming in and the hash in the database are what you expect them to be (particularly inside the comparePassword function) to rule out if it's a data issue or not.
I am trying to create a very simple forum using nodejs, mongo and mongoose.
So far I created a mongoose Schema for users:
var mongoose = require('mongoose');
var user = {
_id: { type: String, required: true },
password: { type: String, required: true }
};
var schema = new mongoose.Schema(user);
module.exports = schema;
module.exports.user = user;
Then created the Model:
var mongoose = require('mongoose');
var url = 'mongodb://localhost:27017/forum'
mongoose.connect(url);
mongoose.connection.on('connected', function() {
console.log('Stablished connection on ' + url);
});
mongoose.connection.on('error', function(error) {
console.log('Something wrong happened: ' + error);
});
mongoose.connection.on('disconnected', function() {
console.log('connection closed');
});
var User = mongoose.model('User', require('./user'));
module.exports.User = User;
Finally, there is the file that contains all the models (currently just one) and its methods:
var models = require('./models');
var User = models.User
exports.addUser = function(user, password) {
var data = new User({ _id: user, password: password });
data.save(function(error) {
console.log('inside');
if(error) { console.log('ERROR: ' + error); return true; }
else { console.log('User ' + user + ' added'); return false; }
});
};
exports.getUserList = function() {
User.find().lean().exec(function(error, users) {
if(error) { console.log('ERROR: ' + error); }
else { return JSON.stringify(users); }
});
}
The problem comes when I execute this file:
var mongodb = require('mongodb');
var mongoose = require('mongoose');
var dm = require('./dm');
var users = { 'user1': '1234',
'user2': '1234',
'user3': '1234',
'user4': '1234'
};
console.log('Initial user list');
dm.getUserList();
for(var user in users) {
dm.addUser(user, users[user]);
}
console.log('Final user list');
dm.getUserList();
process.exit(0);
It seems that it does nothing and does not save the users. Output:
Initial user list
Final user list
Thanks!
Remove the process.exit() part, or wrap it in a timeout. You don't give your database enough time to execute. E.g. put this at the end instead:
...
setTimeout(() => process.exit(0), 2000);
Edit: or add promises, like somebody commented:
exports.addUser = function(user, password) {
var data = new User({ _id: user, password: password });
return data.save()
.then(() => console.log('User ' + user + ' added'))
.catch(function(error) {
console.log('ERROR: ' + error);
else { return false; }
});
};
Then in your main loop:
const promises = users.map(userData => addUser(userData));
Promise.all(promises)
.then(() => {
console.log('All users added.');
// .. do another async operation here, or process.exit();
});
I have the following code :
var ORM = require('../helpers/mysql_orm');
var log = require('../helpers/logger');
function UserModel() {
this.User = ORM.define('User', {
}, {
tableName: 'User',
timestamps: false,
});
}
UserModel.prototype.findOneByCredinitals = function (creditinals) {
this.User.findOne({
attributes:['username','id'],
where:
{
username:creditinals.principal,
password:creditinals.creditinal}
})
.then(function(user) {
console.log("inside then function"+user);
return user;
})
// console.log(result);
},
UserModel.prototype.findAllByLimit = function(req,res) {
}
module.exports= new UserModel;
//app.js
var result = User.findOneByCredinitals({principal: 'admin',creditinal:'danieladenew'});
console.log("returned "+result);
This the result from app.js
------------------------------------------------
returned undefined
inside then function User Sequelize Instance i.e Useriffound and displayed.
How do i return user object from then to app.js code please ?
You need to return the promise in order for the data to appear.
UserModel.prototype.findOneByCredential = function (credentials) {
return this.User.findOne({
attributes: ['username', 'id'],
where: {
username: credential.principal,
password: credential.credential
}
}).then(function(user) {
console.log("inside then function"+user);
return user;
}
});
},
Also, it might be a good idea to add a catch block. If the query fails, you will have no idea otherwise