I'm making a forgot password functionality in my express app suing node mailer package which sends a new password to the email of the user and then updating the database with the new password but the problem is that the database is not updating with the new password i have reviewed my code many times but unable to figure out the problem.
`app.post('/forgot', (req, res) => {
const { email } = req.body;
let newPassword = generatePassword();
db.select('*').from('login')
.where('email', '=', email)
.returning('*')
.then(user => {
if (user.length > 0) {
let mailOptions = {
from: 'haroonrmit#gmail.com',
to: `${email}`,
subject: 'Password reset',
html: `<p>Your new password is ${newPassword}</p>`
};
transporter.sendMail(mailOptions);
db('login')
.where({email: user[0].email})
.update({
password: newPassword
})
res.json(user[0]);
} else {
res.status(404).json('email not found');
}
})
});`
You are not calling .then for the second query, so it is built but never ran.
Also your http returns a value before it knows if update was executed with success.
Related
I am trying to implement email confirmation on my project. I sign a JWT which is sent in an email using nodemailer. After the link is clicked the JWT is sent to the server for processing. I am able to find out if the JWT matches the one generated by the server. However I am now struggling with updating the database to store that the user has confirmed the email.
Controller
confirmEmail = async (req, res, next) => {
this.checkValidation(req)
const { email } = req.body
const param = req.params.token
const user = await userModel.findOne({ email })
if(!user)
{
throw new HttpException(401, 'User not found')
}
if(user.confired)
{
throw new HttpException(401, 'User already confirmed')
}
if(!user.confirmed)
{
const confirmJWT = jwt.verify(param, process.env.SECRET_JWT)
if(!confirmJWT)
{
throw new HttpException(200, 'Token failed')
}
const result = await userModel.emailConfirmed(email)
throw new HttpException(401, 'User not cofirmed')
}
}
Model
emailConfirmed = async({email}) => {
const sql = `UPDATE ${this.tableName} SET confirmed = true WHERE email = ?`
const result = await query(sql, email)
return result
}
[Error] Error: Incorrect arguments to mysqld_stmt_execute
this is the error I get when attempting to change the db.
I have this forgot password handler in my Express app. I send an email with a crypto.randomBytes(20).toString("hex") token, that I use later to verify the request. It is working perfectly.
However, I have seen that people are hashing this token before sending it and storing in the data base, and I don't see why, cause it is already a random string.
const forgotPassword = async (req, res) => {
try {
const user = await User.findOne({ email: req.body.email });
if (!user) {
throw Error("incorrect email");
}
const resetPasswordToken = crypto.randomBytes(20).toString("hex");
user.resetPasswordToken = resetPasswordToken;
user.resetPasswordTokenExpire = Date.now() + 10 * (60 * 1000);
await user.save();
const message = `
<h1>You have requested a password reset</h1>
<p>Here is your token : </p>
<p>${resetPasswordToken}</p>
`;
try {
await sendEmail({
to: user.email,
subject: "Password reset request",
text: message,
});
res.status(200).json({ message: "Email sent" });
} catch (err) {
user.resetPasswordToken = undefined;
user.resetPasswordTokenExpire = undefined;
res.status(500).json({ message: "Email could not be sent" });
}
} catch (error) {
console.log(error);
const errorDetails = handleErrors(error);
res.status(400).json(errorDetails);
}
};
If you hash the token and only save the hash into the database, you can make sure that admins and other people who are able to access the database cannot use the token to reset a password for a different user.
It's basically the same reason why you hash (and salt and pepper) passwords, because you don't want that the original string can be recreated whenever somebody has access to the table.
I am having trouble with my aftersave handler. So when a new user logs in, it checks to see of both tProfile and sProfile fields are empty, if so it saves saves an acl for the user and then sends an email to the user using nodemailer nmp package. But after a user is saved the server keeps on sending email after email in a loop, there were about 64 emails sent after which google blocked out the login attemps, help would be very appreciated. My cloud code is given below
Parse.Cloud.afterSave(Parse.User, (request) => {
const user = request.object;
const t = user.get('tProfile');
const s = user.get('sProfile');
if (!t && !s) {
user.setACL(new Parse.ACL(user));
user.save(null,{ useMasterKey: true });
sendWelcomeEmail(user.getUsername(),user.get('type'));
return;
}else{
console.log("Condition Working");
return;
}
});
const sendWelcomeEmail = (userName,type) => {
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'tanzim3421#gmail.com',
pass: 'oyhlyk****ocvhaa'
}
});
var mailOptions = {
from: 'tutorbeargroup#gmail.com',
to: userName,
subject: 'Welcome to TutorBear',
text: 'Dear '+type+', thankyou for signing up with us. If you have any questions please contact us at: 01726409161'
};
transporter.sendMail(mailOptions,(error, info)=>{
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
}
If you try to save same class object in afterSave it will be recursive function.
You can use beforeSave trigger
Parse.Cloud.beforeSave(Parse.User,async(req)=>{
let userObject = req.object;
if(userObject.isNew()){
//Your Logic
}
});
I'm trying to create a data entry on the firebase database to store additional information about a user when they register on my site.
I've tried to write data to the database in the .then() function following createUserWithEmailAndPassword() as that's the only way for me to extract the user id for the user (I'm hoping to use the uid as the key field of the record I create)
(req, res) => {
// extract user data from the form
const newUser = {
fname: req.body.fname,
lname: req.body.lname,
email: req.body.email,
pw: req.body.pw,
pw_c: req.body.pw_c
}
// carry out validation
const { valid, errors } = validateRegistrationData(newUser);
if (!valid) return res.status(400).json(errors);
// create new firebase user
firebase
.auth()
.createUserWithEmailAndPassword(newUser.email, newUser.pw)
.then(data => {
let uid = data.user.uid;
// make a database entry to store the users info
// by default, assumes that the user is a secondary user
let userData = {
fname: newUser.fname,
lname: newUser.lname,
email: newUser.email,
utype: 1,
createdon: admin.firestore.FieldValue.serverTimestamp(),
intitems: []
}
newUserDoc = db
.collection("users")
.doc(uid)
.set(userData)
return res.status(200).json("Success: new user created.");
})
.catch(err => {
if (err.code === "auth/email-already-in-use"){
return res.status(400).json({ email: "Email is already in use" });
} else {
return res.status(500).json({ error: err.code });
}
});
return res.status(200).json("Success: new user created.");
}
The server responds with {Success: new user created."}. The authentication part seems to work as a new user is created in the Authentication section of my firebase console. However, no new data entries appear in the users collection of my database.
.set returns a promise that still needs to run to completion. However, currently you're not waiting on the promise, and instead just responding via res.send.
You can append .then(() => { do stuff here }) to the end of .set. If it's the last thing you're doing in that function, you can just do res.send from there.
return db.collection("users").doc(uid).set(userData).then(() => {
return res.status(200).json("Success: new user created.");
})
.catch(error => {
console.log(error)
})
I have a login in my Angular 2 app, and I have been converting it from using a fake backend (which works) to connect to our mongoDB-based API instead.
This is the login function I am using in the authentication service:
login(username: string, password: string) {
const u = encodeURIComponent(username);
const p = encodeURIComponent(password);
this._url = `https://api.somesite.com/v0/staff/login/${u}/${p}?apikey=somekey`;
console.log(this._url);
return this.http.post(this._url, JSON.stringify({ username: username, password: password }))
.map((response: Response) => {
// login successful if there's a jwt token in the response
const user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
});
}
In my login component I am subscribing like this:
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(
data => {
this.router.navigate(['/']);
console.log('User logged in as: ' + this.model.username);
},
error => {
this.alertService.error(error);
this.loading = false;
});
this.authenticationService.username = this.model.username;
}
When I try this, and log to the console "this_url", I get what I would expect. For instance, if the user typed in "billsmith" for username, and "parisnow" for password, I see this in the console for "this_url":
https://api.somesite.com/v0/staff/login/billsmith/parisnow?apikey=somekey
Furthermore, I can type that url directly into the browser address window and see data (when the username and password correctly correspond to actual records in our database). So it's accessing the correct info in that sense.
But in the console I get a "404" error for that generated url. It also doesn't "do anything". In other words, it doesn't correctly redirect to the main component as it did with the fakeBackend-enabled login. And the only thing that's different now is the url that I am calling (because I'm connecting to our actual API now, as opposed to a fake backend provider).
FYI, the url when using the fake backend looked like this:
return this.http.post('/api/authenticate', JSON.stringify({ username: username, password: password}))
What am I missing here?
By the way, this is how things look on the server side re: our mongoDB:
exports.byLogin = function(req, res, next) {
let ioOnly = false, username, password;
if (_.isUndefined(req.params)){
ioOnly=true;
username = req.username;
password = req.password;
}
else {
username = req.params.username;
password = req.params.password;
}
staff.findOne({username: username, password: password}, function(err, doc) {
if (err) { if (!ioOnly) { return next(err) } else { return res(err)}}
else if(doc) ((!ioOnly) ? res.send(doc) : res(doc));
else ((!ioOnly) ? res.sendStatus(204) : res(doc));
});
};