Post Method value is undefined - javascript

The return of email2 is undefined. The method userRepository.getAllConfirmedEmails(...) delivers the right value, but in the post methode the return is undefinded.
app.post('/login', async (req, res) => {
const { email } = req.body;
// get safetyAttribues
const safetyAttributes = await safetyAttributesClass.getSafetyAttributes(email);
// if both are true, try to send login challenge
if (safetyAttributes.isAccepted && safetyAttributes.isConfirmed) {
if (safetyAttributes.isAdmin) {
const email2;
const token = await safetyAttributesClass.generateAdminToken(email).then(async (token) => {
email2 = await userRepository.getAllConfirmedEmails(email, token).then(async (email2) => {
console.log("HIER STEHT DIE ZWEITE EMAIL-->" , email2);
})
});
}
const user = userRepository.findByEmail(email);
console.log('HIER ISTHEH <USJR', user);
if (!user) {
return res.sendStatus(400);
}
const assertionChallenge = generateLoginChallenge(user.key);
userRepository.updateUserChallenge(user, assertionChallenge.challenge);
res.send(assertionChallenge);
}
// if not, send attributes to frontend to handle client-side
else {
res.send({ isAcceptet: safetyAttributes.isAccepted, isConfiremd: safetyAttributes.isConfirmed })
}
});

You're oddly mixing async/await with #then, probably sticking with async/await will help:
const token = await safetyAttributesClass.generateAdminToken(email);
const email2 = await userRepository.getAllConfirmedEmails(email, token);
console.log("HIER STEHT DIE ZWEITE EMAIL-->", email2);

You should return email2 in your getAllConfirmedEmails callback. Like so
app.post('/login', async (req, res) => {
const { email } = req.body;
// get safetyAttribues
const safetyAttributes = await safetyAttributesClass.getSafetyAttributes(email);
// if both are true, try to send login challenge
if (safetyAttributes.isAccepted && safetyAttributes.isConfirmed) {
if (safetyAttributes.isAdmin) {
const email2;
const token = await safetyAttributesClass.generateAdminToken(email).then(async (token) => {
email2 = await userRepository.getAllConfirmedEmails(email, token)
});
}
const user = userRepository.findByEmail(email);
console.log('HIER ISTHEH <USJR', user);
if (!user) {
return res.sendStatus(400);
}
const assertionChallenge = generateLoginChallenge(user.key);
userRepository.updateUserChallenge(user, assertionChallenge.challenge);
res.send(assertionChallenge);
}
// if not, send attributes to frontend to handle client-side
else {
res.send({ isAcceptet: safetyAttributes.isAccepted, isConfiremd: safetyAttributes.isConfirmed })
}
})
;

Related

Getting erros using passport-google-oauth20 InternalOAuthError: Failed to fetch user profile and Cannot set headers after they are sent to the client

