So Im currently building a blog site using Mongodb, Express, React, and Node. Everything was working until I started implementing ChakraUI and since then, I have been running into a lot of errors when changing the code for fetching and posting my profile and posts from the data base. I've been spending DAYS trying to figure out the problem I really need someone's help on this. Thanks in advance. Im very new to this
For the Jwt token error, Im not too sure where the issue is originating from but I think from reviewing the logs its pointing to this line of code from my index.js file:
const newLocal = '/profile';
app.get(newLocal, (req,res) => {
const {token} = req.cookies;
jwt.verify(token, secret, {}, (err,info) => {
if (err) throw err;
res.json(info);
});
});
const express = require('express');
const cors = require('cors');
const mongoose = require("mongoose");
const User = require('./models/User');
const Post = require('./models/Post');
const bcrypt = require('bcrypt');
const app = express();
const jwt = require('jsonwebtoken');
const cookieParser = require('cookie-parser');
const multer = require('multer');
const uploadMiddleware = multer({ dest: 'Uploads/' });
const fs = require('fs');
const salt = bcrypt.genSaltSync(10);
const secret = 'asdfe45we45w345wegw345werjktjwertkj';
app.use(cors({credentials:true,origin:'http://localhost:3000'}));
app.use(express.json());
app.use(cookieParser());
app.use('/Uploads', express.static(__dirname + '/Uploads'));
mongoose.connect('mongodb+srv://admin:Deathsword11#testblog.jmhhq2b.mongodb.net/?retryWrites=true&w=majority');
app.post('/register', async (req,res) => {
const {username,password} = req.body;
try{
const userDoc = await User.create({
username,
password:bcrypt.hashSync(password,salt),
});
res.json(userDoc);
} catch(e) {
console.log(e);
res.status(400).json(e);
}
});
app.post('/login', async (req,res) => {
const {username,password} = req.body;
const userDoc = await User.findOne({username});
const passOk = bcrypt.compareSync(password, userDoc.password);
if (passOk) {
// logged in
jwt.sign({username,id:userDoc._id}, secret, {}, (err,token) => {
if (err) throw err;
res.cookie('token', token).json({ id:userDoc._id, username,
});
});
} else {
res.status(400).json('wrong credentials');
}
});
const newLocal = '/profile';
app.get(newLocal, (req,res) => {
const {token} = req.cookies;
jwt.verify(token, secret, {}, (err,info) => {
if (err) throw err;
res.json(info);
});
});
app.post('/logout', (req,res) => {
res.cookie('token', '').json('ok');
});
app.post('/post', uploadMiddleware.single('file'), async (req,res) => {
const {originalname,path} = req.file;
const parts = originalname.split('.');
const ext = parts[parts.length - 1];
const newPath = path+'.'+ext;
fs.renameSync(path, newPath);
const {token} = req.cookies;
const x = jwt.verify(token, secret, {}, (err,info) => {
if (err) throw err;
const {title,summary,content} = req.body;
const postDoc = Post.create({
title,
summary,
content,
cover:newPath,
author:info.id,
});
res.json(postDoc);
});
});
app.put('/post',uploadMiddleware.single('file'), async (req,res) => {
let newPath = null;
if (req.file) {
const {originalname,path} = req.file;
const parts = originalname.split('.');
const ext = parts[parts.length - 1];
newPath = path+'.'+ext;
fs.renameSync(path, newPath);
}
const {token} = req.cookies;
jwt.verify(token, secret, {}, async (err,info) => {
if (err) throw err;
const {id,title,summary,content} = req.body;
const postDoc = await Post.findById(id);
const isAuthor = JSON.stringify(postDoc.author) === JSON.stringify(info.id);
if (!isAuthor) {
return res.status(400).json('you are not the author');
}
await postDoc.update({
title,
summary,
content,
cover: newPath ? newPath : postDoc.cover,
});
res.json(postDoc);
});
});
app.get('/post', async (req,res) => {
res.json(
await Post.find()
.populate('author', ['username'])
.sort({createdAt: -1})
.limit(20)
);
});
app.get('/post/:id', async (req, res) => {
const {id} = req.params;
const postDoc = await Post.findById(id).populate('author', ['username']);
res.json(postDoc);
})
app.listen(4000);
//
The 500 Internal Server Error is pointing to line below from my Header.js file
fetch('http://localhost:4000/profile'
/Header.js
import { useContext, useEffect } from "react";
import { Link } from "react-router-dom";
import { useState} from "react";
import { UserContext } from "./UserContext";
import { Box, Button, Flex, useColorModeValue, IconButton, useDisclosure, HStack, MenuButton, MenuList, MenuItem, MenuDivider, Menu, Avatar, Stack } from "#chakra-ui/react";
import { right } from "#popperjs/core";
import { HamburgerIcon, CloseIcon, AddIcon} from "#chakra-ui/icons";
export default function Header() {
const { isOpen, onOpen, onClose } = useDisclosure();
const {userInfo, setUserInfo} = useContext(UserContext);
useEffect(() => {
fetch('http://localhost:4000/profile', {
credentials: 'include',
}).then(response => {
response.json().then(userInfo => {
setUserInfo(userInfo);
});
});
}, []);
function logout() {
fetch('http://localhost:4000/logout', {
credentials: 'include',
method: 'POST',
});
setUserInfo(null);
}
const username = userInfo?.username;
const LinkF = ['BlakFinance'];
const LinkR = ['BlakRelationships'];
const LinkT = ['BlakTech'];
const LinkL = ['Login'];
const LinkS = ['Subscribe'];
const LinkCr = ['Create'];
return (
<>
<Box bg={useColorModeValue('gray.100', 'gray.900')} px={4}>
<Flex h={16} alignItems={'center'} justifyContent={'space-between'}>
<IconButton
size={'md'}
icon={isOpen ? <CloseIcon /> : <HamburgerIcon />}
aria-label={'Open Menu'}
display={{ md: 'none' }}
onClick={isOpen ? onClose : onOpen}
/>
<HStack spacing={10} alignItems={'center'}>
<Box as={Link} to='/'>BlakConscience</Box>
<HStack
as={'nav'}
spacing={4}
display={{ base: 'none', md: 'flex' }}>
{LinkF.map((link) => (
<Link as={Link} to='/BlakFinance' key={link}>{link}</Link>
))}
{LinkT.map((link) => (
<Link as={Link} to='/BlakTech' key={link}>{link}</Link>
))}
{LinkR.map((link) => (
<Link as={Link} to='/BlakRelationships' key={link}>{link}</Link>
))}
{LinkS.map((link) => (
<Link as={Link} to='/Subscribe' key={link}>{link}</Link>
))}
{username && (
LinkCr.map((link) => (
<><Link as={Link} to='/CreatePost' key={link}>{link}</Link><a onClick={logout}> logout {username} </a></>
))
)}
{LinkL.map((link) => (
<Link as={Link} to='/login' key={link}>{link}</Link>
))}
</HStack>
</HStack>
</Flex>
{isOpen ? (
<Box pb={4} display={{ md: 'none' }}>
<Stack as={'nav'} spacing={4}>
{LinkF.map((link) => (
<Link as={Link} to='/BlakFinance' key={link}>{link}</Link>
))}
</Stack>
<Stack as={'nav'} spacing={4}>
{LinkT.map((link) => (
<Link as={Link} to='/BlakTech' key={link}>{link}</Link>
))}
</Stack>
<Stack as={'nav'} spacing={4}>
{LinkR.map((link) => (
<Link as={Link} to='/BlakRelationships' key={link}>{link}</Link>
))}
</Stack>
<Stack as={'nav'} spacing={4}>
{LinkS.map((link) => (
<Link as={Link} to='/Subscribe' key={link}>{link}</Link>
))}
</Stack>
<Stack as={'nav'} spacing={4}>
{LinkL.map((link) => (
<Link as={Link} to='/login' key={link}>{link}</Link>
))}
</Stack>
</Box>
) : null}
</Box>
<Box p={4}></Box>
</>
);
}
The code originally looked like this:
import {formatISO9075} from "date-fns";
import {Link} from "react-router-dom";
export default function Post({_id,title,summary,cover,content,createdAt,author}) {
return (
<div className="post">
<div className="image">
<Link to={`/post/${_id}`}>
<img src={'http://localhost:4000/'+cover} alt=""/>
</Link>
</div>
<div className="texts">
<Link to={`/post/${_id}`}>
<h2>{title}</h2>
</Link>
<p className="info">
<a className="author">{author.username}</a>
<time>{formatISO9075(new Date(createdAt))}</time>
</p>
<p className="summary">{summary}</p>
</div>
</div>
);
}
My goal was to change the website UI to look like ChakraUI, I started getting the errors once I changed this file: post.js
import {formatISO9075} from 'date-fns';
import {
Link,
Box,
Heading,
Image,
Text,
useColorModeValue,
Container,
Stack
} from '#chakra-ui/react';
export default function Post({\_id,title,summary,cover,content,createdAt,author}) {
return (
\<Container maxW={'7xl'} p='12'\>
\<Box
marginTop={{ base: '1', sm: '5' }}
display='flex'
flexDirection={{ base: 'column', sm: 'row' }}
justify-content='space-between'\>
\</Box\>
\<Box
display="flex"
flex="1"
marginRight="3"
position="relative"
alignItems="center"\>
\<Box
width={{ base: '100%', sm: '85%' }}
zIndex="2"
marginLeft={{ base: '0', sm: '5%' }}
marginTop="5%"\>
\<Link to={"/post/"+ \_id} textDecoration="none" \_hover={{ textDecoration: 'none' }}\>
\<Image
borderRadius="lg"
src={
'http://localhost:4000/' + cover
}
alt="some good alt text"
objectFit="contain"
/\>
\</Link\>
\</Box\>
\<Box zIndex="1" width="100%" position="absolute" height="100%"\>
\<Box
bgGradient={useColorModeValue(
'radial(orange.600 1px, transparent 1px)',
'radial(orange.300 1px, transparent 1px)'
)}
backgroundSize="20px 20px"
opacity="0.4"
height="100%"
/\>
\</Box\>
\</Box\>
<Box
display="flex"
flex="1"
flexDirection="column"
justifyContent="center"
marginTop={{ base: '3', sm: '0' }}>
<Heading marginTop="1">
<Link as={Link} to={"/post/" + _id} textDecoration="none" _hover={{ textDecoration: 'none' }}>
{title}
</Link>
</Heading>
<Text
as="p"
marginTop="2"
color={useColorModeValue('gray.700', 'gray.200')}
fontSize="lg">
{summary}
</Text>
<Stack>name={author} date={new Date(createdAt)} </Stack>
</Box>
</Container>
);
}
Related
this is my dashboard page , i should be directed to it after the login , and i am sure that the login process is successful , but after the login I face a plank page .
import React from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import "./Chat.css"
const DashboardPage = (props) => {
const nameRef = React.createRef();
const [chatrooms, setChatrooms] = React.useState([]);
const chatname = nameRef.current.value;
const createChat = (e) => {
e.preventDefault()
axios
.post("http://localhost:5000/chatroom", {
name:chatname })
.then((response) => {
console.log(response.data.message)
})
.catch((err) => {
console.log(err);
});
};
const getChatrooms = () => {
axios
.get("http://localhost:5000/chatroom", {
headers: {
Authorization: "Bearer " + localStorage.getItem("CC_Token"),
},
})
.then((response) => {
setChatrooms(response.data);
console.log(response.data)
})
.catch((err) => {
setTimeout(getChatrooms, 3000);
});
};
React.useEffect(() => {
getChatrooms();
// eslint-disable-next-line
}, []);
return (
<div className="card">
<div className="cardHeader">Chatrooms</div>
<div className="cardBody">
<div className="inputGroup">
<label htmlFor="chatroomName">Chatroom Name</label>
<input
type="text"
name="chatroomName"
id="chatroomName"
placeholder="ChatterBox Nepal"
ref={nameRef}
/>
</div>
</div>
<button onClick={createChat} type="button">Create Chatroom</button>
<div className="chatrooms">
{chatrooms.map((chatroom) => (
<div key={chatroom._id} className="chatroom">
<div>{chatroom.name}</div>
<Link to={"/chat/" + chatroom._id}>
<div className="join">Join</div>
</Link>
</div>
))}
</div>
</div>
);
};
export default DashboardPage;
and this is the App.js :
import './App.css';
import Navigation from './components/Navigation';
import {BrowserRouter,Routes,Route} from "react-router-dom"
import Home from "./pages/Home"
import Login from "./pages/Login"
import Signup from "./pages/Signup"
import Chat from "./pages/Chat"
import 'font-awesome/css/font-awesome.min.css';
import io from "socket.io-client";
import makeToast from "./Toaster";
import React from "react";
import DashboardPage from './pages/DashboardPage';
function App() {
const [socket, setSocket] = React.useState(null);
const setupSocket = () => {
const token = localStorage.getItem("CC_Token");
if (token && !socket) {
const newSocket = io("http://localhost:5000", {
query: {
token: localStorage.getItem("CC_Token"),
},
});
newSocket.on("disconnect", () => {
setSocket(null);
setTimeout(setupSocket, 3000);
makeToast("error", "Socket Disconnected!");
});
newSocket.on("connect", () => {
makeToast("success", "Socket Connected!");
});
setSocket(newSocket);
}
};
React.useEffect(() => {
setupSocket();
//eslint-disable-next-line
}, []);
return (
<BrowserRouter>
<Navigation />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login setupSocket={setupSocket} />} />
<Route path="/signup" element={<Signup />} />
<Route path="/dashboard" element={<DashboardPage socket={socket} />} />
<Route path="/chat/:id" element={<Chat socket={socket} />} />
</Routes>
</BrowserRouter>
);
}
export default App;
and this is the chat page :
import React from "react";
import "./Chat.css"
const Chat = ({ match, socket }) => {
const chatroomId = match.params.id;
const [messages, setMessages] = React.useState([]);
const messageRef = React.useRef();
const [userId, setUserId] = React.useState("");
const sendMessage = () => {
if (socket) {
socket.emit("chatroomMessage", {
chatroomId,
message: messageRef.current.value,
});
messageRef.current.value = "";
}
};
React.useEffect(() => {
const token = localStorage.getItem("CC_Token");
if (token) {
const payload = JSON.parse(atob(token.split(".")[1]));
setUserId(payload.id);
}
if (socket) {
socket.on("newMessage", (message) => {
const newMessages = [...messages, message];
setMessages(newMessages);
});
}
//eslint-disable-next-line
}, [messages]);
React.useEffect(() => {
if (socket) {
socket.emit("joinRoom", {
chatroomId,
});
}
return () => {
//Component Unmount
if (socket) {
socket.emit("leaveRoom", {
chatroomId,
});
}
};
//eslint-disable-next-line
}, []);
return (
<div className="chatroomPage">
<div className="chatroomSection">
<div className="cardHeader">Chatroom Name</div>
<div className="chatroomContent">
{messages.map((message, i) => (
<div key={i} className="message">
<span
className={
userId === message.userId ? "ownMessage" : "otherMessage"
}
>
{message.name}:
</span>{" "}
{message.message}
</div>
))}
</div>
<div className="chatroomActions">
<div>
<input
type="text"
name="message"
placeholder="Say something!"
ref={messageRef}
/>
</div>
<div>
<button className="join" onClick={sendMessage}>
Send
</button>
</div>
</div>
</div>
</div>
);
};
export default Chat;
so as i said above , what should i do ??
before i edit it a liitle bit , it showed only the create room part of the dashboard page , but not the ( join room ) part .
now it does not show anything , and I am lost !!!!!!!!!!!!!!
I am trying to create an app and I want to upload image if user is admin i am using react as front end and node js to create api and mongo db as database now my api is working properly in postmen but when i am trying to upload an image through frontend it throws this error "token is invalid" and in node js terminal i am getting this "Cannot read properties of undefined (reading 'isAdmin')"
File for token verification
const jwt = require("jsonwebtoken");
const dotenv = require("dotenv");
dotenv.config();
const veryfiyToken = (req, res, next) => {
const authHeader = req.headers.token;
if (authHeader) {
const token = authHeader.split(" ")[1];
jwt.verify(token, process.env.JWT_KEY, (err, user) => {
if (err) res.status(403).json("Token is not valid");
req.user = user;
next();
});
} else {
return res.status(401).json("You are not authorised");
}
};
const veryfiyTokenAndAuthorization = (req, res, next) => {
veryfiyToken(req, res, () => {
if (req.user.id === req.params.id || req.user.isAdmin) {
next();
} else {
res.status(403).json("You are not allowed to do that");
}
});
};
const veryfiyTokenAndAdmin = (req, res, next) => {
veryfiyToken(req, res, () => {
if (req.user.isAdmin) {
next();
} else {
res.status(403).json("You are not allowed to do that");
}
});
};
module.exports = {
veryfiyToken,
veryfiyTokenAndAuthorization,
veryfiyTokenAndAdmin };
File to upload image
import React, { useEffect, useState } from "react";
import axios from "axios";
import Cookies from 'js-cookie'
import { authRequest, publicRequest } from "../../../Redux/requestMethods";
import { IoCloudUpload } from "react-icons/io5";
import { doc, setDoc } from "firebase/firestore";
import { getFirestore } from "firebase/firestore";
import {
Flex,
useColorMode,
useColorModeValue,
Input,
Button,
FormLabel,
Text,
} from "#chakra-ui/react";
import ProgressBar from "../ProgressBar/ProgressBar";
import {
getStorage,
ref,
uploadBytesResumable,
getDownloadURL,
} from "firebase/storage";
import { firebaseApp } from "../../../firebase.config";
export default function UploadForm() {
const { colorMode } = useColorMode();
const bg = useColorModeValue("gray.50", "gray.900");
const textColor = useColorModeValue("gray.900", "gray.50");
const [progress, setProgress] = useState(null);
const [loading, setLoading] = useState(false);
const [loading1, setLoading1] = useState(false);
const [loading2, setLoading2] = useState(false);
const [loading3, setLoading3] = useState(false);
const [inputs, setInputs] = useState({});
const [imageAsset, setImageAsset] = useState(null);
const [imageAsset1, setImageAsset1] = useState(null);
const [imageAsset2, setImageAsset2] = useState(null);
const [imageAsset3, setImageAsset3] = useState(null);
axios.defaults.withCredentials = true;
const storage = getStorage(firebaseApp); // Firebase Storage
const firebaseDb = getFirestore(firebaseApp); // Firebase FireStore
function handleChange(e) {
setInputs((prev) => {
return { ...prev, [e.target.name]: e.target.value };
});
}
const token = Cookies.get('accessToken')
console.log(token)
// console.log(inputs);
/// Thumbnail Image ///
function UploadThumbnailImage(e) {
if (e && e.preventDefault) {
e.preventDefault();
setLoading(true);
const ThumbnailImage = e.target.files[0];
const storageRef = ref(
storage,
`Images/${Date.now()}-${ThumbnailImage.name}}`
);
const uploadTask = uploadBytesResumable(storageRef, ThumbnailImage);
uploadTask.on(
"state_changed",
(snapShot) => {
const uploadProgress =
(snapShot.bytesTransferred / snapShot.totalBytes) * 100;
setProgress(uploadProgress);
},
(error) => {
console.log(error);
},
async () => {
await getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setLoading(false);
setImageAsset(downloadURL);
setInputs((prev) => {
return { ...prev, [e.target.name]: downloadURL };
});
});
}
);
}
}
/// Image - 1 ///
function UploadImage1(e) {
if (e && e.preventDefault) {
e.preventDefault();
setLoading1(true);
const Image1 = e.target.files[0];
const storageRef = ref(storage, `Images/${Date.now()}-${Image1.name}}`);
const uploadTask = uploadBytesResumable(storageRef, Image1);
uploadTask.on(
"state_changed",
(snapShot) => {
const uploadProgress =
(snapShot.bytesTransferred / snapShot.totalBytes) * 100;
setProgress(uploadProgress);
},
(error) => {
console.log(error);
},
async () => {
await getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setImageAsset1(downloadURL);
setLoading1(false);
setInputs((prev) => {
return { ...prev, [e.target.name]: downloadURL };
});
});
}
);
}
}
/// Image - 2 ///
function UploadImage2(e, Image2URL) {
if (e && e.preventDefault) {
e.preventDefault();
setLoading2(true);
const Image2 = e.target.files[0];
const storageRef = ref(storage, `Images/${Date.now()}-${Image2.name}}`);
const uploadTask = uploadBytesResumable(storageRef, Image2);
uploadTask.on(
"state_changed",
(snapShot) => {
const uploadProgress =
(snapShot.bytesTransferred / snapShot.totalBytes) * 100;
setProgress(uploadProgress);
},
(error) => {
console.log(error);
},
async () => {
await getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setLoading2(false);
setImageAsset2(downloadURL);
setInputs((prev) => {
return { ...prev, [e.target.name]: downloadURL };
});
});
}
);
}
}
/// Image - 3 ///
function UploadImage3(e, Image3URL) {
if (e && e.preventDefault) {
e.preventDefault();
setLoading3(true);
const Image3 = e.target.files[0];
const storageRef = ref(storage, `Images/${Date.now()}-${Image3.name}}`);
const uploadTask = uploadBytesResumable(storageRef, Image3);
uploadTask.on(
"state_changed",
(snapShot) => {
const uploadProgress =
(snapShot.bytesTransferred / snapShot.totalBytes) * 100;
setProgress(uploadProgress);
},
(error) => {
console.log(error);
},
async () => {
await getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
setLoading3(false);
setImageAsset3(downloadURL);
setInputs((prev) => {
return { ...prev, [e.target.name]: downloadURL };
});
});
}
);
}
}
async function uploadToDatabase(e) {
e.preventDefault();
const res = await authRequest.post("/images",{...inputs },{
withCredentials: true});
console.log(res);
}
return (
<Flex
justifyContent={"center"}
alignItems="center"
width={"full"}
minHeight="100vh"
padding={10}
>
<Flex
width={"80%"}
height="full"
border={"1px"}
borderColor="gray.300"
borderRadius={"md"}
p="4"
flexDirection={"column"}
alignItems="center"
justifyContent={"center"}
gap={2}
>
<Input
variant={"flushed"}
placeholder="Title"
name="title"
id="title"
focusBorderColor="gary.400"
isRequired
errorBorderColor="red"
type={"text"}
_placeholder={{ color: "gray.500" }}
fontSize={20}
onChange={handleChange}
/>
<Flex
border={"1px"}
borderColor="gray.500"
height={"40px"}
borderStyle="dashed"
width={"full"}
borderRadius="md"
overflow={"hidden"}
position="relative"
>
{!imageAsset ? ( // ThumbnailImage
<FormLabel width={"full"}>
<Flex
direction={"column"}
alignItems="center"
justifyContent={"center"}
height="full"
width={"full"}
>
<Flex
direction={"column"}
alignItems="center"
justifyContent={"center"}
height="full"
width={"full"}
cursor="pointer"
>
{loading ? (
<ProgressBar msg={"Uploading Image"} progress={progress} />
) : (
<>
<IoCloudUpload
fontSize={"8rem"}
color={`${colorMode == "#f1f1f1" ? "dark" : "#111"}`}
/>
<Text mt={2} fontSize={20} color={"blackAlpha.700"}>
Click To Upload Thumbnail Image
</Text>
</>
)}
</Flex>
</Flex>
{!loading && (
<input
type={"file"}
name="thumbnailImg"
style={{ width: 0, height: 0 }}
accept="image/*"
onChange={UploadThumbnailImage}
/>
)}
</FormLabel>
) : (
<Flex
justifyContent={"center"}
alignItems="center"
width={"full"}
height="full"
position={"relative"}
>
<Text fontSize={20} fontWeight="bold" color={"blackAlpha.900"}>
Image Uploaded
</Text>
</Flex>
)}
</Flex>
<Flex
border={"1px"}
borderColor="gray.500"
height={"40px"}
borderStyle="dashed"
width={"full"}
borderRadius="md"
overflow={"hidden"}
position="relative"
>
{!imageAsset1 ? ( // 1st Image
<FormLabel width={"full"}>
<Flex
direction={"column"}
alignItems="center"
justifyContent={"center"}
height="full"
width={"full"}
>
<Flex
direction={"column"}
alignItems="center"
justifyContent={"center"}
height="full"
width={"full"}
cursor="pointer"
>
{loading1 ? (
<ProgressBar msg={"Uploading Image"} progress={progress} />
) : (
<>
<IoCloudUpload
fontSize={"8rem"}
color={`${colorMode == "#f1f1f1" ? "dark" : "#111"}`}
/>
<Text mt={2} fontSize={20} color={"blackAlpha.700"}>
Click To Upload Image-1
</Text>
</>
)}
</Flex>
</Flex>
{!loading1 && (
<input
type={"file"}
name="img1"
style={{ width: 0, height: 0 }}
accept="image/*"
onChange={UploadImage1}
/>
)}
</FormLabel>
) : (
<Flex
justifyContent={"center"}
alignItems="center"
width={"full"}
height="full"
position={"relative"}
>
<Text fontSize={20} fontWeight="bold" color={"blackAlpha.900"}>
Image-1 Uploaded
</Text>
</Flex>
)}
</Flex>
<Flex
border={"1px"}
borderColor="gray.500"
height={"40px"}
borderStyle="dashed"
width={"full"}
borderRadius="md"
overflow={"hidden"}
position="relative"
>
{!imageAsset2 ? ( // 2nd Image
<FormLabel width={"full"}>
<Flex
direction={"column"}
alignItems="center"
justifyContent={"center"}
height="full"
width={"full"}
>
<Flex
direction={"column"}
alignItems="center"
justifyContent={"center"}
height="full"
width={"full"}
cursor="pointer"
>
{loading2 ? (
<ProgressBar msg={"Uploading Image"} progress={progress} />
) : (
<>
<IoCloudUpload
fontSize={"8rem"}
color={`${colorMode == "#f1f1f1" ? "dark" : "#111"}`}
/>
<Text mt={2} fontSize={20} color={"blackAlpha.700"}>
Click To Upload Image-2
</Text>
</>
)}
</Flex>
</Flex>
{!loading2 && (
<input
type={"file"}
name="img2"
style={{ width: 0, height: 0 }}
accept="image/*"
onChange={UploadImage2}
/>
)}
</FormLabel>
) : (
<Flex
justifyContent={"center"}
alignItems="center"
width={"full"}
height="full"
position={"relative"}
>
<Text fontSize={20} fontWeight="bold" color={"blackAlpha.900"}>
Image-2 Uploaded
</Text>
</Flex>
)}
</Flex>
<Flex
border={"1px"}
borderColor="gray.500"
height={"40px"}
borderStyle="dashed"
width={"full"}
borderRadius="md"
overflow={"hidden"}
position="relative"
>
{!imageAsset3 ? ( // 3rd Image
<FormLabel width={"full"}>
<Flex
direction={"column"}
alignItems="center"
justifyContent={"center"}
height="full"
width={"full"}
>
<Flex
direction={"column"}
alignItems="center"
justifyContent={"center"}
height="full"
width={"full"}
cursor="pointer"
>
{loading3 ? (
<ProgressBar msg={"Uploading Image"} progress={progress} />
) : (
<>
<IoCloudUpload
fontSize={"8rem"}
color={`${colorMode == "#f1f1f1" ? "dark" : "#111"}`}
/>
<Text mt={2} fontSize={20} color={"blackAlpha.700"}>
Click To Upload Image-3
</Text>
</>
)}
</Flex>
</Flex>
{!loading3 && (
<input
type={"file"}
name="img3"
style={{ width: 0, height: 0 }}
accept="image/*"
onChange={UploadImage3}
/>
)}
</FormLabel>
) : (
<Flex
justifyContent={"center"}
alignItems="center"
width={"full"}
height="full"
position={"relative"}
>
<Text fontSize={20} fontWeight="bold" color={"blackAlpha.900"}>
Image-3 Uploaded
</Text>
</Flex>
)}
</Flex>
<Flex
direction={"column"}
alignItems="center"
justifyContent={"center"}
height="full"
width={"full"}
>
<Input
variant={"flushed"}
placeholder="Description"
name="desc"
focusBorderColor="gary.400"
isRequired
errorBorderColor="red"
type={"text"}
_placeholder={{ color: "gray.500" }}
fontSize={20}
onChange={handleChange}
/>
</Flex>
<Flex
direction={"column"}
alignItems="center"
justifyContent={"center"}
height="full"
width={"full"}
>
<Input
variant={"flushed"}
placeholder="Price"
name="price"
focusBorderColor="gary.400"
isRequired
errorBorderColor="red"
type={"text"}
_placeholder={{ color: "gray.500" }}
fontSize={20}
onChange={handleChange}
/>
</Flex>
<Flex
direction={"column"}
alignItems="center"
justifyContent={"center"}
height="full"
width={"full"}
>
<Input
variant={"flushed"}
placeholder="Place"
name="place"
focusBorderColor="gary.400"
isRequired
errorBorderColor="red"
type={"text"}
_placeholder={{ color: "gray.500" }}
fontSize={20}
onChange={handleChange}
/>
</Flex>
<Flex
direction={"column"}
alignItems="center"
justifyContent={"center"}
height="full"
width={"full"}
>
<Input
variant={"flushed"}
placeholder="Fuel Type"
name="fueltype"
focusBorderColor="gary.400"
isRequired
errorBorderColor="red"
type={"text"}
_placeholder={{ color: "gray.500" }}
fontSize={20}
onChange={handleChange}
/>
</Flex>
<Button
marginTop={"1rem"}
isLoading={loading}
loadingText="Adding File"
colorScheme={"teal"}
variant={`${loading ? "outline" : "solid"}`}
width="full"
_hover={{ shadow: "lg" }}
fontSize={20}
onClick={uploadToDatabase}
>
Upload File
</Button>
</Flex>
</Flex>
);
}
File containing authRequest
import axios from "axios";
import Cookies from 'js-cookie'
const BASE_URL = 'http://localhost:500/api/';
const token = Cookies.get('token')
export const publicRequest = axios.create({
baseURL: BASE_URL
})
export const authRequest = axios.create({
baseURL: BASE_URL,
headers:{
token: `Bearer${token}`
}
})
auth file which stores token in cookie and handles login
const router = require("express").Router();
const User = require("../models/User");
const CryptoJs = require("crypto-js");
const dotenv = require("dotenv");
const jwt = require("jsonwebtoken");
const cookieParser = require("cookie-parser");
const { findOne } = require("../models/User");
dotenv.config();
router.use(cookieParser());
// Register
router.post("/register", async (req, res) => {
const newUser = new User({
username: req.body.username,
email: req.body.email,
password: CryptoJs.AES.encrypt(
req.body.password,
process.env.PASS_KEY
).toString(),
});
try {
const savedUser = await newUser.save();
res.status(201).json(savedUser);
} catch (err) {
res.status(500).json(err);
}
});
// Login
router.post("/login", async (req, res) => {
try {
const user = await User.findOne({ username: req.body.username });
!user && res.status(401).json("wrong credentials");
const hashedPassword = CryptoJs.AES.decrypt(
user.password,
process.env.PASS_KEY
);
const OrignalPassword = hashedPassword.toString(CryptoJs.enc.Utf8);
OrignalPassword !== req.body.password &&
res.status(401).json("wrong credentials");
const token = jwt.sign(
{
id: user._id,
isAdmin: user.isAdmin,
},
process.env.JWT_KEY,
{expiresIn:"3d"}
);
const { password, ...others } = user._doc;
res
.cookie("accessToken", token)
.status(200)
.json({ ...others, token});
} catch (error) {
res.status(500).json(error);
return;
}
return;
});
module.exports = router;
Image controller
const User = require('../models/User');
const Image = require('../models/Image');
const addImage = async (req,res,next)=>{
const newImage = new Image({ ...req.body});
try {
const saveImage = await newImage.save()
res.status(200).json('Image uploaded')
} catch (error) {
next(error)
}
}
module.exports = Object.freeze({
addImage
})
I know this is lot of code but it works perfcetly in postmen but not working in react and i cant figure out why? I tried every possible solution any help......
well after a lot of try I solved this I had issue with passing my token as I said it was working totally ok with postmen so below is my solution
Changes is authRequest method
from this
import axios from "axios";
import Cookies from 'js-cookie'
const BASE_URL = 'http://localhost:500/api/';
const token = Cookies.get('token')
export const publicRequest = axios.create({
baseURL: BASE_URL
})
export const authRequest = axios.create({
baseURL: BASE_URL,
headers:{
token: `Bearer${token}`
}
})
To this
import axios from "axios";
import Cookies from 'js-cookie'
const BASE_URL = 'http://localhost:500/api/';
const accessToken = Cookies.get('accessToken')
export const publicRequest = axios.create({
baseURL: BASE_URL
})
export const authRequest = axios.create({
baseURL: BASE_URL,
headers:{
token:`Bearer ${accessToken}`
}
})
when I was trying to to get token I was using 'token' in Cookies.get() but I named it accessToken in my response so I was not getting token so changing it name gave me token.
second while passing token in header I was not providing space between Bearer and token in formated sting.
If similar problem occurs check for request in networks header tab in dev tools it helps a lot. :)
Note:- Do not pass token in request method as shown in code authRequest instead pass it in post method as below
async function uploadToDatabase(e) {
e.preventDefault();
const res = await authRequest.post(
"/images",
{ ...inputs },
{
withCredentials: true,
headers:{
token:`Bearer ${accessToken}`
}
}
);
}
I am creating a React app which can be used to manage company events. There are two components related to events that aren't working at the moment. These are the edit event component, and the event card component which displays all the information relevant to the event. I'm trying to pass the event ID in order to identify the relevant event to be edited or viewed. The useParams() hook is used to pass the ID. When I set up a route for the edit event feature and view event card feature, I get the following errors in the console.
The error shown in the edit event route is,
No routes matched location "/editEvent/(event ID)".
The error shown in the event card route is,
No routes matched location "/event/(event ID)"
The (event ID) contains the ID of the event that I'm trying to edit or view. The correct ID was visible in the address of the route.
I have attached the code of all components related to the edit event and event card features.
src/App.js
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import AddProject from './Components/AddProject';
import AllProjects from './Components/AllProjects';
import AddEvents from './Components/AddEvents';
import AllEvents from './Components/AllEvents';
import EditProject from './Components/EditProject';
import ProjectDetails from './Components/ProjectDetails';
import EventCard from './Components/EventCard';
import EditEvent from './Components/EditEvent';
import { NoMatch } from './Components/NoMatch';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<AddProject />} />
<Route path="/allProjects" element={<AllProjects />} />
<Route path="/addEvents/:projectName" element={<AddEvents />} />
<Route path="/allEvents/:projectName" element={<AllEvents />} />
<Route path="/editProject/:id" element={<EditProject />} />
<Route Path="/project/:id" element={<ProjectDetails />} />
<Route Path="/event/:id" element={<EventCard />} />
<Route Path="/editEvent/:id" element={<EditEvent/>} />
<Route Path='*' element={<NoMatch/>}></Route>
</Routes>
</Router>
);
}
export default App;
src/Components/AllEvents.js
import { React, useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { Button, Card } from 'react-bootstrap';
import axios from "axios";
function AllEvents() {
const [listOfEvents, setListOfEvents] = useState([]);
useEffect(() => {
axios.get("/getEvent").then((response) => {
setListOfEvents(response.data);
})
}, []);
const { projectName } = useParams();
const handleDelete = (_id) => {
axios.delete(`/deleteEvent/${_id}`)
.then((res) => {
console.log(res);
console.log(res.data);
})
const newList = listOfEvents.filter((event) => event._id !== _id);
alert("Event was deleted");
setListOfEvents(newList);
}
let navigate = useNavigate();
const filteredList = listOfEvents.filter((event) => event.projectName === projectName);
return (
<div id="allEvents">
<h1 style={{ textAlign: "center" }}>{projectName}</h1>
<h3>All Events</h3>
{filteredList.length > 0 ? (filteredList.map((events) => {
return (
<div>
<Card className="detailsCard" border="dark">
<div className="details">
<span className="title">Event Name:</span>
<span className="data">{events.eventName}</span>
</div>
<div className="details">
<span className="title">Event Description:</span>
<span className="data">{events.eventDescription}</span>
</div>
<div className="details">
<span className="title">Event Start Date:</span>
<span className="data">{events.eventStartDate}</span>
</div>
<div className="details">
<span className="title">Event End Date:</span>
<span className="data">{events.eventEndDate}</span>
</div>
<div>
<Button variant="success" size="sm" type="submit" onClick={() => { navigate(`/event/${events._id}`) }}>View Event Card</Button>
<Button className="eventButton" variant="warning" size="sm" type="submit" onClick={() => { navigate(`/editEvent/${events._id}`) }}>Edit Event</Button>
<Button className="eventButton" variant="danger" size="sm" type="submit" onClick={() => { handleDelete(events._id) }}>Delete Event</Button>
</div>
</Card>
</div>
);
})
) : (
<div>
<p>No events have been added yet</p>
</div>
)}
<br />
<Button variant="secondary" size="lg" onClick={() => { navigate(`/addEvents/${projectName}`) }}>Add new event</Button>
</div>
);
}
export default AllEvents;
src/Components/EditEvent.js
import { React, useState, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { Form, Card, Button,CloseButton } from 'react-bootstrap';
import axios from "axios";
function EditEvent() {
const [projectName, setProjectName] = useState();
const [eventName, setEventName] = useState();
const [eventDescription, setEventDescription] = useState();
const [eventStartDate, setEventStartDate] = useState();
const [eventEndDate, setEventEndDate] = useState();
const { id } = useParams();
let navigate = useNavigate();
const editEvent = () => {
axios.put(`/updateEvent/${id}`, {
eventName,
eventDescription,
eventStartDate,
eventEndDate
}).then((res) => {
alert("Project has been edited");
console.log("Project edited");
});
}
useEffect(() => {
axios.get(`/getEvent/${id}`).then((res) => {
setProjectName(res.data.events.projectName);
setEventName(res.data.events.eventName);
setEventDescription(res.data.events.eventDescription);
setEventStartDate(res.data.events.eventStartDate);
setEventEndDate(res.data.events.setEventEndDate);
console.log(res.data.events);
});
// eslint-disable-next-line
}, []);
return (
<div>
<div className="eventCard">
<Card border="dark" >
<Card.Header>
<div className="eventCardHeader">
Edit an Event
<CloseButton className="closeButton" onClick={() => { navigate(`/allEvents/${projectName}`) }} />
</div>
</Card.Header>
<Card.Body>
<Form>
<Form.Group>
<h5>Edit Event Name</h5>
<Form.Control as="textarea"
rows={1}
placeholder='Add Event Name'
value={eventName}
onChange={(event) => { setEventName(event.target.value) }}>
</Form.Control><br />
</Form.Group>
<Form.Group>
<h5>Edit Event Description</h5>
<Form.Control as="textarea"
rows={3}
placeholder='Add Event Description'
value={eventDescription}
onChange={(event) => { setEventDescription(event.target.value) }}>
</Form.Control><br />
</Form.Group>
<h5>Edit Event Duration</h5>
<Form.Label>Start Date</Form.Label><br />
<input
type="date"
min={new Date().toISOString().split('T')[0]}
max="2030-12-31"
value={eventStartDate}
onChange={(event) => { setEventStartDate(event.target.value) }} /><br />
<Form.Label>End Date</Form.Label><br />
<input
type="date"
min={new Date().toISOString().split('T')[0]}
max="2030-12-31"
value={eventEndDate}
onChange={(event) => { setEventEndDate(event.target.value) }} /><br />
</Form>
<Card.Footer style={{ paddingLeft: '50%' }}>
<Button variant="warning" size="lg" type="submit" onClick={editEvent}>Edit Project</Button>
</Card.Footer>
</Card.Body>
</Card>
</div>
</div>
);
}
export default EditEvent;
src/Components/EventCard.js
import { React, useEffect, useState } from "react";
import { useParams, useNavigate } from "react-router-dom";
import axios from "axios";
import { CloseButton } from 'react-bootstrap';
function EventCard(){
const [eventName,setEventName] = useState();
const [eventDescription,setEventDescription] = useState();
const [eventStartDate,setEventStartDate] = useState();
const [eventEndDate,setEventEndDate] = useState();
const { id } = useParams();
let navigate = useNavigate();
useEffect(() =>{
axios.get(`/getEvent/${id}`).then((res) => {
console.log("Hello");
setEventName(res.data.event.eventName);
setEventDescription(res.data.event.eventDescription);
setEventStartDate(res.data.event.eventStartDate);
setEventEndDate(res.data.event.eventEndDate);
console.log("EventData",res.data.event);
});
// eslint-disable-next-line
},[]);
return(
<div>
<CloseButton className="closeButton" onClick={() => { navigate("/allProjects") }} />
{eventName}
{eventDescription}
{eventStartDate}
{eventEndDate}
</div>
);
}
export default EventCard;
routes/events.js
const express = require('express');
const router = express.Router();
const eventModel = require('../models/Events');
// Add an event
router.post("/createEvent", async (req, res) => {
const event = req.body;
const newEvent = new eventModel(event);
await newEvent.save();
res.json(event);
});
// Retrieve all events
router.get("/getEvent", (req, res) => {
eventModel.find({}, (err, result) => {
if (err) {
res.json(err);
} else {
res.json(result);
}
});
});
// Retrieve a specific event
router.get("/getEvent/:id", (req,res) => {
let eventId = req.params.id;
eventModel.findById(eventId,(err,event) => {
if(err){
return res.status(400).json({success:false, err});
}
return res.status(200).json({
success:true,
event
});
});
});
// Update an event
router.put('/updateEvent/:id',(req,res) => {
eventModel.findByIdAndUpdate(
req.params.id,
{
$set:req.body
},
(err,updatedEvent) => {
if(err){
return res.status(400).json({error:err});
}
return res.status(200).json({
success:"Updated succesfully"
});
}
);
});
// Delete an event
router.delete('/deleteEvent/:id',(req,res) => {
eventModel.findByIdAndRemove(req.params.id).exec((err,deletedEvent) => {
if(err) return res.status(400).json({
message:"Delete unsuccessful",err
});
return res.json({
message:"Delete successful",deletedEvent
});
});
});
module.exports = router;
Server.js
const express = require('express');
const app = express();
const mongoose = require('mongoose');
const cors = require('cors');
const projectRoutes = require('./routes/projects');
const eventRoutes = require('./routes/events');
app.use(express.json());
app.use(cors());
app.use(projectRoutes);
app.use(eventRoutes);
app.get("/", (req, res) => {
res.send("Hello world");
}
);
//Actual url was removed when posting to stackoverflow
const DB_URL = '';
mongoose
.connect(DB_URL)
.then(() => {
console.log('MongoDB connected');
})
.catch((err) => console.log('DB connection error',err));
app.listen(5000, () => console.log("Server is running in port 5000"));
I appreciate any help that I can get.
It's been all day I tried to update a user profile but I keep getting an error Cannot read property _id null. I can't figure out whats the problem is. I've checked many times backend and frontend, Even checking other's Github repository but I cannot figure out where is the problem. Please help me out with this. Here is my code
And please is there any better way to fetch the user if I don't fetch from userInfo please tell me
if you want to check the full repository here is the GitHub link
Here is what I see in the console (
PUT /api/users/profile 500 62.771 ms - 642
Profile.js
import { useEffect, useState } from 'react';
import { Button, Col, Container, Form, InputGroup, Row } from 'react-bootstrap';
import { toast, ToastContainer } from 'react-toastify';
import { useDispatch, useSelector } from 'react-redux';
import { updateUserProfile } from '../actions/userActions';
// import { USER_UPDATE_PROFILE_RESET } from '../constant/userConstants';
const Profile = ({ history }) => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [pic, setPic] = useState();
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [picMessage, setPicMessage] = useState();
const [passwordType, setPasswordType] = useState('password');
const [passwordType2, setPasswordType2] = useState('password');
const [showPass, setShowPass] = useState(false);
const [showPass2, setShowPass2] = useState(false);
const dispatch = useDispatch();
// const userDetails = useSelector((state) => state.userDetails);
// const { user } = userDetails;
// console.log(` this is from line 25 ${user}`);
const userLogin = useSelector((state) => state.userLogin);
const { userInfo } = userLogin;
const userUpdateProfile = useSelector((state) => state.userUpdateProfile);
const { success } = userUpdateProfile;
useEffect(() => {
if (!userInfo) {
history.push('/login');
} else {
setName(userInfo.name);
setEmail(userInfo.email);
setPic(userInfo.pic);
}
if (success) {
return toast.success('Updated Successfully');
}
showPass ? setPasswordType('text') : setPasswordType('password');
showPass2 ? setPasswordType2('text') : setPasswordType2('password');
}, [showPass, showPass2, dispatch, history, userInfo, success]);
const postDetails = (pics) => {
setPicMessage(null);
if (pics.type === 'image/jpeg' || pics.type === 'image/png') {
const data = new FormData();
data.append('file', pics);
data.append('upload_preset', 'codeblogger_profile_image');
data.append('cloud_name', 'dhuej17x0');
fetch('https://api.cloudinary.com/v1_1/dhuej17x0/image/upload', {
method: 'post',
body: data,
})
.then((res) => res.json())
.then((data) => {
setPic(data.secure_url.toString());
})
.catch((err) => {
toast.error(err);
});
} else {
setPicMessage('Please Select an Image');
toast.error(picMessage);
}
};
const submitHandler = (e) => {
e.preventDefault();
dispatch(updateUserProfile({ name, email, password, pic }));
};
return (
<div className="profilePage mt-4 py-3">
<ToastContainer />
<Container>
<h2>PROFILE</h2>
<Row className="profileContainer">
<Col md={6}>
<Form onSubmit={submitHandler}>
<Form.Group controlId="name" className="mb-2">
<Form.Label>Name</Form.Label>
<Form.Control
type="name"
value={name}
placeholder="Enter Name"
onChange={(e) => setName(e.target.value)}
/>
</Form.Group>
<Form.Group controlId="email" className="mb-2">
<Form.Label>Email</Form.Label>
<Form.Control
type="email"
value={email}
placeholder="Enter email"
onChange={(e) => setEmail(e.target.value)}
/>
</Form.Group>
<Form.Group controlId="password" className="mb-2">
<Form.Label>New Password</Form.Label>
<InputGroup>
<Form.Control
type={passwordType}
placeholder="New Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<InputGroup.Text>
<i
onClick={() => setShowPass(!showPass)}
className={showPass ? 'fas fa-eye-slash' : 'fas fa-eye'}
style={{ cursor: 'pointer' }}></i>
</InputGroup.Text>
</InputGroup>
</Form.Group>
<Form.Group controlId="confirmPassword" className="mb-2">
<Form.Label>Confirm Password</Form.Label>
<InputGroup>
<Form.Control
type={passwordType2}
placeholder="Confirm Password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
/>
<InputGroup.Text>
<i
onClick={() => setShowPass2(!showPass2)}
className={showPass2 ? 'fas fa-eye-slash' : 'fas fa-eye'}
style={{ cursor: 'pointer' }}></i>
</InputGroup.Text>
</InputGroup>
</Form.Group>
<Form.Group controlId="pic" className="mb-2">
<Form.Label>Change Profile Picture</Form.Label>
<Form.File
onChange={(e) => postDetails(e.target.files[0])}
id="custom-file"
type="image/png"
custom
/>
</Form.Group>
<Button
type="submit"
variant="success"
style={{ letterSpacing: '2px' }}>
UPDATE
</Button>
</Form>
</Col>
<Col
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}>
<img src={pic} alt={name} className="profilePic" />
</Col>
</Row>
</Container>
</div>
);
};
export default Profile;
Here is userAction.js file
// User Details Action Start===========================================================================
export const getUserDetails = (id) => async (dispatch, getState) => {
try {
dispatch({
type: USER_DETAILS_REQUEST,
});
const {
userLogin: { userInfo },
} = getState();
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.get(`/api/users/${id}`, config);
dispatch({
type: USER_DETAILS_SUCCESS,
payload: data,
});
} catch (error) {
const message =
error.response && error.response.data.message
? error.response.data.message
: error.message;
if (message === 'Not authorized, token failed') {
dispatch(logout());
}
dispatch({
type: USER_DETAILS_FAIL,
payload: toast.error(message),
});
}
};
// User Details Action Complete===========================================================================
// User Profile Details Action Start===========================================================================
export const updateUserProfile = (user) => async (dispatch, getState) => {
try {
dispatch({
type: USER_UPDATE_PROFILE_REQUEST,
});
const {
userLogin: { userInfo },
} = getState();
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.put(`/api/users/profile`, user, config);
dispatch({
type: USER_UPDATE_PROFILE_SUCCESS,
payload: data,
});
dispatch({
type: USER_LOGIN_SUCCESS,
payload: data,
});
localStorage.setItem('userInfo', JSON.stringify(data));
} catch (error) {
const message =
error.response && error.response.data.message
? error.response.data.message
: error.message;
if (message === 'Not authorized, token failed') {
dispatch(logout());
}
dispatch({
type: USER_UPDATE_PROFILE_FAIL,
payload: toast.error(message),
});
}
};
// User Profile Details Action Complete===========================================================================
Backend Usercontroller.js file
export const updateUserProfile = asyncHandler(async (req, res) => {
const user = await User.findById(req.user._id);
if (user) {
user.name = req.body.name || user.name;
user.email = req.body.email || user.email;
user.pic = req.body.pic || user.pic;
if (req.body.password) {
user.password = req.body.password;
}
const updatedUser = await user.save();
res.json({
_id: updatedUser._id,
name: updatedUser.name,
email: updatedUser.email,
pic: updateUser.pic,
isAdmin: updatedUser.isAdmin,
token: generateToken(updatedUser._id),
});
} else {
res.status(404);
throw new Error('User not found');
}
});
routes.js file
import express from 'express';
import {
adminUpdateUserProfile,
deleteUser,
getUserById,
getUserProfile,
getUsers,
loginUser,
registerUser,
updateUserProfile,
} from '../controller/userController.js';
import { admin, protect } from '../middleware/authMiddleware.js';
const router = express.Router();
router.route('/').post(registerUser).get(protect, admin, getUsers);
router.route('/login').post(loginUser);
router
.route('/profile')
.get(protect, getUserProfile)
.put(protect, updateUserProfile);
router
.route('/:id')
.delete(protect, admin, deleteUser)
.get(protect, admin, getUserById)
.put(protect, admin, adminUpdateUserProfile);
export default router;
For some reason I cannot get the token from the localstorage in order to make the request, it says that there is no token. I am using cookie parser. I am trying to create a new category for my shop. It is not recognizing the token, although it is here.
here is my client:
adminDashoard.js
import { useState } from 'react';
import { createCategory } from './api/category';
import isEmpty from 'validator/lib/isEmpty';
import { showErrorMsg, showSuccessMsg } from './helpers/message';
import { showLoading } from './helpers/Loading'
export default function AdminDashboard() {
const [category, setCategory] = useState('');
const [errorMsg, setErrorMsg] = useState('');
const [successMsg, setSuccessMsg] = useState('');
const [loading, setLoading] = useState(false);
const handleMessages= evt =>{
setErrorMsg('');
setSuccessMsg('');
}
const handleCategoryChange = (evt) => {
setErrorMsg('');
setSuccessMsg('');
setCategory(evt.target.value);
}
const handleCategorySubmit = (evt) => {
evt.preventDefault();
if (isEmpty(category)) {
setErrorMsg('Please enter a category')
} else {
const data = { category }
setLoading(true);
createCategory(data)
.then(response => {
setLoading(false);
setSuccessMsg(response.data.successMessage)
})
.catch(err => {
setLoading(false);
setErrorMsg(err.response.data.errorMessage)
console.log(err)
})
}
};
function ShowHeader() {
return (
<div className='bg-dark text-white py-4'>
<div className='container'>
<div className='row'>
<div className='col-md-6'>
<h1>
<i className='fas fa-home'> Dashboard</i>
</h1>
</div>
</div>
</div>
</div>
)
}
function ShowActionBtns() {
return (
<div className='bg-light my-2'>
<div className='container'>
<div className='row pb-3'>
<div className='col-md-4 my-1 '>
<button
className='btn btn-outline-info btn-block'
data-toggle='modal'
data-target='#addCategoryModal'>
<i className=' fas fa-plus'>Add Category</i>
</button>
</div>
<div className='col-md-4 my-1 '>
<button className='btn btn-outline-danger btn-block'>
<i className=' fas fa-plus'>Add Products</i>
</button>
</div>
<div className='col-md-4 my-1 '>
<button className='btn btn-outline-success btn-block'>
<i className=' fas fa-plus'>Add Blog</i>
</button>
</div>
</div>
</div>
</div>
)
}
function ShowCategoryModal() {
return (
<div id='addCategoryModal' className='modal' onClick={handleMessages}>
<div className='modal-dialog modal-dialog-centered modal-lg'>
<div className='modal-content'>
<form onSubmit={handleCategorySubmit}>
<div className='modal-header bg-info text-white'>
<h5 className='modal-title'>Add Category</h5>
<button className='close' data-dismiss='modal'>
<span>
<i className='fas fa-times'></i>
</span>
</button>
</div>
<div className='modal-body my-2'>
{errorMsg && showErrorMsg(errorMsg)}
{successMsg && showSuccessMsg(successMsg)}
{
loading ? (
<div className='text-center'>{showLoading()}</div>
) : (
<>
<label className='text-secondary'> Category</label>
<input
type='text'
className='form-control'
name='category'
value={category}
onChange={handleCategoryChange}
/>
</>
)
}
</div>
<div className='modal-footer'>
<button data-dismiss='modal' className='btn btn-secondary'>Close</button>
<button className='btn btn-info' type='submit'>Submit</button>
</div>
</form>
</div>
</div>
</div>
)
}
return <div>
{ShowHeader()}
{ShowActionBtns()}
{ShowCategoryModal()}
</div>
}
Here is my api file:
import axios from "axios"
export const createCategory = async (formData) => {
const config = {
headers: {
'Content-Type': 'application/json'
},
};
const response = await axios.post('http://localhost:5000/api/category', formData, config);
return response;
}
on the server side,
here is my server.js :
const express=require('express');
const app= express();
const cors=require('cors');
const connectDB= require('./database/db');
const morgan= require('morgan');
const authRoutes= require ('./routes/auth')
const categoryRoutes = require ('./routes/category');
const cookieParser = require('cookie-parser')
//middleware
app.use(cors());
app.use(morgan('dev'));
app.use(express.json());
app.use(cookieParser());
app.use('/api/auth', authRoutes);
app.use('/api/category', categoryRoutes);
connectDB();
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Listening on port ${port}`));
app.get('/', (req, res) =>{
res.send(' hello server')
})
here is my route file :
const express = require('express');
const router = express.Router();
const categoryController = require('../routes/controllers/category');
const {authenticatateJWT} = require('./middleware/authenticator');
router.post('/', authenticatateJWT, categoryController.create);
module.exports = router;
here is my controller:
exports.create = (req, res)=>{
console.log(req.user);
setTimeout(() =>{
res.json({
successMessage: `${req.body.category} was created!`
});
}, 5000)
}
here is my middleware:
const jwt = require('jsonwebtoken');
const { jwtSecret } = require('../../config/keys');
exports.authenticatateJWT = (req, res, next) => {
const token = req.cookies.token;
console.log(token);
if (!token) {
return res.status(401).json({
errorMessage: 'No token. Authorization denied',
});
}
try {
const decoded = jwt.verify(token, jwtSecret);
req.user = decoded.user;
next();
} catch (err) {
console.log('jwt error:', err)
res.status(401).json({
errorMessage: 'Invalid token',
});
}
};