I'm new to passport and I'm trying to create a "register" page. This actually works fine, and the log-in form as well. However, I want to check if the username entered already exists, and if it does, throw an error to the user. Here is my code so far:
expressApp.post("/register", function(request, response){
User.findOne({username: request.body.username}, function(err, user) {
if (err) {
return err;
}
if (user) {
}
else {
User.register(new User({
username: request.body.username,
type: "Student"}),
request.body.password, function(err){
if(err){
console.log(err);
}
passport.authenticate("local")(request, response, function(){
response.redirect("/");
});
});
}
})
});
However, If someone chooses a username that already exists, then i want to be able to tell them that there is an error.
It should look something like this.
expressApp.post("/register", function(request, response) {
User.findOne({
username: request.body.username
}, function(err, user) {
if (err) {
return err
} else if (user) {
//user.message = "User already exists!!"
response.statusCode = 409
return response.send({"message": "User already exists!!")
} else {
User.register(new User({
username: request.body.username,
type: "Student"
}),
request.body.password,
function(err) {
if (err) {
console.log(err);
}
passport.authenticate("local")(request, response, function() {
response.redirect("/");
});
});
}
});
});
Related
I have this problem in the time i am in admin routes and i try to add a new article or a new image in my database , the same things happen even when i want to update something ....
this is my codes ?
exports.isAdmin = (req, res, next) => {
if (req.isAuthenticated() && res.locals.user.admin == 1) {
next();
} else {
req.flash("danger", "please log in as admin");
res.redirect("/users/login");
}
}
var LocalStrategy = require("passport-local").Strategy;
var User = require("../models/user");
var bcrypt = require("bcryptjs");
module.exports = function (passport) {
passport.use(new LocalStrategy(function (username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err)
console.log(err);
if (!user) {
return done(null, false, { message: "No user found" });
}
bcrypt.compare(password, user.password, function (err, isMatch) {
if (err) console.log(err);
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: "Wrong password" });
}
})
});
}));
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
}
Anyone one can help the problem is i think in res.locals.user.admin but in other admin routes works ok but only when i want to add a new and edit a think happen this problem
I have small project to introduce myself to some front-end technologies. I am using Node, Express, Pug, and MongoDB.
I define the user schema in my user.js file:
var userSchema = mongoose.Schema({
username : String,
password : String,
jobs : [{ type: mongoose.Schema.Types.Mixed }]
});
Then, in my passport.js file I start the sign up process.
User.findOne({ 'username' : username }, function(err, user) {
// if there are any errors, return the error
if (err) {
console.log(err);
return done(err);
}
// check to see if theres already a user with that email
if (user) {
console.log('user exists');
return done(null, false, req.flash('signupMessage', 'That username is already taken.'));
} else {
console.log('creating new user...');
// if there is no user with that email
// create the user
var newUser = new User();
newUser.username = username;
newUser.password = newUser.generateHash(password);
newUser.jobs = [{ website: 'google.com' }];
// save the user
newUser.save(function(err) {
if (err) {
console.log(err);
throw err;
}
console.log('user saved: ', newUser);
return done(null, newUser);
});
}
});
The post successfully saves the new user as:
{
"_id": {
"$oid": "5967d2acc64d953330a3ac32"
},
"__v": 0
}
My goal is to have an array in the database where website links can be pushed into the array for that user.
Thanks for any assistance.
Set the jobs field type as array of Mixed:
var userSchema = mongoose.Schema({
local: { username : String, password : String },
jobs: [ { type: mongoose.Schema.Types.Mixed } ]
});
Then create the user passing all parameters to the constructor:
var newUser = new User({
local: {
username: username,
password: User.generateHash(password),
},
jobs: [{ website: 'google.com' }]
});
// save the user
newUser.save(function(err) {
if (err) {
console.log(err);
throw err;
}
console.log('user saved: ', newUser);
return done(null, newUser);
});
You could also create the user without instantiating it first:
// save the user
User.create({
local: {
username: username,
password: User.generateHash(password),
},
jobs: [{ website: 'google.com' }]
}, function(err, newUser) {
if (err) {
console.log(err);
throw err;
}
console.log('user saved: ', newUser);
return done(null, newUser);
})
For both these methods you will probably need to make the generateHash a static method.
I'm trying to authenticate a user when logging in to website. Upon login, the username and password get sent to a post route from an ajax request on the client side. The problem is that there is an old userID attached to req.user._id that I cannot remove. This old userID continues to authenticate any user I try.
This is my passport settings on the server:
var passport = require('passport');
var BasicStrategy = require('passport-http').BasicStrategy;
var strategy = new BasicStrategy(function(username, password, callback) {
User.findOne({
username: username
}, function(err, user) {
if (err) {
callback(err);
return;
}
if (!user) {
return callback(null, false, {
message: 'Incorrect username.'
});
}
user.validatePassword(password, function(err, isValid) {
if (err) {
return callback(err);
}
if (!isValid) {
return callback(null, false, {
message: 'Incorrect password.'
});
}
return callback(null, user);
});
});
});
passport.use(strategy);
app.use(passport.initialize());
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
This is my route:
app.post('/authenticate', passport.authenticate('basic', { session: false }), function(req, res) {
console.log("req.user:", req.user);
var id = req.user._id;
res.json({
message: 'You have been authenticated',
userID: id
});
});
On the client side, I am sending a POST request like this:
function getLogin(loginObject) {
$.ajax({
type: "POST",
url: "/authenticate",
dataType : "json",
data: { username: loginObject.username, password: loginObject.password }
})
.done(function(result) {
console.log("Authenticated");
loginUserID = result.userID;
})
.fail(function(jqXHR, error, errorThrown) {
};
This is a screenshot of my terminal showing the userID that won't delete:
req.user: { _id: 588a834c08c038342e420568,
username: 'mm',
password: '$2a$10$Khp1wUkHvLLn6ZVBNlLqM.Mtio0ZZ4dznGPQs0ECqf.snhUl44OxK',
__v: 0 }
From my understanding, the req.user._id is created as soon as the username and password get's authenticated. So I cannot understand what is holding on to this userID.
Your help is appreciated.
I have a ReactJS and Redux connected to MongoDB, Mongoose.
I have a Mongoose Schema (user.js) set up like so:
var UserSchema = new Schema({
email: {
type: String,
lowercase: true,
unique: true,
required: true
},
})
And a API controller that receives the email string request, and then if nothing is entered in the text field, it sends a 422 error, and inside User.findOne, if the email already exists in the database, then it throws a 422 error and if not, does user.save to save it in the database.
"use strict";
const User = require('../models/user')
exports.register = function(req, res, next) {
const email = req.body.email;
console.log('ERROR 1')
if(!email) {
return res.status(422).send({ error: 'You must enter an email address.'})
console.log('ERROR 1')
}
User.findOne({ email: email }, function(err, existingUser) {
if(err) { return next(err); }
console.log('ERROR 2')
if(existingUser) {
return res.status(422).send({ error: 'That email address is already in use.'})
}
console.log('ERROR 3')
let user = new User({
email: email,
})
console.log('ERROR 4')
user.save(function(err, user) {
if(err) { return next(err); }
console.log('ERROR 5')
res.status(201).json({
user: user,
})
})
})
console.log('ERROR 6')
}
And I am making a POST request as such:
export function registerUser({ email }) {
return function(dispatch) {
axios.post(`${API_URL}/auth/register`, { email })
.then(response => {
console.log('THIS IS TESTING PURPOSE')
console.log(response)
dispatch({ type: AUTH_USER });
})
.catch((error) => {
errorHandler(dispatch, error.response, AUTH_ERROR)
});
}
}
I made several POST requests and all get successful status back from API with sever config: {'database': 'mongodb://localhost/practicedb',
'port': process.env.PORT || 3000}, yet the data never gets saved and database (practicedb) doesn't show up on Terminal.
Everything seem to be set up correctly but why the problem? Could I be missing something? Any insight or guidance would be really appreciated.
Thank you in advance!
Here are some logs and what's OPTIONS request that I never made:
Tried registering with same email again:
Correct if i'm wrong but your bare save method is not async. Save method return a promise. See http://mongoosejs.com/docs/promises.html
EDIT
user.save().then(function(doc) {
if (!doc) { next(new Error('Error while persisting!')); }
console.log('ERROR 5');
res.status(201).json({
user: doc
});
});
You can also achieve this with any promised library (Q, bluebird) or use ES6 Promise. Alternatively use async.
Example with Q. NOT TESTED:
"use strict";
const User = require('../models/user');
const Q = require('Q'); //add https://github.com/kriskowal/q
exports.register = function(req, res, next) {
const email = req.body.email;
console.log('ERROR 1')
if(!email) {
return res.status(422).send({ error: 'You must enter an email address.'})
console.log('ERROR 1')
}
var deferred = Q.defer();
User.findOne({ email: email }, function(err, existingUser) {
if(err) { return next(err); }
console.log('ERROR 2')
if(existingUser) {
return res.status(422).send({ error: 'That email address is already in use.'})
}
console.log('ERROR 3')
let user = new User({
email: email,
})
console.log('ERROR 4')
user.save(function(err, user) {
if(err) {
deferred.reject(err);
return next(err);
}
console.log('ERROR 5')
deferred.resolve(user); //
});
res.status(201).json({
user: deferred.promise,
})
})
console.log('ERROR 6')
}
I just looking for solution which makes verification email with token for my local autentification in passport.js
Is there some plugin or component for node which can make me verification easyer? Or I have to do it myself?
My controller
exports.postSignup = function(req, res, next) {
req.assert('email', 'Email is not valid').isEmail();
req.assert('password', 'Password must be at least 4 characters long').len(4);
req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password);
var errors = req.validationErrors();
if (errors) {
req.flash('errors', errors);
return res.redirect('/signup');
}
var user = User.build({
email: req.body.email,
password: req.body.password,
});
User
.find({ where: { email: req.body.email } })
.then(function(existingUser){
if (existingUser) {
req.flash('errors', { msg: 'Account with that email address already exists.' });
return res.redirect('/signup');
}
user
.save()
.complete(function(err){
if (err) return next(err);
req.logIn(user, function(err){
if (err) return next(err);
res.redirect('/');
});
});
}).catch(function(err){
return next(err);
});
};
Thanks for any opinion!
Implementing this yourself is pretty straightforward.
The pseudocode:
//A user registers
//User is stored along with a random token string and a variable set to false
//User is sent a verification email
//Verification email has a link with the random token and a unique ID for that user
//Link goes to a route that takes the token as a parameter
//Match the user and the random token
//If they match - change a variable to verified
The package I use to generage the random string is:
https://www.npmjs.com/package/randomstring
Local signup strategy
passport.use('local-signup', 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) {
// asynchronous
// User.findOne wont fire unless data is sent back
process.nextTick(function () {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
User.findOne({'local.email': email}, function (err, user) {
// if there are any errors, return the error
if (err) {
return done(err);
}
// check to see if theres already a user with that email
if (user) {
console.log('that email exists');
return done(null, false, req.flash('signupMessage', email + ' is already in use. '));
} else {
User.findOne({'local.username': req.body.username}, function (err, user) {
if (user) {
console.log('That username exists');
return done(null, false, req.flash('signupMessage', 'That username is already taken.'));
}
if (req.body.password != req.body.confirm_password) {
console.log('Passwords do not match');
return done(null, false, req.flash('signupMessage', 'Your passwords do not match'));
}
else {
// create the user
var newUser = new User();
var permalink = req.body.username.toLowerCase().replace(' ', '').replace(/[^\w\s]/gi, '').trim();
var verification_token = randomstring.generate({
length: 64
});
newUser.local.email = email;
newUser.local.password = newUser.generateHash(password);
newUser.local.permalink = permalink;
//Verified will get turned to true when they verify email address
newUser.local.verified = false;
newUser.local.verify_token = verification_token;
try {
newUser.save(function (err) {
if (err) {
throw err;
} else {
VerifyEmail.sendverification(email, verification_token, permalink);
return done(null, newUser);
}
});
} catch (err) {
}
}
});
}
});
});
}));
I use a combination of /permalink/random-token for the verification URL
The route should look like this:
app.get('/verify/:permaink/:token', function (req, res) {
var permalink = req.params.permaink;
var token = req.params.token;
User.findOne({'local.permalink': permalink}, function (err, user) {
if (user.local.verify_token == token) {
console.log('that token is correct! Verify the user');
User.findOneAndUpdate({'local.permalink': permalink}, {'local.verified': true}, function (err, resp) {
console.log('The user has been verified!');
});
res.redirect('/login');
} else {
console.log('The token is wrong! Reject the user. token should be: ' + user.local.verify_token);
}
});
});