Update user profile page using mongoose express js - node.js

I am working on personal project. one of common functionality i am implementing is allowing users to update their profile but having hard time doing it.
here is what i did so far
form
<form
action="/users/doctor-profile?_method=PUT"
method="POST"
enctype="multipart/form-data"
>
<input type="hidden" name="_method" value="PUT" />
<div class="form-group">
<input
type="text"
class="form-control"
id="name"
name="name"
/>
</div>
<div class="form-group">
<label for="phone">Phone</label>
<input
type="tel"
class="form-control"
id="formGroupExampleInput"
name="phone"
/>
</div>
<div class="form-group">
<label for="exampleInputEmail1">Email</label>
<input
type="email"
class="form-control"
id="formGroupExampleInput"
name="email"
/>
</div>
<button type="submit" class="btn btn-primary">Save changes</button>
</form>
here is my user model
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
phone: {
type: String,
required: true,
},
});
const User = mongoose.model("User", UserSchema);
module.exports = User;
here is my post route
router.post("/users/doctor-profile", (req, res) => {
const { name, email,phone } = req.body;
const _id = ObjectId(req.session.passport.user._id);
console.log(_id)
USer.findOne({ _id: _id })
.then((user) => {
if (!user) {
req.flash("error_msg", "user not found");
res.redirect("/users/doctor-profile");
}
if (typeof name !== "undefined") {
user.name = name;
console.log(user.name);
}
if (typeof email !== "undefined") {
user.email = email;
}
if (typeof phone !== "undefined") {
user.phone = phone;
}
user.save().then((User) => {
req.flash("success_msg", "details updated successfully");
res.redirect("/users/profile");
});
})
.catch((err) => console.log(err));
});
console output
application running on port 5000
mongodb connection successfull
5ef5bc20261beb1e6c1c25a3
but it does not update fields in database.

try this:
user.save(function (err, resolve) {
if(err)
console.log('db error', err)
// saved!
});

You had a typo in your post route js file
here is the code you got the typo on:
USer.findOne({ _id: _id })
USer should be User

Related

How to login to a page using mongoDB post request isnt recognized?

Hi there im having difficulty with my post request for login,
I've managed to get register working and i redirect it to login so i can attempt, the account registered goes onto mongodb correctly, from some testing with multiple logs, turns out the post for login isnt effecting it, and it simply redirects again to login, unsure how that is
heres what i got
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
}
})
module.exports = mongoose.model('users', userSchema)
This is for where im storing the users info for the login page
<h1>Login</h1>
<form action="/login" method="GET">
<div>
<label for="name">Name</label>
<input type="name" id="name" name="name" required>
</div>
<div>
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">Login</button>
</form>
Register a User
Register is the same as this only with the href relating to this login page
const express = require('express')
const router = express.Router()
const users = require('../models/users')
const book = require('../models/book')
router.get('/home', async (req, res) => {
let books
try {
books = await book.find().sort({ createdAt: 'desc' }).limit(10).exec()
} catch {
books = []
}
res.render('home.ejs', { books: books })
})
//Login user
router.get('/', (req, res) => {
res.render('index.ejs')
})
router.get('/login', async (req, res) => {
res.render('login')
})
router.post('/login', async (req, res) => {
console.log("HI")
try{
const valid=await users.findOne({name:req.body.name})
if (valid.password===req.body.password){
res.render('home')
}
else{
console.log("HI")
res.send("Incorrect Password Try again?")
res.render('home')
}
}catch{
console.log("HI")
res.render('home')
}
})
//Register and upload to DB
router.post('/', async (req, res) => {
const user = ({
name: req.body.name,
email: req.body.email,
password: req.body.password,
})
await users.insertMany([user])
res.redirect('/')
})
module.exports = router
In your form you have mentioned method as "GET" . It is a post request so method should be "POST".
<form action="/login" method="post">

I'm trying to add users to my MongoDB database

