My nodejs blog site wont show my current email in the Edit Settings page. It only shows the correct Name. For Email Edit User settings: it shows: [object Object] The correct email should show for each email from mongodb. Not sure if I need app.get and app.post as well.
app.js:
app.get('/editUserSettings', (req, res) => {
User.findOne({ email: req.body.email }, function(err, user) {
const email = User.findOne(req.body.email)
if (!err) {
res.render("editUserSettings", {
user: user, email: email
});
}
});
});
editUserSettings.ejs
<%- include("partials/header") -%>
<div class="ui main text container segment">
<div class="ui huge header">Edit my Profile </div>
<form class="ui form" action="/editUserSettings/<%= currentUser._id %>?_method=PUT" method="POST">
<div class="field">
<label>Name</label>
<input type="text" name="name" value="<%=currentUser%>" >
</div>
<div class="field">
<label>Email</label>
<input type="text" name="email" value="<%=email %>" >
</div>
<button class="ui violet basic button">Submit</button>
</form>
</div>
<%- include("partials/footer") -%>
your User.findeOne returns an object with your properties defined in the Schema and a unique id to your database entry, try a console.log(email) after the findOne line, it should log something like:
{
_id: XXXXXXXXXXXX,
email: example#youremail.de
}
also if you are using mongoose as a client for mongodb you need to async await your code because User.findOne returns a promise, maybe contact me on my discord lausnens#6598, there i could help you a bit better :)
Related
I am working on a website with MongoDB, Node.js and Express (no React or Angular). I have the user registration working fine. But my login is not working and I cannot figure out why. Below I post the relevant code:
index.js
/*
* Login Existing User
*/
const loginController = require("./controllers/login")
app.get('/auth/login', loginController);
const loginUserController = require('./controllers/loginUser')
app.post('/users/login', loginUserController)
/controllers/login:
module.exports = (req, res) => {
res.render('login')
}
relevant portion of login.ejs (which is rendered due to preceding code):
<form action="/users/login" method="POST" enctype="multipart/form-data">
<div class="form-floating">
<input class="form-control" id="username" type="text" placeholder="User Name" data-sb-validations="required" name = "username"/>
<label for="title">Username</label>
<div class="invalid-feedback" data-sb-feedback="title:required">A descriptive title is required.</div>
</div>
<div class="form-floating">
<input class="form-control" id="password" type="password" placeholder="Password" data-sb-validations="required" name="password"/>
<label for="name">Password</label>
<div class="invalid-feedback" data-sb-feedback="name:required">Password required.</div>
</div>
<br />
<!-- This is what your users will see when there is-->
<!-- an error submitting the form-->
<div class="d-none" id="submitErrorMessage"><div class="text-center text-danger mb-3">Error sending message!</div></div>
<!-- Submit Button-->
<button class="btn btn-primary text-uppercase" id="submitButton" type="submit">Login</button>
</form>
/controllers/loginUser:
const bcrypt = require('bcrypt')
const User = require('../models/User')
module.exports = (req,res) =>{
const { username,password } = req.body
User.findOne({username: username}, (error,user) => {
if(user){
bcrypt.compare(password, user.password, (error,same)=>{
if(same){
req.session.userId = user._id
res.redirect('/')
}
else{
res.redirect('/auth/login')
}
})
}
else{
console.log("/auth/login::",user)
res.redirect('/auth/login')
}
})
}
I have used Postman and also just tested in Chrome and Firefox and it appears that the GET made to /auth/login appears to work. I get there and I submit my form. But instead of redirecting me to my index or landing page ("/"), it just sends me back to /users/login and, also, the website doesn't recognize that I am logged in. Here is my code to trigger a Boolean if I am logged in:
global.loggedIn = null;
app.use("*", (req, res, next) => {
loggedIn = req.session.userId;
next()
});
Any thoughts/suggestions as to what I am doing wrong are appreciated.
So I have a form and in the form i ask the user to enter his phone number to be verified, and then his information will be inserted into DB with PHP queries.
I used this code:
var firebaseConfig = {
apiKey: "******",
authDomain: "*****",
databaseURL: "https://****",
projectId: "*****",
storageBucket: "",
messagingSenderId: "*****",
appId: "1:****:*****"
};
firebase.initializeApp(firebaseConfig);
// Create a Recaptcha verifier instance globally
// Calls submitPhoneNumberAuth() when the captcha is verified
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier(
"recaptcha-container",
{
size: "normal",
callback: function(response) {
submitPhoneNumberAuth();
}
}
);
// This function runs when the 'sign-in-button' is clicked
// Takes the value from the 'phoneNumber' input and sends SMS to that phone number
function submitPhoneNumberAuth() {
var phoneNumber = document.getElementById("phoneNumber").value;
var appVerifier = window.recaptchaVerifier;
firebase
.auth()
.signInWithPhoneNumber(phoneNumber, appVerifier)
.then(function(confirmationResult) {
window.confirmationResult = confirmationResult;
})
.catch(function(error) {
console.log(error);
});
}
// This function runs when the 'confirm-code' button is clicked
// Takes the value from the 'code' input and submits the code to verify the phone number
// Return a user object if the authentication was successful, and auth is complete
function submitPhoneNumberAuthCode() {
var code = document.getElementById("code").value;
confirmationResult
.confirm(code)
.then(function(result) {
var user = result.user;
console.log(user);
})
.catch(function(error) {
console.log(error);
});
}
//This function runs everytime the auth state changes. Use to verify if the user is logged in
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log("USER LOGGED IN");
} else {
// No user is signed in.
console.log("USER NOT LOGGED IN");
}
});
to verify the user's phone number. and in the form i used this :
<div class="verifyCon">
<div class="SMSBox Padding2">
<div>
<span class="Text3"> phone number </span>
</div>
<div>
<input class="InptText" type="tel" id="phoneNumber" maxlength="10" minlength="10" name="uphone" required>
</div>
<div>
<button type="button" class="SMSBut" onclick="submitPhoneNumberAuth()">
<h2 id="sign-in-button" class="Text2"> send </h2>
</button>
</div>
</div>
<div class="SMSBox Padding2">
<div>
<span class="Text3"> code </span>
</div>
<div>
<input class="InptText" type="text" id="code" name="code" maxlength="6" minlength="6" required>
</div>
<div>
<button type="button" class="SMSBut" onclick="submitPhoneNumberAuthCode()">
<h2 id="check-in-button" class="Text2"> check </h2>
</button>
</div>
</div>
</div>
My questions:
Is it secure? can the user get configuration info from the file? if so how to secure it?
Is there a way to make sure the user won't just submit the form without verifying the phone number?
Do I need to add ReCaptcha in the form page, or the one with auth will be enough?
I'm not good with JavaScript, so please any suggestions will be appreciated.
I've got a single page website and I'm trying to submit the 'subscribe to newsletter' form (which just has one input field, email) without refreshing the page but just sending feedback by using connect-flash flash messages.
Right now the page reloads and I get no flash message sadly.
Is there a way to achieve this without using AJAX and its preventDefault method?
Form
<div class="input-group">
<label class="sr-only" for="subscriber-email">Email address</label>
<input name="email" type="email" id="subscriber-email" class="form-control" placeholder="Email address" required>
<span class="input-group-addon">
<input id="subscribe-button" type="submit" class="btn btn-default" value="Join">
</span>
</div><!--/input-grpup-->
</form>
<!-- SUCCESS OR ERROR MESSAGES -->
<div id="subscription-response">
{{#if locals.messages.success}}
{{locals.messages.success}}
{{/if}}
</div>
Route
app.post('/', urlencodedParser, function(req, res){
var mailOpts, smtpTrans;
//send
smtpTrans.sendMail(mailOpts, function(error, info){
if (error) {
console.log(error);
} else {
req.flash('success', 'success message');
res.locals.messages = req.flash();
res.redirect('/');
}
});
});
I have a handlebars view that is a form set that I am trying to manipulate to populate the fields of the form with values if the user is using the form from my /edit/:annotation_id route. I originally thought something like passing an object, editMode: req.originalUrl and using that as the condition would work, but I have had no success. I'm curious as to what approach I should take to only show forms with populated values if it is coming from the /edit/:annotation_id route and then a blank form if it is not. Any suggestions?
routes:
appRoutes.route('/')
.get(function(req, res){
models.Annotation.findAll({
where: {
userId: req.user.user_id
},
attributes: ['annotationId', 'name'],
order: 'annotationDate DESC'
}).then(function(annotation){
res.render('pages/high-level-activity-feed.hbs',{
annotation: annotation,
user: req.user,
message: req.flash('Flash is back!')
});
})
})
.post(function(req, res){
models.Annotation.create({
name: req.body.name,
}).then(function() {
res.redirect('/app');
}).catch(function(error){
res.send(error);
})
});
appRoutes.get('/edit/:annotationId', function(req, res){
console.log('This is the url path ' + req.originalUrl);
models.Annotation.find({
where: {
userId: req.user.user_id,
annotationId: req.params.annotationId
},attributes: ['name']
}).then(function(annotation){
res.render('partials/edit-modal.hbs',{
annotation: annotation,
user: req.user,
editMode: req.originalUrl
});
})
});
annotation-form.hbs:
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h2>Add a new annotation</h2>
<div class="annotation-form">
{{#if editMode}}
<form action="/app/edit/{{annotation.annotationId}}" method="post">
<div class="annotation-form-header">
<img class="user-image" src="http://placehold.it/80x80" alt="Generic placeholder image">
<label for="annotation-date">name</label>
<input type="date" name="name" id="name" value="{{annotation.name}}">
</div>
<button type="submit" id="update-button">Update</button>
</form>
{{else}}
<form action="/app" method="post">
<div class="annotation-form-header">
<img class="user-image" src="http://placehold.it/80x80" alt="Generic placeholder image">
<label for="annotation-name">Name</label>
<input type="date" name="name" id="name">
</div>
<button type="submit" id="create-button">Create</button>
</form>
{{/if}}
</div>
</div>
</div>
I don't know about handlebars - but have you tried ejs integration with express?
There are only about four things you'd need to do to integrate it:
1. Add the following to your package.json and run npm install:
"ejs": "^2.3.4",
"express-ejs-layouts": "^2.0.0",
Update your app to use ejs:
var expressLayouts = require('express-ejs-layouts');
app.set('view engine', 'ejs');
Your render code can remain essentially unchanged - but here is a simplified version:
res.render('pages/test.ejs',{
editMode:true
});
Then update your view/html page with the ejs syntax:
<%if (editMode) { %>
in editMode your html looks like this
<%
}
else{
%>
In non editMode your html looks like this
<%}%>
app.post('/reset/:token', function(req, res) {
async.waterfall([
function(done) {
User.findOne({ 'local.resetPasswordToken' : req.params.token, 'local.resetPasswordExpires' : { $gt: Date.now() } }, function(err, user) {
if (!user) {
req.flash('resetMessage', req.params.token);
return res.redirect('back');
}
], function(err) {
res.redirect('/');
});
});
app.get('/reset/:token', function(req, res) {
User.findOne({ 'local.resetPasswordToken': req.params.token, 'local.resetPasswordExpires' : { $gt: Date.now() } }, function(err, user) {
if (!user) {
req.flash('forgotMessage', req.params.token );
return res.redirect('/forgot');
}
res.render('reset.ejs', { user: req.user, message: req.flash('resetMessage') });
});
});
<!--Reset.ejs page ResetPassword FORM -->
<form action="/reset/:token" method="post">
<div class="form-group">
<label>New Password</label>
<input type="text" class="form-control" name="newpassword">
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="text" class="form-control" name="confirmpassword">
</div>
<button type="submit" class="btn btn-warning btn-lg">Reset</button>
</form>
I able to get the token with req.params.token for the "post" after clicking
http://localhost:8080/reset/fed831abf73150c96f6a3e392b5cbdcaccdeb9bd
Later when I submit through the reset.ejs for the "get" I couldn't retrieved any token value with req.params.token.
Any solution to it?
I imagine that the original code for this might have come from http://sahatyalkabov.com/how-to-implement-password-reset-in-nodejs/. In this tut the jade templating engine is used and if you look at the reset.jade you will see that it starts with
form(method='POST')
but no action is defined. I don't really know jade but in your example you are using ejs and in your code you are setting the action to
form action="/reset/:token" method="post"
and as everybody has pointed out the route that you post to is exactly /reset/:token. So req.params will be :token and the reset will fail. What you need to do is post the url exactly as it appears in the get request. If you read
Is it a good practice to use an empty URL for a HTML form's action attribute? (action="")
you can see that you can amend your reset.ejs page code to read
form action="" method="post"
Now the post should have an action equal to the get url with the token in place and the reset should occur.
you need another form with method='get' and action='reset/' + tokenvar. Also your async waterfall does not call done() so will not call the redirect if the user exists