Here is my code--------
const express = require("express");
const router = express.Router();
const gravatar = require("gravatar");
// Load User model
const User = require("../../models/User");
// #route GET api/users/test
// #desc Tests users route
// #access Public
router.get("/test", (req, res) => res.json({ msg: "Users Works" }));
// #route GET api/users/register
// #desc Register user
// #access Public
router.post("/register", (req, res) => {
User.findOne({ email: req.body.email }).then(user => {
if (user) {
return res.status(400).json({ email: "email already exists" });
} else {
const avatar = gravatar.url(req.body.email, {
s: "200", // Size
r: "pg", // Rating
d: "mm" // Default
});
const newUser = new User({
name: req.body.name,
email: req.body.email,
avatar,
password: req.body.password
});
}
});
});
module.exports = router;
When I attempt a postman test for the .post(/register ... ) route it stalls loading for some minutes before giving me the error of --
"Could not get any response
There was an error connecting to http://localhost:5000/api/users/register.
Why this might have happened:
The server couldn't send a response:
Ensure that the backend is working properly
Self-signed SSL certificates are being blocked:
Fix this by turning off 'SSL certificate verification' in Settings > General
Proxy configured incorrectly
Ensure that proxy is configured correctly in Settings > Proxy
Request timeout:
Change request timeout in Settings > General"
Tweaking the suggested options did nothing and I'm lead to think neither of these things are the cause, as I am able to successfully process the .get(/test) route.
**point of note, I add the key:values in the body of the postman request for name, email and password. The avatar is generated from the email.
This is the route I use(post) --- http://localhost:5000/api/users/register
and for reference this is the working route (get)
--- http://localhost:5000/api/users/test
Any help would be great!
There is no return statement in the else block. Try as following... It should work
// #route GET api/users/register
// #desc Register user
// #access Public
router.post("/register", (req, res) => {
User.findOne({ email: req.body.email }).then(user => {
if (user) {
return res.status(400).json({ email: "email already exists" });
} else {
const avatar = gravatar.url(req.body.email, {
s: "200", // Size
r: "pg", // Rating
d: "mm" // Default
});
return res.status(200).json(new User({
name: req.body.name,
email: req.body.email,
avatar,
password: req.body.password
}));
}
});
});
I guess you are trying to register a user and save it mongoDB and return the response.
What you are doing wrong is you are not responding the data back to user. Also you are not saving anything in the whole API call..
Here's how you can do it.
router.post("/register", (req, res, next) => {
User.findOne({ email: req.body.email }).then(user => {
if (user) {
return res.status(400).json({ email: "email already exists" });
} else {
const avatar = gravatar.url(req.body.email, {
s: "200", // Size
r: "pg", // Rating
d: "mm" // Default
});
const newUser = new User({
name: req.body.name,
email: req.body.email,
avatar,
password: req.body.password
});
newUser.save()
.then(user => {
res.status(201).json(user); // 201 is HTTP Code for "Created"
});
.catch(next); // we usually handle error in a common middleware, which is why, I am calling "next" here with error as 1st argument.
}
});
});
Related
im completing a fullstack project using react and node
when trying to register a user or a product i keep on getting error 500 in the browser and this error in my visual studio terminal:
Error: Illegal arguments: string, object
here's my create user function:
const createUser = asyncHandler(async (req, res) => {
const { name, email, password } = req.body;
const userExist = await User.findOne({ email });
if (userExist) {
res.status(400);
throw new Error("User already exists");
}
const user = await User.create({
name,
email,
password,
});
if (user) {
res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
isAdmin: user.isAdmin,
token: generateToken(user._id),
});
} else {
res.status(400);
throw new Error("Invalid user data");
}
});
what could cause an error 500?
trying to register a new user to the db
To resolve this issue you can follow some steps:
Try to console the data from the request parameters i.e name, email, password and manipulate your request parameters
Else use:- const email=req.body.email; such syntax for all the request params
Again try to console the req params, hope this time these params will be there.
Use this modification:
const createUser = asyncHandler(async (req, res) => {
const name = req.body.name;
const email = req.body.email;
const password = req.body.password;
const userExist = await User.findOne({ email });
if (userExist) {
res.status(400);
throw new Error("User already exists");
}
const user = await User.create({
name,
email,
password,
});
if (user) {
res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
isAdmin: user.isAdmin,
token: generateToken(user._id),
});
} else {
res.status(400);
throw new Error("Invalid user data");
}
});
if your req params are not accessing the body params from the form, try using body-parser or multer for the same.
Note: Try using console.log() to know the line of concern of your code.
I am writing code for basic backend authentication, specifically registering user. I am testing my route by REST Client in VS code.
But the problem is that my route is not getting access to res.body ( the JSON data I am sending).
Here is my route
router.post("/", async (req, res) => {
console.log(req.body);
const { name, email, password } = req.body;
try {
// check if user exists
let user = await User.findOne({ email });
if (user) {
return res.status(400).json({ errors: [{ msg: "User already Exists" }] });
}
const avatar = gravatar.url(email, { s: "200", r: "pg", d: "mm" });
user = new User({
name,
email,
avatar,
password,
});
//encrypt password
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
await user.save();
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
This is the error and empty req.body
*Server started
Database connected Successfully!
{}
Illegal arguments: undefined, string
*
And this is JSON data i am sending
What seems to be the problem here?
POST http://localhost:5000/api/register
Content-Type: application/json
{
"name": "hello",
"email":"hello#gmail.com",
"password": "0987654321"
}
How will I set a {protected} as the first argument in my router.route('/').get(protect, getProducts)
I am trying to protect my '/' route same as the
router.route('/profile').get(protect, getUserProfile)
Here is my authMiddleware.js file
productController.js file
productRoutes.js file
These are my users files in which I use the same middleware:
This is my userRoutes
This is my userRoutes.js below:
import asyncHandler from 'express-async-handler'
import generateToken from '../utils/generateToken.js'
import User from '../models/userModel.js'
// #desc Auth user & get token
// #route POST /api/users/login
// #access Public
const authUser = asyncHandler(async (req, res) => {
const { email, password } = req.body
const user = await User.findOne({ email })
if (user && (await user.matchPassword(password))) {
res.json({
_id: user._id,
name: user.name,
email: user.email,
isAdmin: user.isAdmin,
token: generateToken(user._id),
})
} else {
res.status(401)
throw new Error('Invalid email or password')
}
})
// #desc Register a new user
// #route POST /api/users
// #access Public
const registerUser = asyncHandler(async (req, res) => {
const { name, email, password } = req.body
const userExist = await User.findOne({ email })
if (userExist) {
res.status(400)
throw new Error('User already exists')
}
const user = await User.create({
name,
email,
password,
})
if (user) {
res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
isAdmin: user.isAdmin,
token: generateToken(user._id),
})
} else {
res.status(400)
throw new Error('Invalid user data')
}
})
// #desc Get user profile
// #route GET /api/users/profile
// #access Private
const getUserProfile = asyncHandler(async (req, res) => {
const user = await User.findById(req.user._id)
if (user) {
res.json({
_id: user._id,
name: user.name,
email: user.email,
isAdmin: user.isAdmin,
})
} else {
res.status(404)
throw new Error('User not found')
}
})
export { authUser, registerUser, getUserProfile }
I think you could do something like :
router.get('/', [protect], getProducts);
Calling your middleware and simplifying syntax :)
In my Node.js/MERN app, I get error 250 2.0.0 OK 1590267554 o18sm275551eje.40 - gsmtp & something went wrong when I register my user for authentication and receive an email with EMPTY body. I am using the code from https://blog.bitsrc.io/email-confirmation-with-react-257e5d9de725
I can see user is added to mongodb database with confirmed set to false. Why am I not getting the complete email with confirmation?
Please find my attached code for my MERN application. I would really appreciate a reply! Thank you!
Register
Register route in users which takes you to login and on React side OnSubmit starts chain of sending and confirming email.
router.post("/register", type, function (req, res, next) {
// var tmp_path = req.file.path;
if(!req.file){
console.log("File missing");
}
/** The original name of the uploaded file
stored in the variable "originalname". **/
// var target_path = 'uploads/' + req.file.originalname;
// /** A better way to copy the uploaded file. **/
// var src = fs.createReadStream(tmp_path);
// var dest = fs.createWriteStream(target_path);
// src.pipe(dest);
// fs.unlink(tmp_path);
// src.on('end', function() { res.render('complete'); });
// src.on('error', function(err) { res.render('error'); });
// Form validation
const { errors, isValid } = validateRegisterInput(req.body);
const url = req.protocol + '://' + req.get('host')
// Check validation
if (!isValid) {
return res.status(400).json(errors);
}
//Checks email against registered emails in database
registeredemails.findOne({ email: req.body.email}).select("email").lean().then(result => {
if (!result) {
return res.status(400).json({email: "Email not provided"});
}
});
User.findOne({ email: req.body.email }).then(user =>
{
if (user) {return res.status(400).json({ email: "Email already exists" })
}
else if(!user){
const newUser = new User({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: req.body.password,
fileimg: url + '/public/' + req.file.filename
});
// // Hash password before saving in database
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser
.save()
.then(newUser =>
sendEmail(newUser.email),
templates.confirm(newUser._id)
)
.then(() => res.json({ msg: msgs.confirm }))
.catch(err => console.log(err))
}
)}
)}
else if (user && !user.confirmed) {
sendEmail(user.email, templates.confirm(user._id))
.then(() => res.json({ msg: msgs.resend })).catch(err => console.log(err))
}
// The user has already confirmed this email address
else {
res.json({ msg: msgs.alreadyConfirmed })
}
}).catch(err => console.log(err))
sendemail as used in the MEDIUM articles
const nodemailer = require('nodemailer');
const { CLIENT_ORIGIN } = require('../../config')
// const mg = require('nodemailer-mailgun-transport');
// The credentials for the email account you want to send mail from.
const credentials = {
secure: true,
service: 'Gmail',
auth: {
user: process.env.MAIL_USER,
pass: process.env.MAIL_PASS
// These environment variables will be pulled from the .env file
// apiKey: 'b61286bf9e28b149fac32220f0c7349f-e5e67e3e-00a38515',
// domain: 'sandbox0b8a7f0ebcc74c0d8161304f24909bd2.mailgun.org'
}
}
// Getting Nodemailer all setup with the credentials for when the 'sendEmail()'
// function is called.
const transporter = nodemailer.createTransport(credentials)
// exporting an 'async' function here allows 'await' to be used
// as the return value of this function.
module.exports = async (to, content) => {
// The from and to addresses for the email that is about to be sent.
const contacts = {
from: process.env.MAIL_USER,
to // An array if you have multiple recipients.
// subject: 'React Confirm Email',
// html: `
// <a href='${CLIENT_ORIGIN}/confirm/${id}'>
// click to confirm email
// </a>
// `,
// text: `Copy and paste this link: ${CLIENT_ORIGIN}/confirm/${id}`
}
// Combining the content and contacts into a single object that can
// be passed to Nodemailer.
const email = Object.assign({}, content, contacts)
// This file is imported into the controller as 'sendEmail'. Because
// 'transporter.sendMail()' below returns a promise we can write code like this
// in the contoller when we are using the sendEmail() function.
//
// sendEmail()
// .then(() => doSomethingElse())
//
// If you are running into errors getting Nodemailer working, wrap the following
// line in a try/catch. Most likely is not loading the credentials properly in
// the .env file or failing to allow unsafe apps in your gmail settings.
await transporter.sendMail(email, function(error, info){
if(error)
{
return console.log(error);
}
else
{
return console.log(info.response);
}
})
}
templates.confirm as used in Medium article
onst { CLIENT_ORIGIN } = require('../../config')
// This file is exporting an Object with a single key/value pair.
// However, because this is not a part of the logic of the application
// it makes sense to abstract it to another file. Plus, it is now easily
// extensible if the application needs to send different email templates
// (eg. unsubscribe) in the future.
module.exports = {
confirm: id => ({
subject: 'React Confirm Email',
html: `
<a href='${CLIENT_ORIGIN}/confirm/${id}'>
click to confirm email
</a>
`,
text: `Copy and paste this link: ${CLIENT_ORIGIN}/confirm/${id}`
})
}
I am trying to make get request to my protected routes using bearer token and it returns unautorized, even after sending token through header.
I am using bearer token on nodejs, expressjs app using mlab remote database
I registered new user, then I logged with that email and it sent me back a token(as expected).
When I sent this token through header of other route without login it returns Unautorized.
my steps are
1) registered with new email
2) login request successful
3) failed get request to route localhost:5000/api/users/current, and returns Unautorized.
user.js file has
// users.js for authentication and authorization
const express = require("express");
const router = express.Router();
const gravatar = require("gravatar");
const bcrypt = require("bcryptjs");
const keys = require("../../config/keys");
const jwt = require("jsonwebtoken");
const passport = require("passport");
// Load User Model to check existing email is used for registration or not?
const User = require("../../models/User");
// #route GET request to api/users/test
// #description Tests users route
// #access Public, without login
router.get("/test", (req, res) => res.json({ msg: "Users Works" }));
// #route GET request to api/users/register
// #description new registration of user.
// #access Public, without login first register
router.post("/register", (req, res) => {
User.findOne({ email: req.body.email }).then(user => {
if (user) {
return res.status(400).json({ email: "Email value exists already." });
} else {
console.log("no user found of this email in DB");
const avatar = gravatar.url(req.body.email, {
s: "200", //Size of gravatar in pixels
r: "pg", //rating,
d: "mm" //default value= 'mm'
});
// create user
const newUser = new User({
name: req.body.name,
email: req.body.email,
avatar,
password: req.body.password
});
// gensalt(noOfSalts_of_Iterations,(err,salt_result)=>{})
bcrypt.genSalt(10, (err, salt) => {
// hash(plaintext,salt,callback(err,resultant ciphertext))
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) {
console.log("error in bcrypt.hash()");
throw err;
}
//assign salted hash to password
newUser.password = hash;
// Save new password in datebase, overriding plaintext;
newUser
.save()
.then(user => res.json(user)) // if yes,then send it as argument in brackets.
.catch(err =>
console.log("Error occured in saving hash password in DB\n")
);
});
});
}
});
});
// #route GET request to api/users/login
// #description Login/signing-in registered user. return JWT token
// #access Public
router.post("/login", (req, res) => {
const email = req.body.email;
const password = req.body.password;
// find user to match it's password
User.findOne({ email: req.body.email }).then(user => {
//check if no user
if (!user) {
return res.status(404).json({ email: "User's email found." });
}
// else if do this..
// if user's email-id is found then match it's password-hash with local-database
bcrypt.compare(password, user.password).then(isMatch => {
if (isMatch) {
// user pswd matched => then return JWT token back for authentication
// res.json({ msg: "Success" });
const payload = { it: user.id, name: user.name, avatar: user.avatar };
// created JWT token
// now sign token
// jwt.sign(payload, secretKey, expire-time, callback );
// jwt.sign
jwt.sign(
payload,
keys.secretOrKey,
{ expiresIn: 3600 },
(err, token) => {
res.json({
success: true,
token: "bearer " + token
});
}
);
} else {
// pswd doesn't matched
return res.status(400).json({ password: "Password didn't match" });
}
});
});
});
// #route GET request to api/users/current - current user with token
// #description Return current user
// #access Private, can't go without login
router.get(
"/current",
passport.authenticate("jwt", { session: false }),
(req, res) => {
res.json({ msg: "Success" });
}
);
module.exports = router;
data is stored succesfully at remote db mlab, but I can't figureout what's problem.
my Github repo of this project is this
Please Look at the Line of your code Users.js Line 88 the payload id is stored in 'it'
const payload = { it: user.id, name: user.name, avatar: user.avatar };
But in your passport.js
User.findById(jwt_payload.id)
you are extracting it by id so if you use here jwt_payload.it the you will get message success