Can't upload picture to MongoDb from React frontend - javascript

I'm creating a tinder clone, I can create a user fine however I cant upload a picture. The error I get is ValidationError: User validation failed: pictures: Cast to embedded failed for value "'picture'" at path "pictures". I'm not sure what I'm doing wrong. The post request seems to fire as excepted with the payload however its when I login when I get the error. So I'm sure this has something to do with initial creation of the account.
create account front and back
import React, { useState } from "react";
import {useHistory } from "react-router-dom";
import axios from "axios";
const CreateAccount = () => {
const api = "http://localhost:5000/user/create-account";
const history = useHistory();
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [emailAddress, setEmailAddress] = useState("");
const [password, setPassword] = useState("");
const [gender, setGender] = useState("Male");
const [sexualPreference, setSexualPreference] = useState("Straight");
const [age, setAge] = useState("");
const [description, setDescription] = useState("");
const [picture, setPicture] = useState("");
const account = {
firstName: firstName,
lastName: lastName,
emailAddress: emailAddress,
password: password,
gender: gender,
sexualPreference: sexualPreference,
age: age,
description: description,
pictures: picture
};
console.log(account.gender);
console.log(account.sexualPreference);
console.log(account.pictures)
const submit = () => {
axios
.post(api, account)
.then((res) => {
console.log(res.data);
history.push({
pathname: "/",
});
})
.catch((err) => console.log(err));
};
const handleSubmit = (event) => {
event.preventDefault();
submit();
};
return (
<div>
<div>
<h1>Create account</h1>
</div>
<form onSubmit={handleSubmit} encType="multipart/form-data">
<p>First Name</p>
<input
id="firstName"
name="firstName"
type="firstName"
onChange={(e) => setFirstName(e.target.value)}
></input>
<p>Last Name</p>
<input
id="lastName"
name="lastName"
type="lastName"
onChange={(e) => setLastName(e.target.value)}
></input>
<p>Email Address</p>
<input
id="emailAddress"
name="emailAddress"
type="emailAddress"
onChange={(e) => setEmailAddress(e.target.value)}
></input>
<p>Password</p>
<input
id="password"
name="password"
type="password"
onChange={(e) => setPassword(e.target.value)}
></input>
<p>Gender</p>
<select
id="gender"
name="gender"
type="gender"
onChange={(e) => setGender(e.target.value)}
>
<option value="Male">Male</option>
<option value="Female">Female</option>
</select>
<p>Sexual Preference</p>
<select
id="sexualPreference"
name="sexualPreference"
type="sexualPreference"
onChange={(e) => setSexualPreference(e.target.value)}
>
<option value="Straight" >Straight</option>
<option value="Gay" >Gay</option>
<option value="Lesbian" >Lesbian</option>
<option value="Bisexual" >Bisexual</option>
</select>
<p>Age</p>
<input
id="age"
name="age"
type="age"
onChange={(e) => setAge(e.target.value)}
></input>
<p>Description</p>
<input
id="description"
name="description"
type="description"
onChange={(e) => setDescription(e.target.value)}
></input>
<input
type="file"
name="file"
id="picture"
onChange={(e) => setPicture(e.target.id)}
></input>
<button type="submit">Submit</button>
</form>
</div>
);
};
export default CreateAccount;
router.post( "/user/create-account", [
check("firstName")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "firstName"'),
check("lastName")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "username"'),
check("emailAddress")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "emailAddress"'),
check("password")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "password"'),
check("gender")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "gender"'),
check("sexualPreference")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "sexualPreference"'),
check("age")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "age"'),
check("description")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "description"'),
check("pictures")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "pictures"'),
],
asyncHandler(async (req, res, next) => {
// Attempt to get the validation result from the Request object.
const errors = validationResult(req);
// If there are validation errors...
if (!errors.isEmpty()) {
// Use the Array `map()` method to get a list of error messages.
const errorMessages = errors.array().map((error) => error.msg);
// Return the validation errors to the client.
return res.status(400).json({ errors: errorMessages });
}
//new user request body using mongo model from schema
const postUser = new User({
firstName: req.body.firstName,
lastName: req.body.lastName,
emailAddress: req.body.emailAddress,
password: req.body.password,
gender: req.body.gender,
sexualPreference: req.body.sexualPreference,
age: req.body.age,
description: req.body.description,
pictures: req.body.pictures
});
const userEmail = await User.findOne({
emailAddress: postUser.emailAddress,
});
if (postUser.emailAddress === userEmail) {
console.log("User with this email already exists");
return res.status(500).end();
} else if (postUser) {
//if true salts the password with bcryptjs
let salt = await bcryptjs.genSalt(10);
const hashPass = await bcryptjs.hash(postUser.password, salt);
console.log(hashPass);
postUser.password = hashPass;
postUser.save();
res.json({ postUser });
return res.status(201).end();
} else {
res.status(400).send({ error: "Error: Account not created" }).end();
}
})
);
mongoDb Schema
const mongoose = require('mongoose');
const userSchema = mongoose.Schema( {
firstName:{
type: String,
required: true
},
lastName: {
type: String,
require: true
},
emailAddress: {
type: String,
require: true
},
password:{
type: String,
required: true
},
gender:{
type: String,
required: true
},
sexualPreference: {
type: String,
required: true
},
age: {
type: Number,
required: true
},
description: {
type: String,
required: true
},
pictures: {
type: [{
picURL: String,
}],
},
matches: {
type: [{
Object
}],
},
})
module.exports = mongoose.model('User', userSchema);
login backend and frontend
router.post( "/login", asyncHandler(async (req, res, next) => {
const userBody = req.body;
const user = await User.findOne({ emailAddress: req.body.emailAddress });
if (userBody && user) {
console.log(user);
const authenticated = bcryptjs.compare(userBody.password, user.password);
console.log(authenticated);
if (authenticated) {
console.log("match");
const accessToken = jwt.sign(user.toJSON(), process.env.ACCESS_TOKEN_SECRET, { expiresIn: 86400 });
res.cookie("token", accessToken, { httpOnly: false, maxAge: 86400 });
res.setHeader('Authorization', 'Bearer '+ accessToken);
res.json({
user: user,
accessToken: accessToken,
})
.send()
} else {
res.status(403).send({ error: "Login failed: Please try again" }).end();
}
} else {
res.status(403).send({ error: "Login failed: Please try again" }).end();
}
})
);
import React, { useState} from "react";
import { useHistory } from "react-router";
import axios from "axios";
import { Link } from "react-router-dom";
const api = 'http://localhost:5000';
export default function Login () {
const history = useHistory();
const [ email, setEmail ] = useState("");
const [ pass, setPassword ] = useState("");
const submit = () => {
axios.post(`${api}/login`, { emailAddress: email, password: pass }, {withCredentials: true, credentials: 'include'})
.then(res => {
localStorage.setItem('jwt', res.data.accessToken);
history.push({
pathname: `/user/account/${res.data.user._id}`
});
})
.catch(err => console.log(err));
}
const handleSubmit = (event) => {
event.preventDefault();
submit()
}
return (
<div>
<h1>Login</h1>
<form onSubmit={handleSubmit}>
<input
id="emailAddress"
name="emailAddress"
type="text"
placeholder="emailAddress"
onChange={(e) => setEmail(e.target.value)}
/>
<input
id="password"
name="password"
type="password"
placeholder="Password"
onChange={(e) => setPassword(e.target.value)}
/>
<button type="submit">Submit</button>
<button >Cancel</button>
</form>
<p>Don't have a user account?
<Link to="/user/create-account" >Click here</Link>
to sign up!
</p>
</div>
);
}