I want to add a user to my database. But I couldn't add a user.I played on the user schema as much as I could, but I still couldn't get a record in the database. What should I do?
//routes/user.js
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const config = require('config');
const User=require('../models');
const { check, validationResult } = require('express-validator');
const User = require('../models/User');
// #route POST api/users
// #dsc Register a user
// #access Public
router.post(
'/',
[
check('name', 'Please add a name').notEmpty(),
check('email', 'Please include a valid email').isEmail(),
check(
'password',
'Please Enter a password for 6 or more characters'
).isLength({ min: 6 }),
check('address', 'Please include a valid address').notEmpty(),
check('location', 'Please include a valid location').notEmpty(),
check('phone', 'Please include a valid number').isLength(10),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { name, email, password, address, location, phone } = req.body;
try {
let user = await User.findOne({ email });
if (user) {
return res.status(400).json({ msg: 'User already exists' });
}
user = new User({
name,
email,
password,
address,
location,
phone,
});
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
await user.save();
const payload = {
user: {
id: user.id,
},
};
jwt.sign(
payload,
config.get('jwtSecret'),
{
expiresIn: 3600000,
},
(err, token) => {
if (err) throw err;
res.json({ token: token, userId: user.id }rot);
}
);
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
}
);
module.exports = router;
//frontend user.js
import React, { Component } from "react";
import { Redirect, Link } from "react-router-dom";
import Home from "./Home";
import "./signup.css";
import img from "./cart-removebg-preview.png";
import img1 from './WhatsApp Image 2020-09-18 at 17.35.32.jpeg';
import Axios from "axios";
import { localsName } from "ejs";
class Signup extends Component {
constructor(props) {
super(props);
this.signup = this.signup.bind(this);
this.handleChange = this.handleChange.bind(this);
this.state = {
email: "",
password: "",
name: "",
phone: "",
address: "",
location: "",
valid: false,
userId: "",
};
}
signup = async (e) => {
e.preventDefault();
await Axios.post("/api/users", {
name: this.state.name,
email: this.state.email,
password: this.state.password,
address: this.state.address,
location: this.state.location,
phone: this.state.phone,
})
.then((res) =>
this.setState({ valid: res.data.token, userId: res.data.userId })
)
.catch((err) => console.log(err));
};
handleChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
render() {
if (this.state.valid) {
localStorage.setItem("token", this.state.valid);
localStorage.setItem("userId", this.state.userId);
}
if (this.state.valid) return <Redirect to="/"></Redirect>;
return (
<div className='signup'>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="/">Stud-Shop</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ml-auto">
<li className="nav-item">
<i className="fas fa-home"></i>
</li>
<li className="nav-item">
Login
</li>
</ul>
</div>
</nav>
<img src={img} className='mobSignup'/>
<div className="row">
<div className="col-lg-3 bg-white rounded ">
<div className='card'>
<form>
<div className="form-group">
<h3>Sign-Up</h3>
<label htmlFor="exampleInputEmail1"><i class=" fa-lg fas fa-envelope"></i></label>
<input
type="email"
name="email"
className="form-control"
aria-describedby="emailHelp"
placeholder="Email-Address"
value={this.state.email}
onChange={this.handleChange}
></input>
<small className="form-text text-muted">
we'll never share your email with anyone!
</small>
<label><i class=" fa-lg fas fa-key"></i></label>
<input
value={this.state.password}
name="password"
type="password"
placeholder="Password (Min Length-6)"
className="form-control"
aria-describedby="emailHelp"
onChange={this.handleChange}
></input>
<label><i class=" fa-lg fas fa-user"></i></label>
<input
type="text"
name="name"
className="form-control"
placeholder="Name"
aria-describedby="emailHelp"
onChange={this.handleChange}
value={this.state.name}
></input>
<label><i class=" fa-lg fas fa-phone"></i>.</label>
<input
value={this.state.phone}
name="phone"
type="Number"
placeholder="Ph No. (Ex-98765XXXXX)"
className="form-control"
aria-describedby="emailHelp"
onChange={this.handleChange}
></input>
<label><i class=" fa-lg fas fa-home"></i></label>
<input
value={this.state.address}
type="text"
name="address"
className="form-control"
placeholder="Address"
aria-describedby="emailHelp"
onChange={this.handleChange}
></input>
<label><i class=" fa-lg fas fa-map-marked"></i></label>
<input
value={this.state.location}
type="text"
name="location"
className="form-control"
placeholder="Location (City)"
aria-describedby="emailHelp"
onChange={this.handleChange}
></input>
</div>
<button
type="submit"
onClick={this.signup}
className="btn btn-primary"
>
Sign-Up <i className=" fas fa-check"></i>
</button>
</form>
</div>
</div>
<div className='col-lg-8'>
<img src={img} className='signupImg'/>
</div>
</div>
</div>
);
}
}
export default Signup;
//model.js
const mongoose = require('mongoose');
const UserSchema = mongoose.Schema({
name: {
type: String,
required: true,
},
address: {
type: String,
required: true,
},
location: {
type: String,
required: true,
},
phone: {
type: Number,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
date: {
type: Date,
default: Date.now,
},},
{
collection:"Users"}
);
const model = mongoose.model('UserSchema', UserSchema)
module.exports = model
database connection is established. I tried to get the code from outside, but when I tried it with my code, it didn't work. What should I do? Can you help me?

System validation failed - Node / Express / Mongoose

When I submit my form I get the following error: Error [ValidationError]: System validation failed: lastName: Path lastName is required., firstName: Path firstName is required.
I'm not sure what's causing this, when I console.log(formData) I get the data I submitted into the form.
App.js
const express = require('express')
const app = express();
const mongoose = require('mongoose');
const dotenv = require ('dotenv/config');
const System = require('./models/System');
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.get('/', (req,res) => {
res.render('index.ejs');
});
app.post('/post-feedback', (req, res) => {
const formData = {
firstame: req.body.firstName,
lastname: req.body.lastName,
assetTag: req.body.assetTag
}
const system = new System(formData);
system.save()
.then(result => {
console.log(result);
})
.catch(err => {
console.log(err);
});
});
Model:
const mongoose = require('mongoose');
var SystemSchema = new mongoose.Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
assetTag: {
type: Number,
required: true
}
});
module.exports = mongoose.model('System', SystemSchema);
Form:
<form action="/post-feedback" method="POST">
<div class="form-group">
<label for="firstName">First Name: </label>
<input type="text" class="form-control" id="firstName" name="firstName">
</div>
<div class="form-group">
<label for="lastName">Last Name: </label>
<input type="text" class="form-control" id="lastName" name="lastName">
</div>
<div class="form-group">
<label for="assetNum">Asset Tag: </label>
<input type="text" class="form-control" id="assetTag" name="assetTag">
</div>
<button type="submit" name="submit" class="btn btn-primary">Submit</button>
</form>
The only one reason why you got some error it's because you're typo on your formData. It must be firstName and lastName, make sure it same with your Schema field and then Make Sure your assetTag is a number, because your Schema type is number.
You can try with this code below:
app.post('/post-feedback', (req, res) => {
const formData = {
// you're typo here: firstame
firstName: req.body.firstName,
// you're typo here: lastname
lastName: req.body.lastName,
// must be number
assetTag: parseInt(req.body.assetTag);
}
const system = new System(formData);
system.save()
.then(result => {
console.log(result);
})
.catch(err => {
console.log(err);
});
});
I hope it can help you.
app.post('/post-feedback', (req, res) => {
const system = new System(req.body);
system.save()
.then(result => {
console.log(result);
})
.catch(err => {
console.log(err);
});
});
i think above code should be work.

