Duplicate key E11000 is the expected behavior but crashing the server is not. The duplicate key error comes from my unique index on email.
controller method:
exports.saveOAuthUserProfile = function(req, profile, done) {
User.findOne({
provider: profile.provider,
providerId: profile.providerId
}, function(err, user) {
if (err) {
return done(err);
} else {
if (!user) {
var possibleUsername = profile.username || ((profile.email) ? profile.email.split('#')[0] : '');
User.findUniqueUsername(possibleUsername, null, function(availableUsername) {
profile.username = availableUsername;
user = new User(profile);
user.save(function(err) {
if (err) {
var message = getErrorMessage(err);
console.log(message);
//req.flash('error', message);
return res.redirect('/signup');
}
return done(err, user);
});
});
} else {
return done(err, user);
}
}
});
};
getErrorMessage method:
var getErrorMessage = function(err) {
var message = '';
// If an internal MongoDB error occurs get the error message
if (err.code) {
switch (err.code) {
// If a unique index error occurs set the message error
case 11000:
message = 'Duplicate Key';
break;
case 11001:
message = 'Username already exists';
break;
// If a general error occurs set the message error
default:
message = 'Something went wrong';
}
} else {
// Grab the first error message from a list of possible errors
for (var errName in err.errors) {
if (err.errors[errName].message) message = err.errors[errName].message;
}
}
return message;
};
email in UserSchema:
email: {
type: String,
unique: 'That email is already taken',
match: [/.+\#.+\..+/, 'Please use a valid e-mail address']
},
cli output:
λ node server
Server running at http://localhost:3000/
GET / 200 26.879 ms - 1347
GET /lib/angular-route/angular-route.min.js 200 12.790 ms - 4408
GET /lib/angular-resource/angular-resource.min.js 200 13.863 ms - 3598
GET /modules/example/example.client.module.js 200 14.557 ms - 30
GET /modules/example/controllers/example.client.controller.js 200 12.595 ms - 240
GET /modules/example/config/example.client.routes.js 200 12.024 ms - 547
GET /lib/angular/angular.min.js 200 77.183 ms - 145234
GET /modules/users/users.client.module.js 200 24.306 ms - 28
GET /modules/users/services/authentication.client.service.js 200 25.467 ms - 168
GET /application.js 200 23.834 ms - 536
GET /modules/articles/articles.client.module.js 200 27.471 ms - 31
GET /modules/articles/services/articles.client.service.js 200 28.066 ms - 234
GET /modules/example/views/example.client.view.html 200 1.968 ms - 83
GET /lib/angular/angular.min.js.map 304 10.579 ms - -
GET /lib/angular-route/angular-route.min.js.map 304 17.932 ms - -
GET /lib/angular-resource/angular-resource.min.js.map 304 31.510 ms - -
GET /signin 200 5.881 ms - 606
GET /oauth/google 302 2.573 ms - 0
Duplicate Key
C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:108
if (this.ended && !this.hasRejectListeners()) throw reason;
^
ReferenceError: res is not defined
at EventEmitter.<anonymous> (C:\Users\lotus\Desktop\mastering_mean\application\app\controllers\users.server.controller.js:107:22)
at EventEmitter.<anonymous> (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:174:48)
at EventEmitter.emit (events.js:107:17)
at Promise.safeEmit (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:81:21)
at Promise.reject (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:109:15)
at Promise.error (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\lib\promise.js:94:15)
at Promise.resolve (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\lib\promise.js:112:24)
at C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\lib\document.js:1578:39
at handleError (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:40:22)
at next_ (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:75:26)
at EventEmitter.fnWrapper (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:171:15)
at EventEmitter.<anonymous> (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:174:48)
at EventEmitter.emit (events.js:107:17)
at Promise.safeEmit (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:81:21)
at Promise.reject (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:109:15)
at C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\lib\model.js:263:20
As you can see in the cli output my getErrorMessage function is correctly retrieving the error and I can console.log(message) but at this point node server crashes resulting in the error message that res is not defined.
node version: 0.12.4
MongoDB shell version: 3.0.3
express 4.12.4
mongoose 4.0.5
Win 7 Pro x64
Any more information I can provide?
UPDATE:
Adding the passport strategy that calls the controller method
module.exports = function() {
passport.use(new GoogleStrategy({
clientID: config.google.clientID,
clientSecret: config.google.clientSecret,
callbackURL: config.google.callbackURL,
passReqToCallback: true
},
function(req, accessToken, refreshToken, profile, done) {
var providerData = profile._json;
providerData.accessToken = accessToken;
providerData.refreshToken = refreshToken;
var providerUserProfile = {
firstName: profile.name.givenName,
lastName: profile.name.familyName,
fullName: profile.displayName,
email: profile.emails[0].value,
username: profile.emails[0].value.replace(/#.*$/,""),
provider: 'google',
providerId: profile.id,
providerData: providerData
};
users.saveOAuthUserProfile(req, providerUserProfile, done);
}));
Passport strategy handlers have an option to get passed req (by setting passReqToCallback), but not res. So if you need the response object in the strategy handler, or any functions called from it (like your users.saveOAuthUserProfile), you need to use the fact that Express adds the response object to the request object, which you can access through req.res.
So this:
return res.redirect('/signup');
Needs to be this:
return req.res.redirect('/signup');
Related
Update: This problem was solved. I followed the advice of the replies and tried the console.log(req.body) command. Turns out it was calling a different function. Now at the time I was using postman to test the API and I learned that editing an already saved function is not the same as with other text or media editors and you have to make a completely new function to test it. I.E. I used a previous post function to create user and changed some elements, turns out postman doesnt like that and just ran the old function.
Thanks for the help everyone
I made an admin route using an already working user route exactly except using fewer values.
I keep getting an undefined error during validation when ever I try to run a post function. what could have gone wrong here? Or where should I look for the error, I checked the spellings of each of the values Iam using in the create admin function but I see no spelling problems?
Error in Console:
Error: admin validation failed: AdminEMail: Path `AdminEMail` is required., AdminPassword: Path `AdminPassword` is required.
at ValidationError.inspect (D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\error\validation.js:48:26)
at formatValue (internal/util/inspect.js:563:31)
at inspect (internal/util/inspect.js:221:10)
at formatWithOptions (internal/util/inspect.js:1693:40)
at Object.Console.<computed> (internal/console/constructor.js:272:10)
at Object.log (internal/console/constructor.js:282:61)
at D:\Downloads\Compressed\api-master_3\api-master\routes\Admin.js:25:21
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\model.js:4876:16
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\helpers\promiseOrCallback.js:16:11
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\model.js:4899:21
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\model.js:493:16
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\kareem\index.js:246:48
at next (D:\Downloads\Compressed\api-master_3\api-master\node_modules\kareem\index.js:167:27)
at next (D:\Downloads\Compressed\api-master_3\api-master\node_modules\kareem\index.js:169:9)
at Kareem.execPost (D:\Downloads\Compressed\api-master_3\api-master\node_modules\kareem\index.js:217:3)
at _handleWrapError (D:\Downloads\Compressed\api-master_3\api-master\node_modules\kareem\index.js:245:21) {
errors: {
AdminEMail: ValidatorError: Path `AdminEMail` is required.
at validate (D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\schematype.js:1178:13)
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\schematype.js:1161:7
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\schematype.js:1106:14)
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\document.js:2379:18
at processTicksAndRejections (internal/process/task_queues.js:76:11) {
properties: [Object],
kind: 'required',
path: 'AdminEMail',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
},
AdminPassword: ValidatorError: Path `AdminPassword` is required.
at validate (D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\schematype.js:1178:13)
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\schematype.js:1161:7
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\schematype.js:1106:14)
at D:\Downloads\Compressed\api-master_3\api-master\node_modules\mongoose\lib\document.js:2379:18
at processTicksAndRejections (internal/process/task_queues.js:76:11) {
properties: [Object],
kind: 'required',
path: 'AdminPassword',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
}
},
_message: 'admin validation failed'
}
And Here is the route:
//Imported modules
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
//Imported models
const Admin = require('../models/admin');
//const User = require('../models/user');
router.get('/', (req,res) =>{
res.send("We are on Admin");
})
//Admin Functions
//Creation of new Admin
router.post("/signup", (req,res) => {
const admin = new Admin({
_id: new mongoose.Types.ObjectId(),
AdminEMail: req.body.AdminEMail,
AdminPassword: req.body.AdminPassword
});
admin.save(function(err,admin){
if(err){
console.log(err);
res.send(err);
return
}
console.log("New admin created");
res.send(admin);
})
})
//Admin Login and verification
router.post("/login", (req,res) => {
const AdminID = req.body.AdminID;
const Username = req.body.username;
const Password = req.body.password;
Admin.findOne({_id:AdminID}, function(err, foundAdmin){
if(err){
res.send("<h1>got clicked</h1>");
console.log(err);
}else{
if(foundAdmin){
if(foundAdmin.AdminEMail === Username){
if(foundAdmin.AdminPassword === Password){
res.send("logged in");
}
else{
res.send("Username and Password Mismatch");
}
}
else{
res.send("Username and ID Mismatch");
}
}
else{
res.send("No Such admin exists");
}
}
});
});
//
module.exports = router;
I just want to implement Joi in Hapi API.
server.route([
{
method: 'POST',
path: '/login',
config: {
tags: ['login', 'auth'],
auth: false,
validate: {
payload: payloadValidator,
failAction: (req, h, source, error) => {
console.log("Error ::: ", source.details[0].message);
return h.response({ code: 0, message: source.details[0].message });
}
}
},
handler: async (request, h) => {
console.log(request.payload.email);
console.log(request.payload.password);
...
}
}
]);
Hear I call payloadValidator.
const payloadValidator = Joi.object({
email: Joi.string().required(),
password: Joi.string().required()
}).options({ allowUnknown: true });
Actually I'm new with hapi and I'm missing something in my code. Can anyone help me to fix this issue?
Required output
If I do not pass email then the app must throw an error of Email is required and it should be the same with the password field also.
Error:
Error ::: "email" is required
Debug: internal, implementation, error
Error: Lifecycle methods called before the handler can only return an error, a takeover response, or a continue signal
at Request._lifecycle (/var/www/html/hapi/node_modules/#hapi/hapi/lib/request.js:326:33)
at process._tickCallback (internal/process/next_tick.js:68:7)
As an error suggests Lifecycle methods called before the handler can only return an error, a takeover response, or a continue signal you have to return takeover response.
return h.response({ code: 0, message: source.details[0].message }).takeover();
For more information you can visit this link : reference link
I have the following route for the password reset form, the form has a password and password confirmation field.
router.post('/users/reset/:token', (req, res, next) => {
if(req.body.password === req.body['password-confirm']) {
req.flash('error', 'Passwords do not match!');
res.redirect('/users/forgot');
}
User.findOne({
resetPasswordToken: req.params.token,
resetPasswordExpires: { $gt: Date.now() }
}, function(err, user) {
if(!user) {
req.flash('error', ' Password reset is invalid or has expired');
res.redirect(302, '/login');
}
const setPassword = promisify(user.setPassword, user);
setPassword(req.body.password);
user.resetPasswordToken = undefined;
user.resetPasswordExpires = undefined;
const updatedUser = user.save();
user.save((saveError, updatedUser) => {
// Check if saveError is present here and handle appropriately
req.login(updatedUser, loginError => {
req.flash('success_msg', 'Your password has been reset successfully! You are now logged in!');
res.redirect('/dashboard' + req.user);
})
});
});
});
When I fill out the form I get the following error
Fri Jan 26 2018 11:28:55 GMT+0000 (GMT): GET /users/reset/6e2574bfa532e0d13af7fae61114308f9a683767
Mongoose: users.findOne({ resetPasswordExpires: { '$gt': new Date("Fri, 26 Jan 2018 11:28:55 GMT") }, resetPasswordToken: '6e2574bfa532e0d13af7fae61114308f
9a683767' }, { fields: {} })
Fri Jan 26 2018 11:28:55 GMT+0000 (GMT): GET /favicon.ico
Fri Jan 26 2018 11:29:02 GMT+0000 (GMT): POST /users/reset/6e2574bfa532e0d13af7fae61114308f9a683767
Mongoose: users.findOne({ resetPasswordExpires: { '$gt': new Date("Fri, 26 Jan 2018 11:29:02 GMT") }, resetPasswordToken: '6e2574bfa532e0d13af7fae61114308f
9a683767' }, { fields: {} })
Mongoose: users.update({ _id: ObjectId("5a5c6740b9e210087e098fd6") }, { '$unset': { resetPasswordExpires: 1, resetPasswordToken: 1 } })
Mongoose: users.update({ _id: ObjectId("5a5c6740b9e210087e098fd6") }, { '$unset': { resetPasswordExpires: 1, resetPasswordToken: 1 } })
(node:1451) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'apply' of undefined
at /Users/benbagley/Code/poetry-out-loud/node_modules/es6-promisify/dist/promisify.js:75:41
at new Promise (<anonymous>)
at /Users/benbagley/Code/poetry-out-loud/node_modules/es6-promisify/dist/promisify.js:54:20
at /Users/benbagley/Code/poetry-out-loud/routes/users.js:321:5
at model.Query.<anonymous> (/Users/benbagley/Code/poetry-out-loud/node_modules/mongoose/lib/model.js:4056:16)
at /Users/benbagley/Code/poetry-out-loud/node_modules/kareem/index.js:273:21
at /Users/benbagley/Code/poetry-out-loud/node_modules/kareem/index.js:131:16
at process._tickCallback (internal/process/next_tick.js:150:11)
(node:1451) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a c
atch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:1451) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminat
e the Node.js process with a non-zero exit code.
Fri Jan 26 2018 11:29:02 GMT+0000 (GMT): GET /users/forgot
events.js:136
throw er; // Unhandled 'error' event
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at validateHeader (_http_outgoing.js:503:11)
at ServerResponse.setHeader (_http_outgoing.js:510:3)
at ServerResponse.header (/Users/benbagley/Code/poetry-out-loud/node_modules/express/lib/response.js:767:10)
at ServerResponse.location (/Users/benbagley/Code/poetry-out-loud/node_modules/express/lib/response.js:884:15)
at ServerResponse.redirect (/Users/benbagley/Code/poetry-out-loud/node_modules/express/lib/response.js:922:18)
at req.login.loginError (/Users/benbagley/Code/poetry-out-loud/routes/users.js:332:13)
at /Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/http/request.js:51:48
at /Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/sessionmanager.js:16:14
at pass (/Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/authenticator.js:297:14)
at Authenticator.serializeUser (/Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/authenticator.js:299:5)
at SessionManager.logIn (/Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/sessionmanager.js:14:8)
at IncomingMessage.req.login.req.logIn (/Users/benbagley/Code/poetry-out-loud/node_modules/passport/lib/http/request.js:50:33)
at user.save (/Users/benbagley/Code/poetry-out-loud/routes/users.js:330:11)
at /Users/benbagley/Code/poetry-out-loud/node_modules/mongoose/lib/model.js:4056:16
at /Users/benbagley/Code/poetry-out-loud/node_modules/mongoose/lib/services/model/applyHooks.js:170:20
at process._tickCallback (internal/process/next_tick.js:150:11)
I'm still new to node so any refactoring tips, or fixes for this would be most appreciated, been stuck on this issue for a few days, not sure what I'm doing wrong.
Thank you.
First thing is that this error occur when node sent response of API call more than one time. Secondly, it is best practice to use return when sending response for example return res.json(<OBJECT>);
In your code you are checking the password like
req.body.password === req.body['password-confirm']
it should be like
req.body.password !== req.body['password-confirm']
that may the case that causing node to sent multiple response
You are sending response to client multiple time, that's why facing Cannot set headers after they are sent to the client error.
In your case, your are not returning (exiting) from the function execution when you should have. E.g. when password doesn't match, you are trying to redirect user to /users/forgot, but you are not returning the function there. Hence, code below if condition executes and try to send response back again.
Solution:
router.post('/users/reset/:token', (req, res, next) => {
if // some condition {
// some code
return res.redirect('/users/forgot');
}
User.findOne({
// some code
}, function(err, user) {
if(!user) {
// some code
return res.redirect(302, '/login');
}
// some code
user.save((saveError, updatedUser) => {
req.login(updatedUser, loginError => {
// some code
return res.redirect('/dashboard' + req.user);
})
});
});
});
When I try to update a user using a web form, it runs a app.post on express. The object user is correct, but sometimes it throws a error in node console
app.post('/register/update', jsonParser, (request, response) => {
let user = request.body.user;
let users = mongoUtil.users();
console.log(user);
users.update({email: user.email}, user, (err, res) => {
if(err) {
response.sendStatus(400);
}
response.sendStatus(201);
});
});
In node console:
{ _id: '578246ec9eb0587a5d67b8c9',
email: 'test#test.com',
zipcode: '1231-123',
companyName: 'test',
tradeName: 'test',
contactName: 'Test',
tel: '(14) 1232-1231',
password: 'test',
passwordConfirm: 'test',
adress: 'test',
adressComplement: 'test',
adressNumber: '123' }
/home/ec2-user/ ... /mongodb/lib/utils.js:98
process.nextTick(function() { throw err; });
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:346:11)
at ServerResponse.header (/home/ec2-user/ ... /node_modules/express/lib/response.js:719:10)
at ServerResponse.contentType (/home/ec2-user/ ... /node_modules/express/lib/response.js:552:15)
at ServerResponse.sendStatus (/home/ec2-user/ .. /node_modules/express/lib/response.js:340:8)
at users.update (/home/ec2-user/menuWebApp/server/app.js:94:14)
at handleCallback (/home/ec2-user/ ... /node_modules/mongodb/lib/utils.js:96:12)
at /home/ec2-user/ ... /node_modules/mongodb/lib/collection.js:1008:42
at commandCallback (/home/ec2-user/ ... /node_modules/mongodb/node_modules/mongodb-core/lib/topologies/server.js:1194:9)
at Callbacks.emit (/home/ec2-user/ ... /node_modules/mongodb/node_modules/mongodb-core/lib/topologies/server.js:119:3)
at Connection.messageHandler (/home/ec2-user/ ... /node_modules/mongodb/node_modules/mongodb-core/lib/topologies/server.js:358:23)
I'm probably dealing with a callback problem, but I don't have idea how to solve it D:
The error is not coming from the update statement itself its coming from your callback function.
Specifically these lines of code.
if(err) {
response.sendStatus(400);
}
response.sendStatus(201);
What you are doing is if there is an error send the status 400, then send the status 201. The problem is once you send a response with your headers to the requestor you can't try and set the headers again.
So your code should change to:
if(err) {
response.sendStatus(400);
}else{
response.sendStatus(201);
}
So if an error is generated you will send a 400 response otherwise you will send a 201 response instead of trying to send a 400 response and then a 201 response immediately after.
When I use login function
User.login({email: 'foo#bar.com', password: 'bar'}, function(err, accessToken) {
console.log(err);
console.log(accessToken);
})
the error is
TypeError: Object [Model session] has no method 'create'
It looks like you are using an old version of LoopBack. Try upgrading and making sure the user model is attached to a data source. Below are the steps to do this.
// # Verify version
// Ω slc version
// slc v2.1.1 (node v0.10.9)
// # upgrade with `npm install strong-cli -g`
// # create a simple project
// Ω slc lb project hello-user
// Ω cd hello-user
// # create hello-user/models/user.js
var user = require('app').models.user;
var credentials = {
email: 'foo#bar.com',
password: 'password'
};
user.create(credentials, function(err) {
user.login(credentials, function(err, accessToken) {
console.log(accessToken);
// { userId: 1,
// ttl: 1209600,
// id: 'nt2KN4N5p3QbxByypRiHlduavxCRJUPbcStWPfxgrWYU8JllryjUp028hlJAFx4D',
// created: Tue Jan 14 2014 08:26:22 GMT-0800 (PST) }
});
});