first of all you can't upload image like this because you send regular http request if you want to send iamge you need to follow this steps
in the frontend you need to send the request with form data for more info read this blog from mdn what is formData mdn you can do something like that with axios append all of the req body to the formData and add it to the axios add multipart/form-data header
axios({
method: "post",
url: "myurl",
data: bodyFormData,
headers: { "Content-Type": "multipart/form-data" },
})
.then(function (response) {
// handle success
})
.catch(function (response) {
//handle error
});
in the server you need to upload-files-or-images-to-server-using-nodejs

Related

Try to Post data using fetch API in VUE 3 but its throwing custom error

I was trying to create user using vue and nodejs. I created a form which to get input and I have already set up my backend code. When I try to create User using Insomnia or postman, It work fine. But when I try to send data through fetch Api in vue after clicking the button. It just throw custom error.
Front End
Register.vue
<script setup>
import {ref,reactive, onMounted} from 'vue';
const user_data = reactive({
username: "",
email: "",
password: ""
})
const api_path = "http://localhost:8000/api/users";
const createUser = async () => {
try {
const response = await fetch(api_path, {
method: "POST",
mode: 'cors',
header: {
'Content-Type': 'application/json'
},
body: JSON.stringify({username: user_data.username, email: user_data.email, password: user_data.password}),
})
const data = await response.json();
console.log(data)
} catch(e) {
// statements
console.log(e);
}
}
</script>
<template>
<div class="container">
<form>
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" id="username" name="username" v-model="user_data.username" placeholder="Username">
</div>
<div class="form-group">
<label for="email">Email address</label>
<input type="email" class="form-control" id="email" name="email" aria-describedby="emailHelp" v-model="user_data.email" placeholder="Enter email">
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" name="password" v-model="user_data.password" placeholder="Password">
</div>
<button type="submit" #click.prevent="createUser" class="btn btn-primary">Create Account</button>
</form>
</div>
</template>
<style scoped>
.container{
margin-top: 50px;
}
</style>
Back End
UserModel.js
const {Schema,model} = require("mongoose");
const {isEmail} = require("validator");
const UserSchemaStructure = {
username: {
type: String,
unique: true,
lowercase: true,
required: [true, "Username is required"],
},
email: {
type: String,
unique: true,
lowercase: true,
required: [true, "Email is Required"],
validate: [isEmail, "Please enter valid Email"]
},
password: {
type: String,
required: [true, "Password is required"],
minlength: [8, "Password must be 8 characters long"]
}
}
const UserSchema = new Schema(UserSchemaStructure);
const UserModel = model("Users", UserSchema);
module.exports = UserModel;
UserController.js
const User = require("../models/Users");
const {authErrorHandler} = require("../utils/errorHandler");
const get_user = (req,res) => {
res.send("Get User")
}
const create_user = async (req,res) => {
const {username,email,password} = req.body;
try {
const user = await User.create({username,email,password});
res.status(201).json({user});
} catch(e) {
const errors = authErrorHandler(e);
res.status(300).json({errors});
}
}
module.exports = {
get_user,
create_user
}

