Im trying to make a user profile page where a user can follow another user.
my routes are fine
but then i wanted to ask is if a user clicks on follow. Only the unfollow button will be shown. if i unfollow the follow button will be shown.
these are my codes
router.get('/follow/:id', isLoggedIn, async function(req, res, next) {
try {
const user = await User.findById(req.params.id);
if (!user) {
req.flash("error", "User does not exist");
res.redirect('back')
return res.status(404).json({ error: 'User does not exist' });
}
if (user.followers.indexOf(req.user.id) !== -1) {
req.flash("error",`You're already following ${user.local.username}` )
res.redirect('back')
return res.status(400).json({ error: `You're already following
${user.local.username}` });
}
user.followers.addToSet(req.user.id);
await user.save();
const users = await User.findById(req.user.id);
users.following.addToSet(user.id);
await users.save();
req.flash("success", "User added")
return res.redirect('back')
} catch (err) {
return next(err);
}
});
router.delete('/follow/:id', isLoggedIn, async function(req, res) {
try {
const user = await User.findById(req.params.id);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
const following = user.followers.indexOf(req.user.id);
if (following === -1) {
return res.status(400).json({ error: `You're not following
${user.username}` });
}
user.followers.splice(following, 1);
await user.save();
const userLogged = await User.findById(req.user.id);
const positionUnfollow = userLogged.following.indexOf(user.id);
userLogged.following.splice(positionUnfollow, 1);
await userLogged.save();
req.flash('success', `You have sucessfully unfollowed
${user.local.username || user.facebook.name}`)
return res.redirect("back");
} catch (err) {
return next(err);
}
});
my ejs page
<div class="follow justify-content-center">
<% user.followers.forEach(function(follower) { %>
<% if(currentUser && currentUser._id.equals(follower.id)) { %>
<form id="delete-btn" action="/users/follow/<%= user.id%>?
_method=DELETE" method="POST">
<button class="btn btn-danger"><i class="fas fa-user-slash">
</i></button>
</form>
<% } %>
<% }) %>
</div>
<% user.following.forEach(function(follow) { %>
<% if(currentUser && follow._id !== user._id) {%>
<a href="/users/follow/<%= user.id %>"><button class="btn btn-
primary">
<i class="fas fa-user-plus"></i></button></a>
<% } %>
<% }) %>
<div class="card-footer text-center">
<div class="social-media">
<i class="fab fa-facebook"></i>
<i class="fab fa-twitter-square"></i>
<i class="fab fa-instagram"></i>
</div>
</div>
</div>
</div>
my user schema
followers: [
{
type: mongoose.Schema.ObjectId, ref: 'User'
}
],
following: [
{ type: mongoose.Schema.ObjectId, ref: 'User'
}
],
the problem now is if i follow a user the unfollow button will appear but the follow button won't go away.
also if i did a <%=user._id%> and <%=follow.id%> the values are the same but not sure why the environment variables didn't work.
Related
This question already exists:
I can't login in my project written in react and node.js
Closed 4 months ago.
I am getting error while logging in nodejs.I can't follow errors from the console reset when I press the enter key.in my login.js file
// catch(err) .can you help me i couldn't find the reason.I have no idea what to do?When I press the login button, it gives an error warning directly.What is the situation that caused the error? How can I find out?
const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const config = require('config');
const auth = require('../middleware/auth');
const { check, validationResult } = require('express-validator');
const User = require('../models/User');
const router = express.Router();
// #route GET api/auth
// #dsc Get logged in user
// #access Private
router.get('/', auth, async (req, res) => {
try {
const user = await User.findById(req.user.id).select('-password');
res.json(user);
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
});
// #route POST api/auth
// #dsc Auth user & get token
// #access Public
router.post(
'/',
[
check('email', 'Please include a valid email').isEmail(),
check('password', 'Password is required').exists(),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
}
const { email, password } = req.body;
try {
let user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ msg: 'Invalid Credentials' });
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ msg: 'Invalid Credentials' });
}
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,
});
}
);
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
}
);
// #route GET api/getUser/:id
// #dsc get user with uid
// #access Public
router.get('/getUser/:id', async (req, res) => {
try {
const user = await User.findById(req.params.id).select('-password');
res.json(user);
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
});
module.exports = router;
login.js
import React, { Component, useEffect } from "react";
import { Route, Redirect, Link } from "react-router-dom";
import "./Login.css";
import imgB from "./WhatsApp Image 2020-09-07 at 11.17.14.jpeg";
import img from "./cart-removebg-preview.png";
import Axios from "axios";
class Login extends Component {
constructor(props) {
super(props);
this.login = this.login.bind(this);
this.handleChange = this.handleChange.bind(this);
this.state = {
email: "",
password: "",
errMessage: " ",
valid: false,
userId: "",
};
}
errMessage = " ";
login = async (e) => {
e.preventDefault();
try{
const { data } = Axios.post("/api/auth", {
email: this.state.email,
password: this.state.password,
})
this.setState({
...this.state,
valid: data.token,
userId: data.userId
}) }
catch(err) {
alert("hata");
window.location.reload();
console.log(err);
};
console.log(localStorage.getItem("token"));
};
handleChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
/* change() {
this.setState({ valid: true });
} */
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="image1">
<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">
Sign Up
</li>
</ul>
</div>
</nav>
<img src={img} className='mobSignup'/>
<div className="row">
<div className="desk col-lg-3 login bg-white rounded">
<h3>Log-In</h3>
<form>
<label><i className="fas fa-envelope fa-lg"></i></label>
<input
type="email"
className="form-control"
aria-describedby="emailHelp"
id="email"
name="email"
placeholder="Email-Address"
onChange={this.handleChange}
value={this.state.email}
/>
<label><i className="fas fa-key fa-lg"></i></label>
<input
name="password"
type="password"
className="form-control"
aria-describedby="emailHelp"
onChange={this.handleChange}
id="password"
placeholder="Password (Min Length-6)"
value={this.state.password}
/>
<button onClick={this.login} className="btn btn-primary">
Login <i className="fas fa-sign-in-alt"></i>
</button>
<Link to="/signup">New User? Signup here!</Link>
</form>
<p className="para">{this.state.errMessage}</p>
</div>
<div className='col-lg-8'>
<img src={img} className='signupImg'/>
</div>
</div>
</div>
);
}
}
export default Login;
new here and a very very green react and node dev. My question is as follows:
Automatic login upon user registration
I believe this require the API to generate and send a JWS token to the front end. I've a vague idea of what needs to happen but the particulars of how to go about this elude me.
auth controller:
const db = require("../models");
const User = db.user;
const Role = db.role;
var jwt = require("jsonwebtoken");
var bcrypt = require("bcryptjs");
exports.signup = (req, res) => {
const user = new User({
username: req.body.email,
firstname: req.body.firstname,
lastname: req.body.lastname,
email: req.body.email,
password: bcrypt.hashSync(req.body.password, 8),
});
user.save((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
if (req.body.roles) {
Role.find(
{
name: { $in: req.body.roles },
},
(err, roles) => {
if (err) {
res.status(500).send({ message: err });
return;
}
user.roles = roles.map((role) => role._id);
user.save((err) => {
if (err) {
res.status(500).send({ message: err });
return;
}
res.send({ message: "User was registered successfully!" });
});
}
);
} else {
Role.findOne({ name: "user" }, (err, role) => {
if (err) {
res.status(500).send({ message: err });
return;
}
user.roles = [role._id];
user.save((err) => {
if (err) {
res.status(500).send({ message: err });
return;
}
res.send({ message: "User was registered successfully!" });
});
});
}
});
};
exports.signin = (req, res) => {
User.findOne({
email: req.body.email,
})
.populate("roles", "-__v")
.exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
if (!user) {
return res.status(404).send({ message: "User Not found." });
}
var passwordIsValid = bcrypt.compareSync(
req.body.password,
user.password
);
if (!passwordIsValid) {
return res.status(401).send({ message: "Invalid Password!" });
}
var token = jwt.sign({ id: user.id }, config.secret, {
expiresIn: 86400, // 24 hours
});
var authorities = [];
for (let i = 0; i < user.roles.length; i++) {
authorities.push("ROLE_" + user.roles[i].name.toUpperCase());
}
req.session.token = token;
res.status(200).send({
id: user._id,
username: user.username,
firstname: user.firstname,
lastname: user.lastname,
email: user.email,
roles: authorities,
});
});
};
exports.signout = async (req, res) => {
try {
req.session = null;
return res.status(200).send({ message: "You've been signed out!" });
} catch (err) {
this.next(err);
}
};
auth jwt:
const config = require("../config/auth.config.js");
const db = require("../models");
const User = db.user;
const Role = db.role;
verifyToken = (req, res, next) => {
let token = req.session.token;
if (!token) {
return res.status(403).send({ message: "No token provided!" });
}
jwt.verify(token, config.secret, (err, decoded) => {
if (err) {
return res.status(401).send({ message: "Unauthorized!" });
}
req.userId = decoded.id;
next();
});
};
isAdmin = (req, res, next) => {
User.findById(req.userId).exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
Role.find(
{
_id: { $in: user.roles },
},
(err, roles) => {
if (err) {
res.status(500).send({ message: err });
return;
}
for (let i = 0; i < roles.length; i++) {
if (roles[i].name === "admin") {
next();
return;
}
}
res.status(403).send({ message: "Require Admin Role!" });
return;
}
);
});
};
isModerator = (req, res, next) => {
User.findById(req.userId).exec((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
Role.find(
{
_id: { $in: user.roles },
},
(err, roles) => {
if (err) {
res.status(500).send({ message: err });
return;
}
for (let i = 0; i < roles.length; i++) {
if (roles[i].name === "moderator") {
next();
return;
}
}
res.status(403).send({ message: "Require Moderator Role!" });
return;
}
);
});
};
const authJwt = {
verifyToken,
isAdmin,
isModerator,
};
module.exports = authJwt;
front end(metronic react typescript):
/* eslint-disable jsx-a11y/anchor-is-valid */
import {useState, useEffect} from 'react'
import {useFormik} from 'formik'
import * as Yup from 'yup'
import clsx from 'clsx'
import {getUserByToken, register} from '../core/_requests'
import {Link} from 'react-router-dom'
import {toAbsoluteUrl} from '../../../../_metronic/helpers'
import {PasswordMeterComponent} from '../../../../_metronic/assets/ts/components'
import {useAuth} from '../core/Auth'
import React from 'react'
const initialValues = {
firstname: '',
lastname: '',
email: '',
password: '',
changepassword: '',
acceptTerms: false,
}
const registrationSchema = Yup.object().shape({
firstname: Yup.string()
.min(3, 'Minimum 3 symbols')
.max(50, 'Maximum 50 symbols')
.required('First name is required'),
email: Yup.string()
.email('Wrong email format')
.min(3, 'Minimum 3 symbols')
.max(50, 'Maximum 50 symbols')
.required('Email is required'),
lastname: Yup.string()
.min(3, 'Minimum 3 symbols')
.max(50, 'Maximum 50 symbols')
.required('Last name is required'),
password: Yup.string()
.min(3, 'Minimum 3 symbols')
.max(50, 'Maximum 50 symbols')
.required('Password is required'),
changepassword: Yup.string()
.required('Password confirmation is required')
.when('password', {
is: (val: string) => (val && val.length > 0 ? true : false),
then: Yup.string().oneOf([Yup.ref('password')], "Password and Confirm Password didn't match"),
}),
acceptTerms: Yup.bool().required('You must accept the terms and conditions'),
})
export function Registration() {
const [loading, setLoading] = useState(false)
const {saveAuth, /*setCurrentUser*/} = useAuth()
const formik = useFormik({
initialValues,
validationSchema: registrationSchema,
onSubmit: async (values, {setStatus, setSubmitting}) => {
setLoading(true)
try {
const {data: auth} = await register(
values.email,
values.firstname,
values.lastname,
values.password,
values.changepassword
)
saveAuth(auth)
//const {data: user} = await getUserByToken(auth.api_token)
//setCurrentUser(user)
} catch (error) {
console.error(error)
saveAuth(undefined)
setStatus('The registration details are incorrect')
setSubmitting(false)
setLoading(false)
}
},
})
useEffect(() => {
PasswordMeterComponent.bootstrap()
}, [])
return (
<form
className='form w-100 fv-plugins-bootstrap5 fv-plugins-framework'
noValidate
id='kt_login_signup_form'
onSubmit={formik.handleSubmit}
>
{/* begin::Heading */}
<div className='mb-10 text-center'>
{/* begin::Title */}
<h1 className='text-dark mb-3'>Create an Account</h1>
{/* end::Title */}
{/* begin::Link */}
<div className='text-gray-400 fw-bold fs-4'>
Already have an account?
<Link to='/auth/login' className='link-primary fw-bolder' style={{marginLeft: '5px'}}>
Forgot Password ?
</Link>
</div>
{/* end::Link */}
</div>
{/* end::Heading */}
{/* begin::Action */}
<button type='button' className='btn btn-light-primary fw-bolder w-100 mb-10'>
<img
alt='Logo'
src={toAbsoluteUrl('/media/svg/brand-logos/google-icon.svg')}
className='h-20px me-3'
/>
Sign in with Google
</button>
{/* end::Action */}
<div className='d-flex align-items-center mb-10'>
<div className='border-bottom border-gray-300 mw-50 w-100'></div>
<span className='fw-bold text-gray-400 fs-7 mx-2'>OR</span>
<div className='border-bottom border-gray-300 mw-50 w-100'></div>
</div>
{formik.status && (
<div className='mb-lg-15 alert alert-danger'>
<div className='alert-text font-weight-bold'>{formik.status}</div>
</div>
)}
{/* begin::Form group Firstname */}
<div className='row fv-row mb-7'>
<div className='col-xl-6'>
<label className='class="form-label fw-bolder text-dark fs-6'>First name</label>
<input
placeholder='First name'
type='text'
autoComplete='off'
{...formik.getFieldProps('firstname')}
className={clsx(
'form-control form-control-lg form-control-solid',
{
'is-invalid': formik.touched.firstname && formik.errors.firstname,
},
{
'is-valid': formik.touched.firstname && !formik.errors.firstname,
}
)}
/>
{formik.touched.firstname && formik.errors.firstname && (
<div className='fv-plugins-message-container'>
<div className='fv-help-block'>
<span role='alert'>{formik.errors.firstname}</span>
</div>
</div>
)}
</div>
<div className='col-xl-6'>
{/* begin::Form group Lastname */}
<div className='fv-row mb-5'>
<label className='form-label fw-bolder text-dark fs-6'>Last name</label>
<input
placeholder='Last name'
type='text'
autoComplete='off'
{...formik.getFieldProps('lastname')}
className={clsx(
'form-control form-control-lg form-control-solid',
{
'is-invalid': formik.touched.lastname && formik.errors.lastname,
},
{
'is-valid': formik.touched.lastname && !formik.errors.lastname,
}
)}
/>
{formik.touched.lastname && formik.errors.lastname && (
<div className='fv-plugins-message-container'>
<div className='fv-help-block'>
<span role='alert'>{formik.errors.lastname}</span>
</div>
</div>
)}
</div>
{/* end::Form group */}
</div>
</div>
{/* end::Form group */}
{/* begin::Form group Email */}
<div className='fv-row mb-7'>
<label className='form-label fw-bolder text-dark fs-6'>Email</label>
<input
placeholder='Email'
type='email'
autoComplete='off'
{...formik.getFieldProps('email')}
className={clsx(
'form-control form-control-lg form-control-solid',
{'is-invalid': formik.touched.email && formik.errors.email},
{
'is-valid': formik.touched.email && !formik.errors.email,
}
)}
/>
{formik.touched.email && formik.errors.email && (
<div className='fv-plugins-message-container'>
<div className='fv-help-block'>
<span role='alert'>{formik.errors.email}</span>
</div>
</div>
)}
</div>
{/* end::Form group */}
{/* begin::Form group Password */}
<div className='mb-10 fv-row' data-kt-password-meter='true'>
<div className='mb-1'>
<label className='form-label fw-bolder text-dark fs-6'>Password</label>
<div className='position-relative mb-3'>
<input
type='password'
placeholder='Password'
autoComplete='off'
{...formik.getFieldProps('password')}
className={clsx(
'form-control form-control-lg form-control-solid',
{
'is-invalid': formik.touched.password && formik.errors.password,
},
{
'is-valid': formik.touched.password && !formik.errors.password,
}
)}
/>
{formik.touched.password && formik.errors.password && (
<div className='fv-plugins-message-container'>
<div className='fv-help-block'>
<span role='alert'>{formik.errors.password}</span>
</div>
</div>
)}
</div>
{/* begin::Meter */}
<div
className='d-flex align-items-center mb-3'
data-kt-password-meter-control='highlight'
>
<div className='flex-grow-1 bg-secondary bg-active-success rounded h-5px me-2'></div>
<div className='flex-grow-1 bg-secondary bg-active-success rounded h-5px me-2'></div>
<div className='flex-grow-1 bg-secondary bg-active-success rounded h-5px me-2'></div>
<div className='flex-grow-1 bg-secondary bg-active-success rounded h-5px'></div>
</div>
{/* end::Meter */}
</div>
<div className='text-muted'>
Use 8 or more characters with a mix of letters, numbers & symbols.
</div>
</div>
{/* end::Form group */}
{/* begin::Form group Confirm password */}
<div className='fv-row mb-5'>
<label className='form-label fw-bolder text-dark fs-6'>Confirm Password</label>
<input
type='password'
placeholder='Password confirmation'
autoComplete='off'
{...formik.getFieldProps('changepassword')}
className={clsx(
'form-control form-control-lg form-control-solid',
{
'is-invalid': formik.touched.changepassword && formik.errors.changepassword,
},
{
'is-valid': formik.touched.changepassword && !formik.errors.changepassword,
}
)}
/>
{formik.touched.changepassword && formik.errors.changepassword && (
<div className='fv-plugins-message-container'>
<div className='fv-help-block'>
<span role='alert'>{formik.errors.changepassword}</span>
</div>
</div>
)}
</div>
{/* end::Form group */}
{/* begin::Form group */}
<div className='fv-row mb-10'>
<div className='form-check form-check-custom form-check-solid'>
<input
className='form-check-input'
type='checkbox'
id='kt_login_toc_agree'
{...formik.getFieldProps('acceptTerms')}
/>
<label
className='form-check-label fw-bold text-gray-700 fs-6'
htmlFor='kt_login_toc_agree'
>
I Agree the{' '}
<Link to='/auth/terms' className='ms-1 link-primary'>
terms and conditions
</Link>
.
</label>
{formik.touched.acceptTerms && formik.errors.acceptTerms && (
<div className='fv-plugins-message-container'>
<div className='fv-help-block'>
<span role='alert'>{formik.errors.acceptTerms}</span>
</div>
</div>
)}
</div>
</div>
{/* end::Form group */}
{/* begin::Form group */}
<div className='text-center'>
<button
type='submit'
id='kt_sign_up_submit'
className='btn btn-lg btn-primary w-100 mb-5'
disabled={formik.isSubmitting || !formik.isValid || !formik.values.acceptTerms}
>
{!loading && <span className='indicator-label'>Submit</span>}
{loading && (
<span className='indicator-progress' style={{display: 'block'}}>
Please wait...{' '}
<span className='spinner-border spinner-border-sm align-middle ms-2'></span>
</span>
)}
</button>
<Link to='/auth/login'>
<button
type='button'
id='kt_login_signup_form_cancel_button'
className='btn btn-lg btn-light-primary w-100 mb-5'
>
Cancel
</button>
</Link>
</div>
{/* end::Form group */}
</form>
)
}
If there's something else that is relevant please let me know and I will add. I Thanks in advance for any assistance.
Hey Just Pass The Token to req.body after saving your users like this
exports.signup = (req, res) => {
const user = new User({
username: req.body.email,
firstname: req.body.firstname,
lastname: req.body.lastname,
email: req.body.email,
password: bcrypt.hashSync(req.body.password, 8),
});
user.save((err, user) => {
if (err) {
res.status(500).send({ message: err });
return;
}
if (req.body.roles) {
Role.find(
{
name: { $in: req.body.roles },
},
(err, roles) => {
if (err) {
res.status(500).send({ message: err });
return;
}
user.roles = roles.map((role) => role._id);
user.save((err,data) => {
if (err) {
res.status(500).send({ message: err });
return;
}
var token = jwt.sign({ id: data._id }, config.secret, {
expiresIn: 86400, // 24 hours
});
var authorities = [];
// This is what I mean
req.session.token = token;
res.status(200).send({
id: user._id,
username: user.username,
firstname: user.firstname,
lastname: user.lastname,
email: user.email,
});
});
});
}
);
} else {
Role.findOne({ name: "user" }, (err, role) => {
if (err) {
res.status(500).send({ message: err });
return;
}
user.roles = [role._id];
user.save((err,data) => {
if (err) {
res.status(500).send({ message: err });
return;
}
var token = jwt.sign({ id: data._id }, config.secret, {
expiresIn: 86400, // 24 hours
});
var authorities = [];
// This is what I mean
req.session.token = token;
res.status(200).send({
id: user._id,
username: user.username,
firstname: user.firstname,
lastname: user.lastname,
email: user.email,
});
});
});
});
}
});
};
it's simple, you only need call the signin function using the same email and password provided in the signup body instead of the res.send({ message: "User was registered successfully!" }); because the res.send works like a return you need to send the jwt instead the success message.
i hope help you
I don't know how to overcome from this given issue.
Line no 12
12| <% if (products !='') { %>
ReferenceError: C:\Users\Harsh Patel\Downloads\crud-app-main\crud-app-main\views\index.ejs:12 . products are not defined
So This the code from index.ejs file.
<%- include('layouts/header') %>
<div class="container">
<div class="row my-4">
<div class="col-lg-12">
<% if (message) { %>
<div class="alert alert-dismissible fade show alert-<%= message.type %> " role="alert">
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close">
</button>
<strong><%= message.message %> </strong>
</div>
<% } %>
<div class="table-responsive">
<% if (products !='') { %>
<table class="table table-striped text-center">
<thead>
<tr class="table-dark">
<th>ID</th>
<th>Image</th>
<th>Product Name</th>
<th>Category</th>
<th>Price</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<% products.forEach((row, index) => { %>
<tr class="align-middle">
<td><%= index %> </td>
<td><img src="<%= row.image %>" width="100" class="img-thumbnail" /> </td>
<td><%= row.name %> </td>
<td><%= row.category %> </td>
<td><%= row.price %> </td>
<td>
<i class="fas fa-edit fa-lg mx-1"></i>
<i class="fas fa-trash fa-lg mx-1"></i>
</td>
</tr>
<% }) %>
</tbody>
</table>
<% } else { %>
<h1 class="text-center text-secondary mt-5">No Products Found!!</h1>
<% } %>
</div>
</div>
`
[Reference Error][1]
This is the code for routers.js in routes folder
const express = require('express');
const router = express.Router();
const Products = require('../models/products');
const multer = require('multer');
const products = require('../models/products');
const fs = require('fs');
// Image Upload
var storage = multer.diskStorage({
destination: function(req, file, cb){
cb(null, './uploads');
},
filename: function(req, file, cb){
cb(null, file.fieldname+"_"+Date.now()+"_"+file.originalname);
},
});
var upload = multer({
storage: storage,
}) .single('image');
// Insert product name into database route
router.post("/add",upload, (req, res) => {
const product = new Products({
name: req.body.name,
category: req.body.category,
price: req.body.price,
image: req.file.filename,
});
product.save((err)=> {
if(err){
res.json({message: err.message, type:"danger"});
} else {
req.session.message = {
type: "success",
message: "Product added successfully"
};
res.redirect("/");
}
})
});
// Get all products route
router.get("/",(req, res) => {
Products.find().exec((err, products)=> {
if(err){
res.json({ message: err.message});
} else {
res.render("index", {
title: "Home Page",
products: products,
});
}
});
});
router.get("/add",(req, res) => {
res.render("add_products", {title:"Add Products"});
});
// Edit the products routes
router.get("/edit/:id",(req, res) => {
let id = req.params.id;
Products.findById(id, (err, products) => {
if(err)
{
res.redirect('/');
}
else {
if(products == null){
res.redirect("/");
} else {
res.render("edit_products", {
title: "Edit Product",
products : products,
});
}
}
});
});
//update product routes
router.post('/update/:id', upload, (req,res)=> {
let id = req.params.id;
let new_image = '';
if(req.file) {
new_image = req.file.filename;
try {
fs.unlinkSync('./uploads/' + req.body.old_image);
}
catch(err) {
console.log(err);
}
} else {
new_image = req.body.old_image;
}
Products.findByIdAndUpdate(id, {
name: req.body.name,
category: req.body.category,
price: req.body.price,
image: new_image,
}, (err, result) => {
if(err){
res.json({message: err.message, type: 'danger'});
} else {
req.session.message = {
type:'success',
message:'Product Updated Successfully'
};
res.redirect('/');
}
});
});
// Delete routes
router.get('/delete/:id', (req,res)=> {
let id = req.params.id;
Products.findByIdAndRemove(id, (err, result) => {
if(result.image != ''){
try {
fs.unlinkSync('./uploads/'+ result.image);
} catch (error) {
console.log(err);
}
}
if(err){
res.json({message: err.message});
} else {
req.session.message = {
type: 'info',
message: 'User Deleted'
};
res.redirect('/');
}
});
});
module.exports = router;
[1]: https://i.stack.imgur.com/lPH9b.png
Hi I am trying to add search bar in main page and search in the main page without changing to another page.
My user.js file
if (req.method == 'get'){
var username = req.query.username;
Users.find({username}, function (err, user) {
if(err) {
return res.render(template:'index')
}
res.render({template:'index', { user : user}});
})
}
my index.ejs file
<div class="search-user">
<% for user in user { %>
<div>
<p>Username : <%= user.username %></p>
<p>Age <%= user.age %></p>
<p>Status <%= user.status %></p>
</div>
<% } %>
</div>
This is giving me errors. May i know what did i do wrong?
Add a console message and check if you are getting data in user object
if (req.method == 'get'){
var username = req.query.username;
Users.find({username}, function (err, user) {
if(err) {
console.log('error', error)
return res.render('index')
}
console.log('user', user)
res.render('index', { user });
})
}
Further before iterating user of object just check something like this:
<div>
<p>Username : <%= JSON.stringfy(user) %></p>
</div>
By this you will get to know where error is being occured.
Refer to Res.render()
if (req.method == 'get'){
var username = req.query.username;
Users.find({username}, function (err, user) {
if(err) {
return res.render('index')
}
res.render('index', { user });
})
}
So I converted the .hbs template to .ejs template and try to see the difference. I thought converting would be same, but it turns out it doesn't.
My code is working. I can register a user, but no error shows up. The error display is the main problem in my code.
Error-looping of .ejs
This is the .HBS version of Error
{{#if message}}
<h4 class="alert alert-danger mt-4">{{message}}</h4>
{{/if}}
This is the .EJS version of Error
//SignUp.js / SignIn.js
<% if (error) { %>
<h4 class="alert alert-danger mt-4">{{message}}</h4>
<% } %>
Another version of Error in .EJS
<% if (hasErrors) {%>
<div class="alert alert-danger">
<% messages.forEach(function(message){ %>
<p><%= message %></p>
<% });%>
</div>
<% }%>
This is the Controllers folder - auth.js
exports.signin = async (req, res) => {
try {
const {email, password} = req.body;
if(!email || !password) {
return res.status(400).render('shop/signin', {
message: 'Please provide an email and/or password'
});
}
con.query('SELECT * FROM users WHERE email = ?', [email], async (error, results) => {
console.log(results);
if(!results || !(await bcrypt.compare(password, results[0].password))) {
res.status(401).render('shop/signin', {
message: 'Email or Password is incorrect'
});
}
else {
const id = results[0].id;
const token = jwt.sign({ id }, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRES_IN
});
console.log("The token is: " + token);
const cookieOptions = {
expires: new Date(
Date.now() = process.env.JWT_COOKIE_EXPIRES * 24 * 60 * 60 * 1000
),
httpOnly: true
}
res.cookie('jwt', token, cookieOptions);
res.status(200).redirect("shop/profile");
}
});
}
catch(error) {
console.log(error);
}
}
exports.signup = (req, res) => {
console.log(req.body);
const {name, email, password, passwordConfirm} = req.body;
con.query('SELECT email FROM users WHERE email = ?', [email], async (error, results) => {
if(error) {
console.log(error);
}
if(results.length > 0) {
return res.render('shop/signup', {
message: 'That email is already in use!'
});
}
else if(password !== passwordConfirm) {
return res.render('shop/signup', {
message: 'Passwords do not match!'
});
}
let hashedPassword = await bcrypt.hash(password, 8);
console.log(hashedPassword);
con.query('INSERT INTO users SET ?', {name: name, email: email, password: hashedPassword}, (error, results) => {
if(error) {
console.log(error);
}
else {
console.log(results);
return res.render('shop/signup', {
message: 'User Registered!'
});
}
});
});
}
This is the Routes folder - user.js
router.post('/signup', authController.signup);
router.post('/signin', authController.signin);
module.exports = router;
Lord
You can solve this job in two ways.
1-Local Message
return res.send("<script> alert('Error Message'); window.location = 'shop/signin'; </script>")
2- If you don't want to use local messages Use 'flash' and 'session' packages