How to set an admin password with passport node

This website is only going to have admin users, I have created the schema, the registration view and the route, however something is bad with the logic in the route.
/register page only have three inputs, username, password and email address. At the moment, if the user uses any random password to enter, is showing a flash error saying the password is not valid and redirecting me to the landing page, however, it is still creating the new user in the database.
Also, if the user uses the right password same thing as above is happening.
What am I doing wrong?
here is my code:
Schema
var UserSchema = new mongoose.Schema({
username: {
type: String,
unique: true,
required: true
},
password: {
type: String
},
email: {
type: String,
unique: true,
required: true,
lowercase: true,
},
resetPasswordToken: String,
resetPasswordExpires: Date,
// isAdmin: {type: Boolean, default: false, required:true}
});
Register view
<form class="form-group" action="/register" method="POST">
<div class="form-group">
<input class="form-control mb-1" type="text" name="username">
</div>
<div class="form-group">
<input class="form-control mb-3" type="password" name="password">
</div>
<div class="form-group">
<input class="form-control" type="email" name="email">
</div>
<button class="btn btn-outline-info w-100">Register!</button>
</form>
Route
// register route
router.get("/register", function(req, res) {
res.render("register", {page: "register"});
});
// handle sign up logic
router.post("/register", function(req, res){
var newUser = new User({
username: req.body.username,
email: req.body.email
});
User.register(newUser, req.body.password, function(err, user){
if(err){
console.log(err);
return res.render("register", {error: err.message});
} else {
if(req.body.password !== process.env.ADMIN_CODE) {
req.flash('error', 'the password is not valid');
res.redirect("/");
} else {
passport.authenticate("local")(req, res, function(){
req.flash("success", "Great! Welcome! " + req.body.username);
res.redirect("/");
});
}
}
});
});