How to display server-side validation messages in the client side via react-query?

Here is the Express route for the signup API call, It works as expected on the server-side but I want to display these same validation messages in real-time when the user will put their credentials on the React client
app.post("/signup", async (req, res) => {
try {
// Validate data before submission
const { error } = registerValidation(
req.body.username,
req.body.firstname,
req.body.lastname,
req.body.email,
req.body.password
);
if (error) return res.status(400).send(error.details[0].message);
// Checking if username already exists
const usernameExist = await database.query(
"SELECT username FROM users WHERE username=$1",
[req.body.username]
);
if (usernameExist.rows[0])
return res.status(400).send("Username already taken!");
// Checking if email already exists
const emailExist = await database.query(
"SELECT email FROM users WHERE email=$1",
[req.body.email]
);
if (emailExist.rows[0])
return res.status(400).send("Email already exists!");
// Hash the password
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(req.body.password, salt);
// Save the New User
const newUser = await database.query(
"INSERT INTO users(username, firstname, lastname, email, password) VALUES($1, $2, $3, $4, $5) RETURNING *",
[
req.body.username,
req.body.firstname,
req.body.lastname,
req.body.email,
hashedPassword,
]
);
res.json(newUser.rows[0]);
} catch (err) {
console.error(err.message);
}
});
And here is my fetch POST request for signup.
export const signUp = async (formData) => {
try {
const res = await fetch(`${API_URL}/signup`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(formData),
});
if (!res.ok) {
const errMsg = await res.text();
throw new Error(errMsg);
}
await res.json();
} catch (err) {
console.error(err.message);
}
};
And here is the signup form using react-hook-form and react-query, the error message is displayed on the console but wanted to display it on screen in real-time while the user typing in the form without the need to submit the form to display those messages.
import React from "react";
import { useForm } from "react-hook-form";
import { joiResolver } from "#hookform/resolvers/joi";
import Joi from "joi";
import { useMutation } from "react-query";
import { useHistory } from "react-router-dom";
import { signUp } from "../API/API";
// Signup Form Validation
const schema = Joi.object({
username: Joi.string().min(3).required(),
firstname: Joi.string().min(3).required(),
lastname: Joi.string().min(3).required(),
email: Joi.string()
.min(6)
.required()
.email({ tlds: { allow: false } }),
password: Joi.string().min(6).required(),
});
const SignupForm = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({ resolver: joiResolver(schema) });
const mutation = useMutation(signUp);
const history = useHistory();
// To submit data on server
const onSubmit = async (data) => {
// const res = await mutation.mutate(data);
// console.log(res);
await mutation.mutate(data);
history.push("/");
};
console.log(errors);
return (
<div>
<h3>Sign up</h3>
<form onSubmit={handleSubmit(onSubmit)}>
<input
type="text"
name="username"
placeholder="Username"
{...register("username", { required: true, min: 3 })}
/>
<p>{errors.username?.message}</p>
<br />
<input
type="text"
name="firstname"
placeholder="First Name"
{...register("firstname", { required: true, min: 3 })}
/>
<p>{errors.firstname?.message}</p>
<br />
<input
type="text"
name="lastname"
placeholder="Last Name"
{...register("lastname", { required: true, min: 3 })}
/>
<p>{errors.lastname?.message}</p>
<br />
<input
type="email"
name="email"
placeholder="Email"
{...register("email", {
required: true,
min: 6,
pattern: /^\S+#\S+$/i,
})}
/>
<p>{errors.email?.message}</p>
<br />
<input
type="password"
name="password"
placeholder="Password"
{...register("password", { required: true, min: 6 })}
/>
<p>{errors.password?.message}</p>
<br />
<button type="submit">Sign up</button>
</form>
</div>
);
};
export default SignupForm;
Please check with your syntax and all but did you check onError property?.
const { mutate } = useMutation(signUp, {
onSuccess: () => {
alert("successful");
},
onError: () => {
setStatus("there is an error");
},
});