I'm using passport strategies for different socialMedia logins and getting the following two errors
InternalOAuthError: Failed to fetch user profile
Cannot set headers after they are sent to the client
I have doubt there somewhere I have returned a callback or response so getting 2nd error but for 1st don't know reasons scope seems to be correct!
strategy code
passport.use(new GoogleStrategy({
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_SECRET_KEY,
callbackURL: GOOGLE_CALLBACK_URL
}, async (acessToken, refreshToken, profile, done) => {
await User.findOne({ email: profile._json.email }, async (err, user) => {
if (err) {
console.log("passport.config --> err", err);
done(err, null);
} else if (user) {
if (user.socialType !== "GOOGLE" || user.socialType === null)
done(`LOGIN_CREDENTIALS_WITH_${(user.socialType || "PASSWORD").toUpperCase()}`, false);
else {
done(null, user);
}
} else {
// console.log(profile);
const user = {
email: profile._json.email,
socialId: profile.id,
socialType: "GOOGLE",
firstName: profile.name.givenName,
lastName: profile.name.familyName,
isActive: profile._json.email_verified,
isVerified: profile._json.email_verified,
socialImageUrl: profile._json.picture,
userType: "CUSTOMER"
};
const newUser = new User({ ...user });
const newUserData = await newUser.save();
done(null, newUserData);
}
});
}));
route code:
router.get('/auth/:socialType', customerCtrl.socialTypeLogin);
router.get('/auth/:socialType/callback', customerCtrl.socialTypeLoginCallback);
controller code:
const socialTypeLogin = async (req, res) => {
await customerService.socialTypeLogin(req, res);
};
const socialTypeLoginCallback = async (req,res) => {
await customerService.socialTypeLoginCallback(req,res);
};
service code:
const socialTypeLogin = async (req, res) => {
try {
const socialType = (req.params.socialType || '').toLowerCase();
const GOOGLE_SCOPE = ['email', 'profile'];
const FACEBOOK_SCOPE = ['email'];
let scope = [];
if (socialType === 'google') {
scope = GOOGLE_SCOPE;
} else if (socialType === 'facebook') {
scope = FACEBOOK_SCOPE;
}
let oauthOptions = { scope: scope};
const { returnUrl } = req.query;
if(returnUrl && returnUrl.trim().length !== 0) {
oauthOptions['state'] =JSON.stringify({ returnUrl: returnUrl });
}
passport.authenticate(socialType, oauthOptions)(req, res);
}
catch (error) {
}
}
/**
* #param {string} socialType
*/
const socialTypeLoginCallback = async (req, res) => {
const socialType = (req.params.socialType || '').toLowerCase();
// return new Promise((resolve, reject) => {
try {
passport.authenticate(socialType, async (err, user) => {
let webappRedirectURL = WEBAPP_LOGIN_URL;
try {
const state = req.query.state;
if(state) {
const stateObj = JSON.parse(state);
webappRedirectURL = stateObj.returnUrl;
}
} catch (err1) {
console.log("customer.service --> parsing error",err1);
}
if (err || !user) {
console.log("customer.service --> !user",err);
res.render('oauth-redirect', {
webappRedirectURL: webappRedirectURL,
success: false,
error: err,
timerCounter: 5,
accessToken: undefined
});
}
else {
console.log("customer.service --> Generating Token",user.generateJWT());
res.render('oauth-redirect', {
webappRedirectURL: webappRedirectURL,
success: true,
timerCounter: 5,
accessToken: user.generateJWT(),
error: undefined
});
}
})(req, res);
}
catch (error) {
console.log("customerService.js ==> socialTypeLoginCallback -->",error);
}
};
Thanks for help in advance!
I have doubt there somewhere I have returned a callback or response so getting 2nd error but for 1st don't know reasons scope seems to be correct!
In socialTypeLogin
add line
oauthOptions['session'] = false;

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client. app crushed

I'm getting this error -> " Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client ".I tried to apply JSON Web Token(JWT) in my app and every time it's logging me out from app. I can't understand is it server-side error or client-side. Pls check my code
Here is the code:
// verifyJWT function
function verifyJWT(req, res, next){
const authHeader = req.headers.authorization;
if (!authHeader) {
return res.status(401).send({ message: 'Your access is unauthorized to BookPile' });
}
const token = authHeader.split(' ')[1];
jwt.verify(token, process.env.ACCESS_TOKEN_SECRECT, (err, decoded) => {
if (err) {
return res.status(403).send({ message: 'BookPile authority forbid your access' })
}
console.log('decoded', decoded);
req.decoded = decoded;
next();
})
console.log('inside verify function', authHeader);
next();
}
//API
// GET API for get token
app.post('/login' , async(req,res) => {
const user = req.body;
const accessToken = jwt.sign(user, process.env.ACCESS_TOKEN_SECRET, {
expiresIn:'1d'
});
res.send({accessToken});
})
// GET API for load items of logged in user
app.get('/my_items' , verifyJWT , async(req,res) => {
// const authHeader = req.headers.authorization;
// console.log(authHeader);
const email = req.query.email;
const criteria = {email:email};
const cursor = await booksCollection.find(criteria);
const books = await cursor.toArray();
res.send(books);
})
//Client side
const getMyBooks = async () => {
const email = user.email;
const url = `http://localhost:5000/my_items?email=${email}`;
try {
const { data } = await axios.get(url, {
headers: {
authorization: `Bearer ${localStorage.getItem('accessToken')}`
}
})
setMyBooks(data);
}
catch (error) {
console.log((error.message));
if (error.response.status === 401 || error.response.status === 403) {
signOut(auth);
// navigate('/login');
}
}
}
getMyBooks();
}, [user])
//Client side login
const handleForm = async event => {
event.preventDefault();
const email = emailRef.current.value;
const password = passRef.current.value;
await signInWithEmailAndPassword(email, password);
const { data } = await axios.post('http://localhost:5000/login', { email });
// console.log(data);
localStorage.setItem('accessToken', data.accessToken);
navigate(from, { replace: true });
}
Since the verify function is executed asynchronously, the last next() call will be called immediately before the verification is done. Therefore you'll have to call either res.send() or next() inside the callback
function verifyJWT(req, res, next){
const authHeader = req.headers.authorization;
if (!authHeader) {
return res.status(401).send({ message: 'Your access is unauthorized to BookPile' });
}
const token = authHeader.split(' ')[1];
jwt.verify(token, process.env.ACCESS_TOKEN_SECRECT, (err, decoded) => {
if (err) {
return res.status(403).send({ message: 'BookPile authority forbid your access' })
}
console.log('decoded', decoded);
req.decoded = decoded;
next();
})
}

