Cannot read properties of undefined in Nodejs - mysql

I'm trying to do a sample register without JWT using MVC in nodejs, express and mysql so when I run my code and I have an error :
TypeError: Cannot read properties of undefined (reading 'firstName') at exports.register
here is my code :
AuthController
const AuthModel = require('../models/Auth')
// Create and Save a new User
exports.register = (req, res) => {
// Validate request
if (!req.body) {
res.status(400).send({
message: "Content can not be empty!"
});
}
// Create user
const user = new AuthModel({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: req.body.password
});
// Save user in the database
AuthModel.createUser(user, (err, data) => {
if (err)
res.status(500).send({
message:
err.message || "Some error occurred while registring."
});
else res.send(data);
});
};
AuthModel
const AuthModel = function(table){
this.firstName = table.firstName;
this.lastName = table.lastName;
this.email = table.email;
this.password = table.password;
}
AuthModel.createUser = ( newUser, result ) =>{
db.query("INSERT INTO users SET ?", newUser, (err, res) => {
if (err) {
console.log("error: ", err);
result(err, null);
return;
}
console.log("User are registed: ", { id: res.insertId, ...newUser });
result(null, { id: res.insertId, ...newUser });
});
};

It seems to me as if the req.body is undefined. I think you might need something like body-parser, which has been added into the core of Express starting with version 4.
Try adding this middleware to your entrypoint: app.use(express.json());
See more here: http://expressjs.com/en/api.html#express.json

In your exports.register, you .send() if the body is undefined. That doesn't mean the rest of the code won't be executed.
Replace:
res.status(400).send({
message: "Content can not be empty!"
});
by
return res.status(400).send({
message: "Content can not be empty!"
});

Related

Can't get status

I am making register/login page using nodejs but when it comes to the step it returns json when accessing the database as well as when creating a new database
here is my code
register.js
const bcrypt = require("bcryptjs");
const User = require("../model/user");
const register = async (req, res) => {
const {
username,
password: plainTextPassword,
password_confirmation: someOtherPlaintextPassword,
tel_or_email,
} = req.body;
if (!username || typeof username !== "string") {
return res.json({ status: "error", error: "Invalid username" });
}
if (!plainTextPassword || typeof someOtherPlaintextPassword !== "string") {
return res.json({ status: "error", error: "Invalid password" });
}
User.findOne({ Email: tel_or_email }, async (error, user) => {
if (error) throw error;
if (user) {
console.log(user);
return res.json({
status: "ok",
success: "email is already in use, please enter another email",
});
} else {
const password = await bcrypt.hash(plainTextPassword, 10);
const password_confirmation = await bcrypt.hash(
someOtherPlaintextPassword,
10
);
const user = new User({
Name: username,
Email: tel_or_email,
Password: password,
});
user.save((error, result) => {
if (error) throw error;
console.log(result);
});
return res.json({ status: "ok", success: "user successfully created" });
}
});
};
module.exports = register;
status work in the first return ( return res.json({ status: 'error', error: 'Invalid username'}) )and the second( return res.json({ status: 'error', error: 'Invalid password'}) ) , remaining is not

TypeError : res.status is not a function returning Login message and Token