Passport local auth plus passport mongoose local are not accepting email as username

I am using passport local strategy and passport mongoose local to create a user and check user authentication. However, I wanted to explore the option using email instead of username. I followed what the document says and I am getting unauthorized. Can someone tell me why I am getting an error, and it works if I just use the username as login.
From passport-local-mongoose
Note: usernameField: specifies the field name that holds the username. Defaults to 'username'. This option can be used if you want to use a different field to hold the username for example "email".
And from passport local strategy
By default, LocalStrategy expects to find credentials in parameters named username and password. If your site prefers to name these fields differently, options are available to change the defaults.
I have tried to set both true at the same time and I also have tried to set one true and another one off. I will get the same error
express 4.16.0
express-session 1.15.6
mongoose 5.1.2
passport 0.40
passport local 1.0.0
passport local mongoose 5.0.0
passport.js
module.exports = function (passport, LocalStrategy, User) {
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true,
session: true
},
function(req, username, password, done) {
return done(null, req.user);
}
));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
};
model/User.js
var UserSchema = new mongoose.Schema({
name: { type: String, required: true, default: ''},
username: { type: String, unique: true, uniqueCaseInsensitive: true, required: true, default: ''},
email: { type: String, required: true, unique: true, uniqueCaseInsensitive: true, default: ''},
profileImage:{ type: String, default: ''},
timestamp: {type: String, default: () => moment().format("dddd, MMMM Do YYYY, h:mm:ss a") }
});
UserSchema.plugin(passportLocalMongoose, {usernameField: 'email'});
UserSchema.plugin(uniqueValidator);
module.exports = mongoose.model('UserSchema', UserSchema);
signinForm.js
<form class="form-signin" action="/users/signup" method="POST" enctype='multipart/form-data'>
<h1 class="h3 mb-3 font-weight-normal">Please sign up</h1>
<label for="inputName" class="sr-only">Name</label>
<input type="bane" id="inputName" class="form-control" placeholder="Name" name='name' required autofocus />
<label for="inputUsername" class="sr-only">Username</label>
<input type="bane" id="inputUsername" class="form-control" placeholder="Username" name='username' required autofocus />
<label for="inputEmail" class="sr-only">Email</label>
<input type="email" id="inputEmail" class="form-control" placeholder="Email" name='email' required autofocus />
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" id="inputPassword" class="form-control" placeholder="Password" name='password' required autofocus/>
<label for="inputConfirmPassword" class="sr-only">Confirm Password</label>
<input type="password" id="inputConfirmPassword" class="form-control" placeholder="Confirm Password" name='confirmPassword' required autofocus/>
<input type='file' class='form-control' id='inputFile' name='profileImage' />
<div style="height: 10px"></div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
</form>
routes/users.js
router.post('/signup', upload.single('profileImage'), function(req, res, next) {
const name = req.body.name;
const email = req.body.email;
const password = req.body.password;
const confirmPassword = req.body.confirmPassword;
if (req.file) {
console.log('Uploading File...');
var profileImage = req.file.filename;
} else {
console.log('No File Uploaded... Setting to no image');
var profileImage = 'noimage.jpg';
}
UserController.createUser(req.body, function(err, user) {
if (err) {
res.json({
err: err
});
return;
}
passport.authenticate('local')(req, res, function() {
//res.render('index', {currentUser: user, title: 'Product Page' });
res.redirect('/');
return;
});
return;
})
});
I ended up getting authorized and 401
Thanks in advance.
Try to remove the 'return' at the end of UserController.createUser(), you need to wait for the result of passport.authenticate()

Resources