Node.js:"Cannot read property 'toString' of undefined

I'm following a restApi course with Node.js, It's a blog API. my problem is when deleting a post for the unAuthorized user it first gives me a 500 error
"error": "Cannot read property 'toString' of undefined"
. but when doing it again it gives me
Post not found with id of.
Of course, it supposed to give me
not authorized to delete this post.
Update the post is also the same, I even tried to copy/paste the code from the course but the same problem.
postController
exports.deletePost = asyncHandler(async (req, res, next) => {
const post = await Post.findByIdAndDelete(req.params.id);
if (!post) {
return next(
new ErrorResponse(`Post not found with id of ${req.params.id}`, 404)
);
}
// Make sure user is post owner
if (post.user.toString() !== req.user.id) {
return next(
new ErrorResponse(
`User ${req.params.id} is not authorized to delete this post`,
401
)
);
}
post.remove();
res.status(200).json({ success: true, data: post});
});
updatePost
exports.updatePost = asyncHandler(async (req, res, next) => {
let post = await Post.findById(req.params.id);
if (!post) {
return next(
new ErrorResponse(`Post not found with id of ${req.params.id}`, 404)
);
}
// Make sure user is post owner
if (post.user.toString() !== req.user.id) {
return next(
new ErrorResponse(
`User ${req.params.id} is not authorized to update this post`,
401
)
);
}
post = await Post.findOneAndUpdate(req.params.id, req.body, {
new: true,
runValidators: true
});
res.status(200).json({ success: true, data: post });
});
You could introduce a type check on the post.user object to ensure that the user exists within the post.
if (typeof post.user == "undefined" || post.user.toString() !== req.user.id)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
I have tried the code
if (typeof post.user == "undefined" || post.user.toString() !== req.user.id)
But after using this cause to get me an error 'User not Authorized' in my error handling.
In my case, I have to convert the req.user.id to an integer
if (post.user !== req.user.id.parseInt)
const express = require("express");
const router = express.Router();
const fetchuser = require("../middleware/Fetchuser");
const Notes = require("../models/Notes.js");
const { body, validationResult } = require("express-validator");
router.get("/fetchnotes", fetchuser, async (req, res) => {
try {
const notes = await Notes.find({ user: req.user });
res.json(notes);
} catch (error) {
console.log(error.message);
res.status(500).send("error occured");
}
});
router.post(
"/addnotes",
[
body("title").isLength({ min: 5 }),
body("description").isLength({ min: 3 }),
],
fetchuser,
async (req, res) => {
try {
const { title, description, tag } = req.body;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const note = new Notes({
title,
description,
tag,
user: req.user.id,
});
const savedNotes = await note.save();
res.json(savedNotes);
} catch (error) {
console.log(error.message);
res.status(500).send("error occured");
}
}
);
router.put("/updatenotes/:id", fetchuser, async (req, res) => {
const { title, description, tag } = req.body;
const newNote = {};
if (title) {
newNote.title = title;
}
if (description) {
newNote.description = description;
}
if (tag) {
newNote.tag = tag;
}
let note = await Notes.findById(req.params.id);
if (!note) {
return res.status(400).send("error occured");
}
if (note.user !== req.user.id.parseInt) {
return res.status(401).json("user not allowed");
}
note = await Notes.findByIdAndUpdate(
req.params.id,
{ $set: newNote },
{ new: true }
);
res.json(note);
});
module.exports = router;

How can I get my err.message in the alert for this node.js app?