User doesnt stay logged in when refreshing page NODE.js

Good day, I have made a login/register system, where the suer can login/logout and register.
I have made this with JWT and express.
Loggin in and logging out goes well, but when i refresh the page the user gets logged out. How could i fix this?
tokens
const { sign } = require("jsonwebtoken");
// const getToken = (user) => {
// return jwt.sign(
// // payload
// {
// _id: user._id,
// name: user.name,
// email: user.email,
// isAdmin: user.isAdmin,
// },
// process.env.JWT_SECRET,
// {
// expiresIn: '24h',
// }
// )
// }
const createAccessToken = userId => {
return sign(
{
userId,
},
process.env.ACCESS_TOKEN_SECRET,
{
//expire time
expiresIn: "15m",
},
);
};
//you can add versions of refresh tokens. So it only can be used once
const createRefreshToken = userId => {
return sign(
{
userId,
},
process.env.REFRESH_TOKEN_SECRET,
{
//expire time
expiresIn: "7d",
},
);
};
const sendAccessToken = (req, res, accesstoken) => {
res.send({
accesstoken,
email: req.body.email,
});
};
const sendRefreshToken = (res, refreshtoken) => {
//you can call it something different, so it
//will be harder to track which token it is
res.cookie("refreshtoken", refreshtoken, {
httpOnly: true,
path: "/refresh_token",
});
};
module.exports = {
createAccessToken,
createRefreshToken,
sendAccessToken,
sendRefreshToken,
};
Login route
router.post("/signin", async (req, res) => {
try {
const user = await User.findOne({
email: req.body.email,
});
if (!user)
res.status(400).send({
message: "User doesnt exist or password doesnt match",
});
const valid = await compare(req.body.password, user.password);
if (!valid) throw new Error("Invalid password");
const accesstoken = createAccessToken(user._id);
const refreshtoken = createRefreshToken(user._id);
sendRefreshToken(res, refreshtoken);
sendAccessToken(req, res, accesstoken);
res.send({
email: user.email,
refreshtoken: user.refreshtoken,
sendAccessToken: sendAccessToken(req, res, accesstoken),
refreshtoken,
});
} catch (err) {
res.send({
error: `${err.message}`,
});
}
});
generating new token route:
//generating new token
router.post("/refresh_token", (req, res) => {
const token = req.cookies.refreshtoken;
//if we dont have a token in our request
if (!token) return res.send({ accesstoken: "" });
//if we have token. Verify it
let payload = null;
try {
payload = verify(token, process.env.REFRESH_TOKEN_SECRET);
} catch (err) {
return res.send({ accesstoken: "" });
}
//token is valid. Check if user exist
const user = User.findOne(user => user._id === payload.userId);
if (!user) return res.send({ accesstoken: "" });
//user exists, check if refreshtoken exist on user
if (user.refreshtoken !== token) {
return res.send({ accesstoken: "" });
}
//token exist, create new refresh and accesstoken
const accesstoken = createAccessToken(user._id);
const refreshtoken = createRefreshToken(user._id);
//update refresh token in database
user.refreshtoken = refreshtoken;
//all good now, send refreshtoken and accesstoken
sendRefreshToken(res, refreshtoken);
return res.send({ accesstoken });
});
calling the refresh token
export const userContext = React.createContext([]);
function App() {
const [user, setUser] = useState({});
const [loading, setLoading] = useState(true);
const logoutCallback = async () => {
await fetch("http://localhost:5000/users/logout", {
method: "POST",
credentials: "include",
});
//clear user from context
setUser({});
//navigate back to startpage
alert("logged out");
};
useEffect(() => {
async function checkRefreshToken() {
const result = await (
await fetch("http://localhost:5000/users/refresh_token", {
method: "POST",
credentials: "include", //needed to include the cookie
headers: {
"Content-Type": "application/json",
},
})
).json();
setUser({
accesstoken: result.accesstoken,
});
setLoading(false);
}
checkRefreshToken();
}, []);
login page
import React, { useState, useEffect, useContext } from "react";
import { userContext } from "../../App";
function Login(props) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [user, setUser] = useContext(userContext);
const handleSubmit = async e => {
e.preventDefault();
const result = await (
await fetch("http://localhost:5000/users/signin", {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email,
password,
}),
})
).json();
if (result.accesstoken) {
setUser({
accesstoken: result.accesstoken,
refreshtoken: result.refreshtoken,
});
} else {
alert(result.error);
}
};
useEffect(() => {
console.log(user);
}, [user]);
return (
<div>
<h1 className="login-h">Login</h1>
<form onSubmit={handleSubmit} className="login">
<div className="login-form">
<label>email</label>
<br />
<input
type="email"
placeholder="username or email"
for="email"
onChange={e => setEmail(e.target.value)}
></input>
<br />
<label>Password</label>
<br />
<input
type="password"
placeholder="Password"
for="password"
onChange={e => setPassword(e.target.value)}
></input>
<br />
<p className="forget-pw">
Forgot password?
</p>
<button>Login</button> <br />
<br />
{/* <p style={{ color: 'red' }}>{result.error}</p> */}
</div>
<p className="have-ccl">
{" "}
No account yet?Signup
</p>
</form>
</div>
);
}
export default Login;

