Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add JWT for Authentication and Authorization #37

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 15 additions & 17 deletions public/src/components/ChatContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,43 @@ import Logout from "./Logout";
import { v4 as uuidv4 } from "uuid";
import axios from "axios";
import { sendMessageRoute, recieveMessageRoute } from "../utils/APIRoutes";
import userById from "../utils/backendCall";

export default function ChatContainer({ currentChat, socket }) {
const [messages, setMessages] = useState([]);
const scrollRef = useRef();
const [arrivalMessage, setArrivalMessage] = useState(null);

useEffect(async () => {
const data = await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
);
const response = await axios.post(recieveMessageRoute, {
from: data._id,
to: currentChat._id,
});
setMessages(response.data);
useEffect(() => {
async function fetchData() {
const user = await userById();
const response = await axios.post(recieveMessageRoute, {
from: user._id,
to: currentChat._id,
});
setMessages(response.data);
}
fetchData();
}, [currentChat]);

useEffect(() => {
const getCurrentChat = async () => {
if (currentChat) {
await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
)._id;
await userById()._id;
}
};
getCurrentChat();
}, [currentChat]);

const handleSendMsg = async (msg) => {
const data = await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
);
const user = await userById();
socket.current.emit("send-msg", {
to: currentChat._id,
from: data._id,
from: user._id,
msg,
});
await axios.post(sendMessageRoute, {
from: data._id,
from: user._id,
to: currentChat._id,
message: msg,
});
Expand Down
16 changes: 10 additions & 6 deletions public/src/components/Contacts.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import React, { useState, useEffect } from "react";
import styled from "styled-components";
import Logo from "../assets/logo.svg";
import userById from "../utils/backendCall";

export default function Contacts({ contacts, changeChat }) {
const [currentUserName, setCurrentUserName] = useState(undefined);
const [currentUserImage, setCurrentUserImage] = useState(undefined);
const [currentSelected, setCurrentSelected] = useState(undefined);
useEffect(async () => {
const data = await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
);
setCurrentUserName(data.username);
setCurrentUserImage(data.avatarImage);

useEffect(() => {
async function fetchData() {
const user = await userById();
setCurrentUserName(user.username);
setCurrentUserImage(user.avatarImage);
}
fetchData();
}, []);

const changeCurrentChat = (index, contact) => {
setCurrentSelected(index);
changeChat(contact);
Expand Down
13 changes: 9 additions & 4 deletions public/src/components/Logout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ import { BiPowerOff } from "react-icons/bi";
import styled from "styled-components";
import axios from "axios";
import { logoutRoute } from "../utils/APIRoutes";
import userById from "../utils/backendCall";
export default function Logout() {
const navigate = useNavigate();
const handleClick = async () => {
const id = await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
)._id;
const data = await axios.get(`${logoutRoute}/${id}`);
const user = await userById();
const data = await axios.get(`${logoutRoute}/${user._id}`, {
headers: {
Authorization: `Bearer ${localStorage.getItem(
process.env.REACT_APP_LOCALHOST_KEY
)}`,
},
});
if (data.status === 200) {
localStorage.clear();
navigate("/login");
Expand Down
55 changes: 35 additions & 20 deletions public/src/components/SetAvatar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { useNavigate } from "react-router-dom";
import { setAvatarRoute } from "../utils/APIRoutes";
import userById from "../utils/backendCall";
export default function SetAvatar() {
const api = `https://api.multiavatar.com/4645646`;
const navigate = useNavigate();
Expand All @@ -21,29 +22,40 @@ export default function SetAvatar() {
theme: "dark",
};

useEffect(async () => {
if (!localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY))
useEffect(() => {
if (!localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)) {
navigate("/login");
}
}, []);

const setProfilePicture = async () => {
if (selectedAvatar === undefined) {
toast.error("Please select an avatar", toastOptions);
} else {
const user = await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
const user = await userById();
const { data } = await axios.post(
`${setAvatarRoute}/${user._id}`,
{
image: avatars[selectedAvatar],
},
{
headers: {
Authorization: `Bearer ${localStorage.getItem(
process.env.REACT_APP_LOCALHOST_KEY
)}`,
},
}
);

const { data } = await axios.post(`${setAvatarRoute}/${user._id}`, {
image: avatars[selectedAvatar],
});

if (data.isSet) {
user.isAvatarImageSet = true;
user.avatarImage = data.image;
localStorage.setItem(
process.env.REACT_APP_LOCALHOST_KEY,
JSON.stringify(user)
"ImageInfo",
JSON.stringify({
isAvatarSet: user.isAvatarImageSet,
avatarImage: user.avatarImage,
})
);
navigate("/");
} else {
Expand All @@ -52,17 +64,20 @@ export default function SetAvatar() {
}
};

useEffect(async () => {
const data = [];
for (let i = 0; i < 4; i++) {
const image = await axios.get(
`${api}/${Math.round(Math.random() * 1000)}`
);
const buffer = new Buffer(image.data);
data.push(buffer.toString("base64"));
useEffect(() => {
async function fetchData() {
const data = [];
for (let i = 0; i < 4; i++) {
const image = await axios.get(
`${api}/${Math.round(Math.random() * 1000)}`
);
const buffer = new Buffer(image.data);
data.push(buffer.toString("base64"));
}
setAvatars(data);
setIsLoading(false);
}
setAvatars(data);
setIsLoading(false);
fetchData();
}, []);
return (
<>
Expand Down
13 changes: 7 additions & 6 deletions public/src/components/Welcome.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import React, { useState, useEffect } from "react";
import styled from "styled-components";
import Robot from "../assets/robot.gif";
import userById from "../utils/backendCall";
export default function Welcome() {
const [userName, setUserName] = useState("");
useEffect(async () => {
setUserName(
await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
).username
);
useEffect(() => {
async function fetchData() {
const user = await userById();
setUserName(user.username);
}
fetchData();
}, []);
return (
<Container>
Expand Down
46 changes: 30 additions & 16 deletions public/src/pages/Chat.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,55 @@ import { allUsersRoute, host } from "../utils/APIRoutes";
import ChatContainer from "../components/ChatContainer";
import Contacts from "../components/Contacts";
import Welcome from "../components/Welcome";
import userById from "../utils/backendCall";

export default function Chat() {
const navigate = useNavigate();
const socket = useRef();
const [contacts, setContacts] = useState([]);
const [currentChat, setCurrentChat] = useState(undefined);
const [currentUser, setCurrentUser] = useState(undefined);
useEffect(async () => {
if (!localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)) {
navigate("/login");
} else {
setCurrentUser(
await JSON.parse(
localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)
)
);
useEffect(() => {
async function fetchData() {
if (!localStorage.getItem(process.env.REACT_APP_LOCALHOST_KEY)) {
navigate("/login");
} else {
const user = await userById();
setCurrentUser(user);
}
}
fetchData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
if (currentUser) {
socket.current = io(host);
socket.current.emit("add-user", currentUser._id);
}
}, [currentUser]);

useEffect(async () => {
if (currentUser) {
if (currentUser.isAvatarImageSet) {
const data = await axios.get(`${allUsersRoute}/${currentUser._id}`);
setContacts(data.data);
} else {
navigate("/setAvatar");
useEffect(() => {
async function fetchData() {
if (currentUser) {
if (currentUser.isAvatarImageSet) {
const data = await axios.get(`${allUsersRoute}/${currentUser._id}`, {
headers: {
Authorization: `Bearer ${localStorage.getItem(
process.env.REACT_APP_LOCALHOST_KEY
)}`,
},
});
setContacts(data.data);
} else {
navigate("/setAvatar");
}
}
}
fetchData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentUser]);

const handleChatChange = (chat) => {
setCurrentChat(chat);
};
Expand Down
6 changes: 1 addition & 5 deletions public/src/pages/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,7 @@ export default function Login() {
toast.error(data.msg, toastOptions);
}
if (data.status === true) {
localStorage.setItem(
process.env.REACT_APP_LOCALHOST_KEY,
JSON.stringify(data.user)
);

localStorage.setItem(process.env.REACT_APP_LOCALHOST_KEY, data.token);
navigate("/");
}
}
Expand Down
5 changes: 1 addition & 4 deletions public/src/pages/Register.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,7 @@ export default function Register() {
toast.error(data.msg, toastOptions);
}
if (data.status === true) {
localStorage.setItem(
process.env.REACT_APP_LOCALHOST_KEY,
JSON.stringify(data.user)
);
localStorage.setItem(process.env.REACT_APP_LOCALHOST_KEY, data.token);
navigate("/");
}
}
Expand Down
1 change: 1 addition & 0 deletions public/src/utils/APIRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export const allUsersRoute = `${host}/api/auth/allusers`;
export const sendMessageRoute = `${host}/api/messages/addmsg`;
export const recieveMessageRoute = `${host}/api/messages/getmsg`;
export const setAvatarRoute = `${host}/api/auth/setavatar`;
export const userByIdURL = `${host}/api/auth/userById`;
19 changes: 19 additions & 0 deletions public/src/utils/backendCall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import axios from "axios";
import { userByIdURL } from "./APIRoutes";

const userById = async () => {
try {
const response = await axios.get(`${userByIdURL}`, {
headers: {
Authorization: `Bearer ${localStorage.getItem(
process.env.REACT_APP_LOCALHOST_KEY
)}`,
},
});
return response.data;
} catch (err) {
console.log(err);
}
};

export default userById;
3 changes: 2 additions & 1 deletion server/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
PORT=5000
MONGO_URL="mongodb://localhost:27017/chat"
MONGO_URL="mongodb://localhost:27017/chat"
JWT_SECRET="your-secret-key"
3 changes: 2 additions & 1 deletion server/.env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
PORT=5000
MONGO_URL="mongodb://localhost:27017/chat"
MONGO_URL="mongodb://localhost:27017/chat"
JWT_SECRET="your-secret-key"
Loading