I have a PUT in a REST API that should display an error message that says "upvoted already" if the vote_score is 1 (that is, they voted already), but instead I get a generic "internal server error" message in alert which is not good UX. That's always what the error will say with what I have tried so far.
How can I get my error message to display as "upvoted already"? Or for that matter, how can I get any error message to show up with a message? I hope I have provided enough information with the API code followed with the front-end code.
What I have tried thus far is trying different things like res.status(200).json({ error: err.toString() }); and next(err).
Hopefully something simple, I am hoping for a ELI5 type answer because I am a beginner and my error-handling game is weak. Thanks.
const db = require('../db');
const express = require('express');
const debug = require('debug')('app:api:vote');
const Joi = require('joi');
const auth = require('../middleware/auth');
const admin = require('../middleware/admin');
const { required } = require('joi');
const router = express.Router();
router.use(express.urlencoded({ extended: false }));
router.use(express.json());
// general error handler
const sendError = (err, res) => {
debug(err);
if (err.isJoi) {
res.json({ error: err.details.map((x) => x.message + '.').join('\n') });
} else {
res.json({ error: err.message });
}
};
router.put('/upvote/:emojiId/', auth, async (req, res, next) => {
try {
const schema = Joi.object({
emoji_id: Joi.number().required(),
user_id: Joi.number().required(),
vote_score: Joi.number(),
});
const vote = await schema.validateAsync({
emoji_id: req.params.emojiId,
user_id: req.user.user_id,
vote_score: 1,
});
if (!(await db.findVoteByUser(vote.emoji_id, vote.user_id))) {
const upvote = await db.upvote(vote);
} else if ((await db.findVoteByUser(vote.emoji_id, vote.user_id)) == 1) {
throw new Error('Upvoted already');
}
const upvoteScore = await db.getJustUpvotesForEmoji(vote.emoji_id);
res.json(upvoteScore);
} catch (err) {
res.status(500).json({ error: err.toString() });
}
});
module.exports = router;
And the front-end...
$(document).on('click', '.upvote-emoji-button', (evt) => {
const button = $(evt.currentTarget);
const emoji_id = button.data('id');
$.ajax({
method: 'PUT',
url: `/api/vote/upvote/${emoji_id}`,
data: emoji_id,
dataType: 'json',
})
.done((res) => {
if (res.error) {
bootbox.alert(res.error);
} else {
// $('#search-emoji-form').trigger('submit');
button.addClass('btn-danger').removeClass('btn-primary');
button.parent().next().next().html(res.upvotes);
button.parent().next().next().next().next().html(res.vote_count);
button.parent().next().next().next().next().next().html(res.total_score);
}
})
.fail((xhr, textStatus, err) => {
bootbox.alert(err);
});
});
try to replace
res.status(500).json({ error: err.toString() });
with
res.status(400).send(err.toString());
Documentation
Here is what I ended up doing. It took care of my error and a few other things too. :)
//setup
const db = require('../db');
const express = require('express');
const debug = require('debug')('app:api:vote');
const Joi = require('joi');
const auth = require('../middleware/auth');
const admin = require('../middleware/admin');
const { required } = require('joi');
const router = express.Router();
router.use(express.urlencoded({ extended: false }));
router.use(express.json());
// general error handler
const sendError = (err, res) => {
debug(err);
if (err.isJoi) {
res.json({ error: err.details.map((x) => x.message + '.').join('\n') });
} else {
res.json({ error: err.message });
}
};
router.put('/upvote/:emojiId/', auth, async (req, res, next) => {
let vote = {};
try {
const schema = Joi.object({
emoji_id: Joi.number().required(),
user_id: Joi.number().required(),
vote_score: Joi.number(),
});
vote = await schema.validateAsync({
emoji_id: req.params.emojiId,
user_id: req.user.user_id,
vote_score: 1,
});
if (!(await db.findUserByID(req.user.user_id))) {
throw new Error('log in again.');
}
const tester = await db.findVoteByUser(vote.user_id, vote.emoji_id);
if (!(await db.findVoteByUser(vote.user_id, vote.emoji_id))) {
await db.upvotePost(vote);
const upvoteScore = await db.getJustUpvotesForEmoji(vote.emoji_id);
const message = 'message';
upvoteScore[message] = 'Upvote sent.';
const action = 'action';
upvoteScore[action] = 1;
res.json(upvoteScore);
} else if (tester.vote_score == -1) {
await db.upvotePut(vote);
const upvoteScore = await db.getJustUpvotesForEmoji(vote.emoji_id);
const message = 'message';
upvoteScore[message] = 'Downvote changed to upvote.';
const action = 'action';
upvoteScore[action] = 2;
res.json(upvoteScore);
} else {
await db.deleteVoteByUserIdAndEmojiId(vote);
const upvoteScore = await db.getJustUpvotesForEmoji(vote.emoji_id);
const message = 'message';
upvoteScore[message] = 'Upvote deleted.';
const action = 'action';
upvoteScore[action] = 3;
res.json(upvoteScore);
}
} catch (err) {
sendError(err, res);
}
});
module.exports = router;
and front end..
$(document).on('click', '.upvote-emoji-button', (evt) => {
const button = $(evt.currentTarget);
const emoji_id = button.data('id');
$.ajax({
method: 'PUT',
url: `/api/vote/upvote/${emoji_id}`,
data: emoji_id,
dataType: 'json',
})
.done((res) => {
if (res.error) {
bootbox.alert(res.error);
} else {
if (res.action == 1) {
button.addClass('btn-danger').removeClass('btn-primary');
button.parent().next().next().html(res.upvotes);
button.parent().next().next().next().next().html(res.vote_count);
button.parent().next().next().next().next().next().html(res.total_score);
bootbox.alert(res.message);
} else if (res.action == 2) {
button.addClass('btn-danger').removeClass('btn-primary');
button.parent().next().children().addClass('btn-primary').removeClass('btn-danger');
button.parent().next().next().html(res.upvotes);
button.parent().next().next().next().next().html(res.vote_count);
button.parent().next().next().next().next().next().html(res.total_score);
bootbox.alert(res.message);
} else if (res.action == 3) {
button.removeClass('btn-danger').addClass('btn-primary');
button.parent().next().next().html(res.upvotes);
button.parent().next().next().next().next().html(res.vote_count);
button.parent().next().next().next().next().next().html(res.total_score);
bootbox.alert(res.message);
}
}
})
.fail((xhr, textStatus, err) => {
bootbox.alert(err);
// alert(`${textStatus}\n${err}\n${xhr.status}`);
});
});