User input from form not posting to database? (axios ,mongodb, vue)

I am new to vue and I'm trying to post data from user input to my mongodb. I am using axios to retrieve and post data.
While the data from the db does show up on my page, I cannot get the form input to post. I'm not even getting any sort of error message, it is just not posting. I look forward to your response to let me know what I am doing wrong.
Here is my AddUser.vue page, from the client
<template>
<div>
<h1>Registration</h1>
<p>First name: </p>
<b-form-input v-model="firstname">
</b-form-input>
<p>Last name: </p>
<b-form-input v-model="lastname">
</b-form-input>
<p>Email: </p>
<b-form-input v-model="email">
</b-form-input>
<p>Password: </p>
<b-form-input v-model="password">
</b-form-input>
<br>
<button v-on:click="submitNew">Submit</button>
</div>
</template>
<script>
import UserService from "../UserService";
export default {
name: "UserEdit",
data(){
return {
editUsers: this.$route.query.user,
editStatus: "",
user: {}
}
},
methods: {
submitNew(){
try{
this.user = UserService.addUsers;
} catch (err) {
this.error = err.message;
}
this.cancel();
}
},
watch :{
$route: "updateRouter"
}
}
</script>
Here is my UserService.vue, from the client
import axios from "axios";
const mongoURL = "http://localhost:5000/api/posts";
class UserService{
static getUsers(){
return new Promise(async (resolve,reject)=> {
try{
const res = await axios.get(mongoURL);
const users = res.data;
resolve(
users.map((users) =>({
...users,
}))
);
} catch (err) {
reject (err);
}
});
}
static addUsers(user){
return axios.post(mongoURL, {
user
})
}
export default UserService;
Here is my model for Users.js, from the server
const mongoose = require('mongoose');
const User = mongoose.model("User",{
firstname: {
type: String,
required: true,
trim: true
},
lastname: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
trim: true
},
password: {
type: String,
required: true
}
})
module.exports = User;
Here is my posts.js, from the server
const express = require("express"),
mongoose = require("mongoose"),
User = require("../models/Users.js"),
router = express.Router();
router.get("/", async (req,res)=>{
try {
const user = await User.find({});
res.send(user);
} catch (error){
res.status(500).send(error);
}
});
router.post("/", async(req,res)=>{
console.log(req.body["user"]);
const user = new User(req.body["user"])
console.log(user);
try{
await user.save
console.log(user)
} catch(err){
res.status(550).send(err);
}
})
module.exports = router;
<template>
<div>
<h1>Registration</h1>
<p>First name: </p>
<b-form-input v-model="user.firstname">
</b-form-input>
<p>Last name: </p>
<b-form-input v-model="user.lastname">
</b-form-input>
<p>Email: </p>
<b-form-input v-model="user.email">
</b-form-input>
<p>Password: </p>
<b-form-input v-model="user.password">
</b-form-input>
<br>
<button v-on:click="submitNew">Submit</button>
</div>
</template>
<script>
import UserService from "../UserService";
export default {
name: "UserEdit",
data() {
return {
editUsers: this.$route.query.user,
editStatus: "",
user: {}
}
},
methods: {
submitNew() {
try {
this.user = UserService.addUsers(this.user);
} catch (err) {
this.error = err.message;
}
this.cancel();
}
},
watch: {
$route: "updateRouter"
}
}
</script>

