"error": "Cannot read property 'findOne' of undefined" - mysql

Hello everybody !!
Here I have a big problem, I would like to do a registration in back with Node.js sequelize and mySql.
I looked here and there but I did not find the answer to my problem so I came to ask you for help.
With mongoDb, it was easier but I admit that I am going in circles.
Here is my code:
// Importation :
// Bcrypt:
const bcrypt = require("bcrypt");
// Jsonwebtoken d'authentification:
const jwt = require("jsonwebtoken");
// Import du models user:
const models = require("../models/user")
//////////////////////////////////////////////////////////////////////////////////////////////
// Fonction/
// Incription:
exports.signup = (req, res) => {
const username = req.body.username;
const email = req.body.email;
const password = req.body.password;
const bio = req.body.bio;
const admin = req.body.admin;
console.log(req.body)
try {
models.User.findOne({
attributes: ['email'],
where: {
email: email
}
})
.then((userFound => {
if (!userFound) {
bcrypt.hash(password, 10, function (err, bcryptPassword) {
const newUser = models.User.create({
username : username,
email : email,
password : bcryptPassword,
bio : bio,
admin : false
})
.then(newUser => {
res.status(201).json({
'userId': newUser.id
})
})
.catch(err => {
res.status(500).json({
'error': 'Impossible d\'ajouter un utilisateur'
})
})
})
} else {
return res.status(409).json({
error: 'Ce compte existe déjà '
})
}
})
.catch((err) =>
res.status(500).json({
'err': err + 'Impossible de vérifier l\'utilisateur',
})
)
)
}catch (error) {
res.status(400).json({
error: error.message
});
}
}
And the model User:
'use strict'
const { db } = require('../config/connexion')
const { Sequelize, DataTypes } = require('sequelize')
const user = db.define('User', {
// Model attributes are defined here
username: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING,
bio: DataTypes.TEXT,
admin: DataTypes.BOOLEAN,
})
module.exports = user
and connexion.js:
// Connexion de sequelize à mysql:
const {
Sequelize
} = require('sequelize')
const db = new Sequelize(
process.env.NAMEDB,
process.env.USERDB,
process.env.PASSWORDDB, {
host: process.env.HOSTDB,
dialect: process.env.DIALECTDB,
pool: {
min: 0, // nombre minimum de connexion dans le pool
max: 5, // nombre maximum de connexion dans le pool
acquire: 30000, // durée maximale, en millisecondes, pendant laquelle ce pool essaiera d'obtenir la connexion avant de lancer une erreur
idle: 10000, // temps maximum, en millisecondes, pendant lequel une connexion peut être inactive avant d'être libérée
},
}
)
//////////////////////////////////////////////////////////////////////////////////////////////
// Etablit la connexion à mysql:
const dbConnect = async (db) => {
await db
.authenticate()
.then(() => {
db.sync()
console.log('Connecté à la base de données MySQL!')
})
.catch((err) => {
console.error('error: ' + err.message)
setTimeout(() => {
dbConnection(db)
}, 5000)
})
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Exportation:
module.exports = {
db,
dbConnect,
}
Certainly there is still a lot to do, but being a beginner I improve as I go.
Do not be angry with me if my English is not at the top, I admit that it is not my strong point.
Thanking you in advance for all the help provided.

You are directly setting the export object equal to the user object.
When you do this const models = require("../models/user"), models is equal to the user value directly.
You can directly use models.findOne. Read this

You are setting the user variable to be the export of the file
module.exports = user
You then import the user variable as models.
const models = require("../models/user")
this means that you do not need to access user as a property. Instead use:
models.findOne({ // Changed from models.User to models
attributes: ["email"],
where: {
email: email,
},
});
This should stop your current error, but you will keep on getting errors until you change all instances of models.User to models.
Your main file should end up looking like this:
// Importation :
// Bcrypt:
const bcrypt = require("bcrypt");
// Jsonwebtoken d'authentification:
const jwt = require("jsonwebtoken");
// Import du models user:
const models = require("../models/user");
//////////////////////////////////////////////////////////////////////////////////////////////
// Fonction/
// Incription:
exports.signup = (req, res) => {
const username = req.body.username;
const email = req.body.email;
const password = req.body.password;
const bio = req.body.bio;
const admin = req.body.admin;
console.log(req.body);
try {
models
.findOne({
attributes: ["email"],
where: {
email: email,
},
})
.then(
((userFound) => {
if (!userFound) {
bcrypt.hash(password, 10, function (err, bcryptPassword) {
const newUser = models
.create({
username: username,
email: email,
password: bcryptPassword,
bio: bio,
admin: false,
})
.then((newUser) => {
res.status(201).json({
userId: newUser.id,
});
})
.catch((err) => {
res.status(500).json({
error: "Impossible d'ajouter un utilisateur",
});
});
});
} else {
return res.status(409).json({
error: "Ce compte existe déjà ",
});
}
}).catch((err) =>
res.status(500).json({
err: err + "Impossible de vérifier l'utilisateur",
})
)
);
} catch (error) {
res.status(400).json({
error: error.message,
});
}
};

Check your "model" file to see if the "User" model exists there. Also check if you are using the 'module.exports'

You are exporting the User model directly, but calling it like it is in an object property named User. You can either access it directly, changing:
models.User.findOne
to:
models.findOne
and then you'd probably want to rename models to User.
Or change your export to:
module.exports = { User: user };

Related

Login function : Error [ERR_HTTP_HEADERS_SENT]

I'm working on a new project using React, Express and MySQL and my app keep crashing whenever I use the login route. The registration route works fine though.
My frontend:
function Signin() {
const [userNameLog, setNameLog] = useState('');
const [userPasswordLog, setPasswordLog] = useState('');
const login = () => {
Axios.post('http://localhost:3001/auth/signin', {
prenom: userNameLog,
password: userPasswordLog,
}).then((response) => {
console.log(response);
});
};
return (
<SignUpWrapper>
<SignUpTitle>Connectez-vous !</SignUpTitle>
<input
type='text'
placeholder='Prenom'
onChange={(e) => {
setNameLog(e.target.value);
}}
required
></input>
<input
type='password'
placeholder='Mot de passe'
onChange={(e) => {
setPasswordLog(e.target.value);
}}
required
></input>
<StyledButton onClick={login}>Se connecter</StyledButton>
</SignUpWrapper>
);
}
export default Signin;
My backend:
exports.signin = (req, res) => {
const username = req.body.prenom;
const password = req.body.password;
res.json({ message: 'Votre requête pour se connecter a bien été reçue !' })
db.query(
"SELECT * FROM users WHERE prenom = ? AND password = ?",
[username, password],
(err, result) => {
if(err){
//Permet d'envoyer une réponse au front en cas d'erreur
res.send({err: error});
} else {
if (result) {
res.send(result);
} else{
res.send({message : "Wrong combination of name and password"});
}
}
}
)
}
I've been googling it since 2hours but I still don't get where does my mistake come from
As the other users points on the comments, the error is caused by tried to send another "batch" of headers to the client.
The first line res.json(...) is sending the headers already.
You must call just one res.json per request.
Of course you can have one res.json per branch in your code, but be sure only one is called per request in the route.
Here is the error code of the official NodeJS Docs

how can i post data from reactjs form to mysql database

How can I send this data to database MySQL from a reactjs form? I'm a beginner in reactjs and I'm tired of trying.
In the back-end I use nodejs, express, and cors, so if u can tell me how because I have to finish this work.
The console returns GET Localhost 404 Not Found.
This is what I do but I don't know there is a better way to make it.
import React, { Component } from 'react'
import { Table,Button,
Modal,ModalHeader,
ModalBody,ModalFooter,
Label,Input,Form } from 'reactstrap';
export default class Db1 extends Component {
state = {
users: [],
newUserData: {
nom: '',
prenom: '',
adresse: '',
email: ''
},
newUserModal:false,
}
componentDidMount() {
this.getUsers();
}
getUsers = () => {
fetch('http://localhost:4000/users')
.then(response => response.json())
.then(response => this.setState({ users: response.data}))
.catch(err => console.error(err))
}
addUser = () => {
let { nom,prenom,adresse,email } = this.state.newUserData;
fetch(`http://localhost:4000/users/add?
nom=${nom}&prenom=${prenom}&adresse=${adresse}&email=${email}`,{
method: 'POST',
body: JSON.stringify({
nom: this.nom,
prenom: this.prenom,
adresse: this.adresse,
email: this.email
}),
headers: {"Content-Type": "application/json"}
})
.then(this.getUsers)
.catch(err => console.error(err))
this.setState({newUserModal:false});
console.log(this.newUserData) // return undefined
}
toggleNewUserModal = () => {
this.setState({
newUserModal: ! this.state.newUserModal
});
}
const express = require('express');
const cors = require('cors');
const mysql = require('mysql');
const bodyParser = require('body-parser')
const app = express();
// Connection Mysql
const connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'dbusers',
});
connection.connect(err => {
if (err) {
console.log("conection error");
return err;
}
});
// Connection Express Body-Parser Cors
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.get('/', (req, res) => {
res.send('Hello from the users server')
});
// Selectionner Tous Les Utilisateurs
app.get('/users', (req, res) => {
const selectQuery = 'SELECT * FROM userslist';
connection.query(selectQuery, (err, results) => {
if(err) {
res.send(err)
}
else {
res.json({data: results})
}
});
});
// Ajouter Un Nouveau Utilisateur
app.post('/users/add', (req, res) => {
let nom = req.body.nom;
let prenom = req.body.prenom;
let adresse = req.body.adresse;
let email = req.body.email;
let insertQuery ="INSERT INTO userslist SET ?"
const user={nom,adresse,prenom,email}
connection.query(insertQuery,user, (err, results) => {
if(err) {
console.log("insert error");
res.send(err)
}
else {
res.send({ error: false, data: results, message: 'user has been
updated successfully.' });
}
});
});
// Editer Un Nouveau Utilisateur
app.post('/users/update/:id', (req, res) => {
let id = req.params.id;
let nom = req.body.nom;
let prenom = req.body.prenom;
let adresse = req.body.adresse;
let email = req.body.email;
let updateQuery =`UPDATE userslist SET ? WHERE id=${id}`
const user={nom,adresse,prenom,email}
connection.query(updateQuery,user, (err, results) => {
if(err) {
console.log("insert error");
res.send(err)
}
else {
res.send({ error: false, data: results, message: 'user has been
updated successfully.' });
}
});
});
// Suprimer un Utilisateur
app.post("/users/delete/:id", (req, res) => {
let id = req.params.id;
let sql = 'DELETE FROM userslist WHERE id=?';
connection.query(sql, [id], (error, results, fields) => {
if (error)
console.error(error.message);
console.log("Deleted Row(s):", results.affectedRows);
res.json({error:false,data: results})
});
});
app.listen(4000, () => {
console.log('Users server worked on port 4000...')
});

passport authentication callback not calling passport middleware

I am trying to test if a GET request to a specific route is protected by using JSON Web Tokens with passport JwtStrategy; however, it seems like the passport.use middleware function I have in my server.js file is not executing. The console.log I have in there never shows up in my shell/terminal. My login route works, but not the profile route. I am using postman and I entered http://localhost:3000/profile for the GET method and in the Headers tab I chose Authorization for Key and for the Value I copied and pasted the long JSON web token string, but it keeps saying unauthorized. That is because my passport.use function is never getting executed.
//Server.js file
var JwtStrategy = require("passport-jwt").Strategy;
var ExtractJwt = require("passport-jwt").ExtractJwt;
var User = require("../models/user");
var config = require('./secret');
app.use(passport.initialize());
app.use(passport.session());
let options = {};
//pass token back and forth
options.jwtFromRequest = ExtractJwt.fromAuthHeader();
options.secretOrKey = config;
passport.use(new JwtStrategy(options, (jwt_payload, done) => {
*******************************************
//this console log doesn't show up in shell which makes be believe its never getting here
*******************************************
console.log("JWT PAYLOAD", jwt_payload)
User.getUserById(jwt_payload._id, (err, user) => {
if(err){
return done(err, false);
}
if(user){ //null for error
return done(null, user);
}else{
return done(null, false);
}
});
}));
//Routes file where the passport.authenticate callback is called
var passport = require('passport');
var jwt = require('jsonwebtoken');
var secret = require('../config/secret')
var User = require('../models/user');
router.post('/login', (req, res) => {
var username = req.body.username;
var password = req.body.password;
console.log("SECRET2", secret);
console.log("SECRET", secret.secret);
User.getUserByUsername(username, (err, user) => {
if(err){
throw err;
}
if(!user){
return res.json({ success: false, msg: "User not found"});
}
User.comparePassword(password, user.password, (err, isMatch) => {
if(err){
throw err;
}
if(isMatch){
var token = jwt.sign(user, secret.secret, {
expiresIn: 604800 //1 week in seconds, token expires and requires to log back in
});
console.log('TOKEN IN LOGIN ROUTE', token)
res.json({
//tokens are then stored in local storage or cookie
success: true,
token: 'JWT ' + token,
user: {
id: user._id,
name: user.name,
username: user.username,
email: user.email
}
});
}else{
return res.json({ success: false, msg: "Incorrect password"});
}
});
});
});
router.get('/profile', passport.authenticate('jwt', {session:false}), (req, res) => {
res.json({user: req.user});
});
//User model
var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
name: {
type: String,
trim: true,
required: "First Name is Required"
},
email: {
type: String,
required: true
},
username: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});
var User = mongoose.model("User", UserSchema);
module.exports = User;
//Alternate syntax for exporting Schema
// var User = module.exports = mongoose.model("User", UserSchema);
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
}
module.exports.getUserByUsername = function(username, callback){
var query = { username: username }
User.findOne(query, callback);
}
//Custom User model function that will take in the newUser object and hash the password.
module.exports.addUser = function(newUser, callback){
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if(err){
throw err
}
newUser.password = hash;
newUser.save(callback);
});
});
}
module.exports.comparePassword = function(password, hash, callback){
bcrypt.compare(password, hash, (err, isMatch) => {
if(err){
throw err
}
callback(null, isMatch);
});
}
Update:
I tried putting a space after 'JWT' in for the value for Authorization in the postman, but it still does not work and the console log is not showing. Is it because I am somehow not exporting or linking the passport.use I have defined in my server.js to my GET '/profile' route in my routes file?
Update 2: Added model and Login route
Maybe it is necessary to include more code to see your issue, but it seems like the strategy is not being exported correctly. When you create a new strategy, you can include an 'alias' to use it in the entry point:
passport.use('local-login', new JwtStrategy(options, (jwt_payload, done) => {
....
}
router.get('/profile', passport.authenticate('local-login', {session:false}), (req, res) => {
res.json({user: req.user});
});

how to update user table in node js

mycode is--
updateUser: function(req, res) {
var data = req.body;
var option = {
name: data.name,
mobile: data.mobile,
domain: data.domain,
}
userModel.update(option, function (error, rows) {
console.log('###############',error || rows);
if(!res){
//TODO: Error handling
console.log("ERROR", res);
res.status(200).send({"status_code": 0, 'message': 'Some error occured'});
return;
}
res.status(200).send({"status_code": 1, 'message': 'Succesfully Updated'});
})
},
the problem is updated all user coloumn.
in the code how to give id of the particular update data.
If you are not writing some very low level driver, I would recommend to use ORM like https://github.com/sequelize/sequelize. The very first example on their homepage shows:
var Sequelize = require('sequelize');
var sequelize = new Sequelize('database', 'username', 'password');
var User = sequelize.define('user', {
username: Sequelize.STRING,
birthday: Sequelize.DATE
});
sequelize.sync().then(function() {
return User.create({
username: 'janedoe',
birthday: new Date(1980, 6, 20)
});
}).then(function(jane) {
console.log(jane.get());
jane.update({
username: 'a very different username now'
}).then(function() {
console.log(jane.get());
})
});
You should use Bookshelf.js, good ORM, easy to use

Sequelize findAll is not a function

I'm making a project with Sequelize and I'm stucked in this step. The problem is that when I try to log in and the passport-local code is executed, when it reaches the User.findAll(...) it throws that findAll is not a function.
If I make console.log(User) it shows [function].
My structure:
/config/config.js
/config/passport.js
/models/index.js
/models/nuke_users.js (generated by sequelize-auto)
/index.js
config.js:
//Setting up the config
var Sequelize = require('sequelize');
var sequelize = new Sequelize('rocarenav2', 'root', '123456', {
host: "localhost",
port: 3306,
dialect: 'mysql'
});
module.exports = sequelize;
passport.js:
// config/passport.js
// load all the things we need
var LocalStrategy = require('passport-local').Strategy;
// load up the user model
var User = require('../models/nuke_users');
var crypto = require('crypto');
function hashPasswordForNuke(password) {
return md5password = crypto.createHash('md5').update(password).digest('hex');
}
// expose this function to our app using module.exports
module.exports = function(passport) {
// =========================================================================
// passport session setup ==================================================
// =========================================================================
// required for persistent login sessions
// passport needs ability to serialize and unserialize users out of session
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
User.findById(id, {})
.then(function (user) {
done(err, user);
})
.catch(function (error){
done(error);
});
});
// =========================================================================
// LOCAL LOGIN =============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'
passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) { // callback with email and password from our form
User.findAll({
where: {
'user_email': email
}
}).then(function (user) {
if(!user)
return done(null, false, req.flash('loginMessage', 'No user found.')); // req.flash is the way to set flashdata using connect-flash
// if the user is found but the password is wrong
if ((user.user_password).localeCompare(hashPasswordForNuke(password)) === -1)
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); // create the loginMessage and save it to session as flashdata
return done(null, user);
})
.catch(function (error){
done(error);
});
}));
};
models/index.js
'use strict';
var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var basename = path.basename(module.filename);
var config = require(__dirname + '/../config/config');
var db = {};
//Create a Sequelize connection to the database using the URL in config/config.js
var sequelize = config;
//Load all the models
fs
.readdirSync(__dirname)
.filter(function(file) {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(function(file) {
var model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(function(modelName) {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
//Export the db Object
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
/models/nuke_users.js
/* jshint indent: 2 */
module.exports = function(sequelize, DataTypes) {
return sequelize.define('nuke_users', {
user_id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
username: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: "",
references: {
model: 'reps_table',
key: 'PostName'
}
},
user_email: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: ""
},
user_avatar: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: ""
},
user_password: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: ""
}
}, {
tableName: 'nuke_users'
});
};
/index.js
...
var models = require('./models/');
...
So, what am I doing wrong?
The nuke_users module is exporting a function that, when called, returns the Model. Because you aren't calling this function, it is not returning the Model, and thus the function you are looking for does not exist.
To call this exported function you would need to pass in the sequelize instance and DataTypes, as so:
var User = require('../models/nuke_users')(sequelize, DataTypes);
In your case you are using a loader in the index.js file, and it is exporting the db object which contains the models keyed by their name.
var models = require('../models'); // loads index.js
var User = models.nuke_user; // the model keyed by its name
User.findOne(...); // search the model
Instead of returning the model, export it from NukeUser.js:
const NukeUser = sequelize.define('nuke_users', {
// ...
});
module.exports = NukeUser;
Then in index.js:
const NukeUser = require('../models/NukeUser');
NukeUser.findAll() //.then() ...
You need to check the models route in the collections, for example, in my case, I had read() as a method in my collections like that:
async read(id) {
try {
if(id) {
return await this.model.findOne({where: {id: id}});
} else {
return await this.model.findAll();
}
} catch (e) {
console.error(`Error in reading data with the id: ${id}`);
}
}
So, findAll() wouldn't work. Instead, I used read()