Getting error " Route.post() requires a callback function but got a [object Undefined]"

Can anyone explain to me why I'm getting this error? Here's my code where I'm getting this error. I assume it's becuase of the imports/exports in my code?
emailController
const User = require("../models/User")
const jwt = require("jsonwebtoken")
const { transporter, getResetPasswordURL, resetPasswordTemplate } = require("../utils/mailer")
module.exports = {
createOneTimeTokenAndSendMail: async (req, res) => {
const email = req.params.email
try {
const user = await User.findOne({ email })
if (!user) {
return res.status(404).json({ error: "No user with that email "})
}
const hashedPassword = user.password
const createdAt = user.createdAt
const userId = user._id
const secret = hashedPassword + "-" + createdAt
const token = jwt.sign({ userId }, secret, {
expiresIn: 3600
})
const url = getResetPasswordURL(user, token)
const emailTemplate = resetPasswordTemplate(user, url)
const sendEmail = () => {
transporter.sendMail(emailTemplate, (err, info) => {
if (err) {
res.status(500).json("Error sending email")
}
console.log("email sent", info.response)
})
}
sendEmail()
} catch (error) {
res.status(500).json({ error })
}
}
}
mailer
const User = require("../models/User")
const jwt = require("jsonwebtoken")
const {
transporter,
getResetPasswordURL,
resetPasswordTemplate
} = require("../utils/mailer")
module.exports = {
createOneTimeTokenAndSendMail: async (req, res) => {
const email = req.params.email
try {
const user = await User.findOne({ email })
if (!user) {
return res.status(404).json({ error: "No user with that email " })
}
const hashedPassword = user.getPassword
const createdAt = user.createdAt
const userId = user._id
const secret = hashedPassword + "-" + createdAt
const token = jwt.sign({ userId }, secret, {
expiresIn: 3600
})
const url = getResetPasswordURL(user, token)
const emailTemplate = resetPasswordTemplate(user, url)
const sendEmail = () => {
transporter.sendMail(emailTemplate, (err, info) => {
if (err) {
res.status(500).json("Error sending email")
}
console.log("email sent", info.response)
})
}
sendEmail()
} catch (error) {
res.status(500).json({ error })
}
}
}
This is the route which is throwing the above error:
router.post("/reset-password/:email", emailController.createOneTimeTokenAndSendMail)
I have been dealing with errors like these constantly, so I'd like to clear my doubts once and for all.

Categories