How can I check if the users Password is the same as the user typed in the input of oldPassword?

So, I basically wannt to check if the user's Password is the same as the password the user typed into the "oldPassword" input field. The problem I have is how I am suppose to check, cause apparently I have to hash, what the user typed into the input "oldPassword". How can I go about doing this, and please also check my ejs file and what you think? I got new password there as well, THIS IS FOR THE USER TO CHANGE IT'S OLD PASSWORD TO A NEW ONE BY THE WAY*
exports.postChangedPassword = async (req, res) => {
const {
oldPassword,
newPassword,
confirmNewPassword
} = req.body;
try {
const userId = await req.params.userId;
const user = await User.findById(userId)
const oldHashedPassword = await bcrypt.hash(oldPassword, 10);
if (user.password === oldHashedPassword && newPassword === confirmNewPassword) {
const hashedPassword = await bcrypt.hash(newPassword, 10);
user.password = hashedPassword;
user.save();
console.log(user);
res.render("admin/settings/appliedSettings/changed-password", {
pageTitle: "Succesfully Changed Password",
path: "/settings/changed-password",
user: user
})
}
} catch (error) {
console.log(error);
req.flash("error", "Password do not match!");
res.redirect("/settings/password");
}
}
model.js
const mongoose = require("mongoose"),
Schema = mongoose.Schema,
bcrypt = require("bcryptjs");
const postSchema = new Schema({
title: String,
description: String,
context: String,
author: {
type: Schema.Types.ObjectId,
}
});
const userSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true
},
posts: [postSchema]
});
userSchema.pre("save", async function save(next) {
const user = this;
if (!user.isModified("password")) return next();
const hashedPassword = await bcrypt.hash(user.password, 10);
user.password = hashedPassword;
next();
});
const Post = mongoose.model("Post", postSchema);
const User = mongoose.model("User", userSchema);
module.exports = {
User,
Post
}
change-password.ejs
<% if (errorMessage) { %>
<div class="user-message-error"> <%= errorMessage %> </div>
<% } %>
<form class="change-password" action="/settings/changed-password/<%=user._id%>" method="POST">
<label for="password">Old Password</label>
<input type="password" name="oldPassword" placeholder="Enter Your Old Password ..." required>
<label for="password">Your New Password</label>
<input type="password" name="newPassword" placeholder="Enter Your New Password ..." required>
<label for="password">Confirm Your New Password</label>
<input type="password" name="confirmNewPassword" placeholder="Confirm Your Password ..." required>
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button type="submit">
Submit Password
</button>
</form>
admin route
router.post("/settings/changed-password/:userId", adminController.postChangedPassword);
To check whether the password changed, just hash the new password and compare the hashed value to the old one:
const oldHashedPassword = await bcrypt.hash(oldPassword, 10);
const newHashedPassword = await bcrypt.hash(newPassword, 10);
if (
user.password === oldHashedPassword &&
newPassword === confirmNewPassword &&
oldHashedPassword !== newHashedPassword
) {
user.password = newHashedPassword;
user.save();
console.log(user);
res.render("admin/settings/appliedSettings/changed-password", {
pageTitle: "Succesfully Changed Password",
path: "/settings/changed-password",
user: user
})
}
It doesn't matter whether you check against user.password or oldHashedPassword, since you established that they are the same thing in the first condition

Categories

Resources