diff --git a/client/src/App.jsx b/client/src/App.jsx new file mode 100644 index 00000000..df4cd2db --- /dev/null +++ b/client/src/App.jsx @@ -0,0 +1,118 @@ +import { useEffect, useState } from 'react'; +import { Navigate, Route, Routes } from 'react-router-dom'; + +import { KindeProvider } from '@kinde-oss/kinde-auth-react'; +import ReactGA from 'react-ga4'; + +// Store +import { useAuth } from 'context/AuthContext'; +import { useApp } from 'src/context/AppContext'; + +// Components +import NavBar from 'components/NavBar'; +import ProtectedRoutes from 'components/ProtectedRoutes'; +import { api } from 'src/lib/axios'; + +// Pages +import Start from 'pages/Start'; +import Searching from 'pages/Searching'; +import ComingSoon from 'pages/ComingSoon'; +import Profile from './pages/Profile'; +import Login from 'pages/Login'; +import Settings from 'pages/Settings'; +import NoPage from './pages/NoPage'; + +import useIsTabActive from './hooks/useIsTabActive'; + +const clientID = import.meta.env.VITE_IMPORTANT; + +function App() { + ReactGA.initialize('G-HL8CN4JFXN'); + + const { isLoggedIn, dispatchAuth } = useAuth(); + const { loadUserSettings, updateOnlineStatus, app } = useApp(); + + const { settings } = app; + const [onlineStatus, setOnlineStatus] = useState(null); + + const isTabActive = useIsTabActive(); + + async function loginWithEmail(email) { + try { + const response = await api.post('/login', { + email, + }); + + if (response.status === 200) { + const data = await response.data; + const userID = data.id; + + dispatchAuth({ + type: 'LOGIN', + payload: { + loginType: 'email', + loginId: userID, + email, + }, + }); + try { + const userData = await api.get(`/profile/${email}`); + loadUserSettings(userData.data?.settings); + } catch (error) { + console.error('Error loading user data:', error); + } + } else { + throw new Error('Login failed'); + } + } catch (err) { + console.error('Error logging in:', err); + } + } + + useEffect(() => { + if (!isLoggedIn) { + return; + } + + if (isTabActive) { + setOnlineStatus('online'); + } else { + setOnlineStatus(new Date()); + } + }, [isTabActive]); + + useEffect(() => { + updateOnlineStatus(onlineStatus); + }, [onlineStatus]); + + return ( + { + loginWithEmail(user.email); + }} + > +
+ {isLoggedIn && } + + }> + } /> + {/* TODO: Sepreate searching and foundUser into different routes */} + } /> + } /> + } /> + } /> + + + : } /> + } /> + +
+
+ ); +} + +export default App; diff --git a/client/src/components/Chat/DropDownOption.jsx b/client/src/components/Chat/DropDownOption.jsx index a05b39c8..ff3aea6b 100644 --- a/client/src/components/Chat/DropDownOption.jsx +++ b/client/src/components/Chat/DropDownOption.jsx @@ -11,14 +11,10 @@ import { useApp } from 'src/context/AppContext'; import { socket } from 'src/lib/socketConnection'; import useChatUtils from 'src/lib/chatSocket'; -import useCryptoKeys from 'src/hooks/useCryptoKeys'; -const DropDownOptions =({ id, isSender, inputRef, cancelEdit, setEditing, setReplyId }) => { - +const DropDownOptions = ({ id, isSender, inputRef, cancelEdit, setEditing, setReplyId }) => { const { app } = useApp(); - const { importedPrivateKey, cryptoKey - } =useCryptoKeys(app.currentChatId); const { messages: state, updateMessage, removeMessage } = useChat(); const { getMessage, messageExists, handleCopyToClipBoard } = chatHelper(state, app); const { deleteMessage } = useChatUtils(socket); @@ -91,7 +87,7 @@ const DropDownOptions =({ id, isSender, inputRef, cancelEdit, setEditing, setRep > handleEdit(id)}>Edit - handleCopyToClipBoard(id,importedPrivateKey)}>Copy + handleCopyToClipBoard(id, state, app)}>Copy setReplyId(id)}>Reply handleDelete(id)}>Delete @@ -106,7 +102,7 @@ const DropDownOptions =({ id, isSender, inputRef, cancelEdit, setEditing, setRep renderToggle={renderIconButtonReceiver} NoCaret > - handleCopyToClipBoard(id,cryptoKey)}>Copy + handleCopyToClipBoard(id, state, app)}>Copy setReplyId(id)}>Reply ); diff --git a/client/src/hooks/useCryptoKeys.js b/client/src/hooks/useCryptoKeys.js index d5b8dd67..8cf0a9bd 100644 --- a/client/src/hooks/useCryptoKeys.js +++ b/client/src/hooks/useCryptoKeys.js @@ -1,4 +1,4 @@ -import { useState,useEffect } from 'react'; +import { useState, } from 'react'; import { convertArrayBufferToPem } from 'src/lib/chatHelper'; import { NEW_EVENT_REQUEST_PUBLIC_KEY } from '../../../constants.json' @@ -10,66 +10,11 @@ const useCryptoKeys = (currentChatId) => { const [importedPublicKey, setImportedPublicKey] = useState(null); const [importedPrivateKey, setImportedPrivateKey] = useState(null); const [cryptoKey, setCryptoKey] = useState(null); - // Retrieve keys from local storage - const storedCryptoKey = localStorage.getItem('cryptoKey' + currentChatId); - const storedPublicKey = localStorage.getItem('importPublicKey' + currentChatId); - const storedPrivateKey = localStorage.getItem('importedPrivateKey' + currentChatId); - - useEffect(()=>{ - - const fetchData = async () => { - if(storedCryptoKey){ - const privateKeyArray = new Uint8Array(JSON.parse(storedCryptoKey)); - const importedPrivateKey = await crypto.subtle.importKey( - 'pkcs8', - privateKeyArray.buffer, - { - name: 'RSA-OAEP', - hash: { name: 'SHA-256' }, - }, - true, - ['decrypt'] - ); - setCryptoKey(importedPrivateKey); - } - if(storedPublicKey && storedPrivateKey){ - const publicKeyArray01 = new Uint8Array(JSON.parse(storedPublicKey)); - const privateKeyArray01 = new Uint8Array(JSON.parse(storedPrivateKey)); - const importedPublicKey = await crypto.subtle.importKey( - 'spki', - publicKeyArray01, - { - name: 'RSA-OAEP', - hash: { name: 'SHA-256' }, - }, - true, - ['encrypt'] - ); - - setImportedPublicKey(importedPublicKey); - - const importedPrivateKey01 = await crypto.subtle.importKey( - 'pkcs8', - privateKeyArray01 , - { - name: 'RSA-OAEP', - hash: { name: 'SHA-256' }, - }, - true, - ['decrypt'] - ); - - setImportedPrivateKey(importedPrivateKey01); - - } - } - fetchData() - - },[currentChatId]) // Function to import public and private keys const importKey = async (publicArrayBuffer, privateArrayBuffer) => { - + const storedPublicKey = localStorage.getItem('importPublicKey' + currentChatId); + const storedPrivateKey = localStorage.getItem('importedPrivateKey' + currentChatId); // Import public key const importedPublicKey = await crypto.subtle.importKey( @@ -122,7 +67,10 @@ const useCryptoKeys = (currentChatId) => { // Function to generate a new key pair const generateKeyPair = async () => { - + const storedCryptoKey = localStorage.getItem('cryptoKey' + currentChatId); + const storedPublicKey = localStorage.getItem('importPublicKey' + currentChatId); + const storedPrivateKey = localStorage.getItem('importedPrivateKey' + currentChatId); + let pemPrivateKey; // Generate a new RSA key pair @@ -192,4 +140,4 @@ const useCryptoKeys = (currentChatId) => { return { importedPublicKey, importedPrivateKey, cryptoKey, importKey, generateKeyPair }; }; -export default useCryptoKeys; \ No newline at end of file +export default useCryptoKeys; diff --git a/client/src/lib/chatHelper.js b/client/src/lib/chatHelper.js index b00ee70d..9a617f54 100644 --- a/client/src/lib/chatHelper.js +++ b/client/src/lib/chatHelper.js @@ -1,7 +1,4 @@ -import decryptMessage from './decryptMessage'; - export default (state, app) => { - const getMessage = (id) => { if (!state[app.currentChatId]) { return null; @@ -30,19 +27,15 @@ export default (state, app) => { }); }; - const handleCopyToClipBoard = async (id,key) => { - + const handleCopyToClipBoard = async (id) => { const { message } = getMessage(id, state, app); - - const decryptedMessage =await decryptMessage(message,key) - if (message.includes('Warning Message')) { return; } if ('clipboard' in navigator) { - return await navigator.clipboard.writeText(decryptedMessage); + return await navigator.clipboard.writeText(message); } else { - return document.execCommand('copy', true, decryptedMessage); + return document.execCommand('copy', true, message); } };