i am getting this as error
TypeError : res.status is not a function
I do not know why, but i am getting this Error
My code is looking thus :
app.post('/api/v1/user/login', async function(req,res){
var email = req.body.email;
var password = req.body.password;
dbConn.query(`SELECT * FROM XXXXXXXXX_users WHERE email = ${dbConn.escape(req.body.email)};`,(err,result)=>{
if(err){
throw err;
return res.status(400).send({message: err,})
}
if(!result.length){
return res.status(400).send({message: 'Username and password incorrect!',})
}
bcrypt.compare(req.body.password,result[0]['password'],(err,res)=>{
if(err){
throw err;
return res.status(400).send({message: 'Username and password Incorrect!'});
}
if(result){
const token = jwt.sign({email: result[0].email,id:result[0].id},'the-super-strong-secrect',{ expiresIn: '1h' });
return res.status(200).send({message: 'OK', token}) // Error is here
}
return res.status(400).send({message: 'User and pass incorrect'})
})
})
})
I am trying to implement Login system backend API please I would like to know why this is not working as its supposed to. Kindly help. A bit new to this
Issue is in this line
bcrypt.compare(req.body.password,result[0]['password'],(err,res) //<-- Using res keyword here
See how you are using (err, res) for this callback. This interferes with
app.post('/api/v1/user/login', async function(req,res) //<-- Also using res keyword here
I would suggest you to use async/await for better cleanup.
app.post('/api/v1/user/login', async function(req, res) {
let email = req.body.email;
let password = req.body.password;
try {
const queryResult = await dbConn.query(`SELECT * FROM XXXXXXXXX_users WHERE email = ${dbConn.escape(req.body.email)};`)
if (!queryResult.length) {
return res.status(400).send({
message: 'Username and password incorrect!',
})
}
const compareResult = await bcrypt.compare(req.body.password, queryResult[0]['password'])
if (compareResult) {
const token = jwt.sign({
email: queryResult[0].email,
id: queryResult[0].id
}, 'the-super-strong-secrect', {
expiresIn: '1h'
});
return res.status(200).send({
message: 'OK',
token
})
}
return res.status(400).send({
message: 'User and pass incorrect'
})
}
catch (err) {
res.status(500).json({
err
});
}

NodeJS Json Return id only?

Here's the NodeJS code I'm using to create a customer in my MySql database;
const customer = new Customer({
email: req.body.email,
name: req.body.name,
active: req.body.active
});
Customer.create(customer, (err, data) => {
if (err)
res.status(500).send({
message:
err.message || "Some error occurred while creating the Customer."
});
else res.send(data);
});
};
Heres' the model;
const Customer = function(customer) {
this.email = customer.email;
this.name = customer.name;
this.active = customer.active;
};
Customer.create = (newCustomer, result) => {
sql.query("INSERT INTO customers SET ?", newCustomer, (err, res) => {
if (err) {
console.log("error: ", err);
result(err, null);
return;
}
console.log("created customer: ", { id: res.insertId, ...newCustomer });
result(null, { id: res.insertId, ...newCustomer });
});
};
And here's what I'm getting in return;
{"id":8,"email":"harry#gmail.com","name":"harry","active":1}
How can I get it to return just the id as a plain integer instead of the entire JSON string?
To get the specific property from the object. e.g. id, access it as data.id and id is an number which will be treated as status code in express so toString() is needed to convert it to string
The response should be:
res.send(data.id.toString())

NodeJS MySQL API cannot create Users from JSON

First of all, this is the repo website: https://github.com/TheFJS14/ck-app (you can see all code related to)
I am developing a NodeJS RESTful API with MySQL but, when I am trying to post a new User json, it report an error:
ReferenceError: User is not defined
at exports.create (C:\...\app\controllers\user.controller.js:10:18)
This is my file:
exports.create = (req, res) => {
if (!req.body) {
res.status(400).send({
message: "Content can not be empty!"
});
}
vvvvvvvvv
const user = new User({
nameUser: req.body.nameUser,
emailUser: req.body.emailUser
});
User.create(user, (err, data) => {
if (err)
res.status(500).send({
message:
err.message || "Some error occurred while creating the user."
});
else res.send(data);
});
};
I have other code references:
const UserRole = require("../models/userRole.model.js");
exports.create = (req, res) => {
if (!req.body) {
res.status(400).send({
message: "Content can not be empty!"
});
}
const userRole = new UserRole({
nameUserRole: req.body.nameUserRole,
descriptionUserRole: req.body.descriptionUserRole
});
UserRole.create(userRole, (err, data) => {
if (err)
res.status(500).send({
message:
err.message || "Some error occurred while creating the user role."
});
else res.send(data);
});
};
When I move my mouse over my User model, I get this message:
https://i.stack.imgur.com/1wjwf.png
But, when I see other codes, it looks different with my mouse over them: https://i.stack.imgur.com/bqsOR.png
I probably need to change my variable name, but I prefer not.
Thanks!
I have checked your code in github, in user.controller.js you have added this line:
const UserRole = require("../models/user.model.js");
you have to change it to
const User = require("../models/user.model.js");
That's why it throws and Error that User is not defined

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});
});