added missing files to git, refactor authorization
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.idea
|
||||||
5
.idea/.gitignore
generated
vendored
5
.idea/.gitignore
generated
vendored
@@ -1,5 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/relay.iml" filepath="$PROJECT_DIR$/.idea/relay.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
12
.idea/relay.iml
generated
12
.idea/relay.iml
generated
@@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="WEB_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
2
client/assets/logout.svg
Normal file
2
client/assets/logout.svg
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg" id="memory-logout"><path d="M17 1V2H18V6H17V5H16V3H6V19H16V17H17V16H18V20H17V21H5V20H4V2H5V1H17M13 6H15V7H16V8H17V9H18V10H19V12H18V13H17V14H16V15H15V16H13V14H14V13H15V12H8V10H15V9H14V8H13V6Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 423 B |
2
client/assets/read.svg
Normal file
2
client/assets/read.svg
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg" id="memory-tooltip-above"><path d="M2 1H20V2H21V16H20V17H15V18H14V19H13V20H12V21H10V20H9V19H8V18H7V17H2V16H1V2H2V1M3 3V15H8V16H9V17H10V18H12V17H13V16H14V15H19V3H3Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 396 B |
2
client/assets/right-point.svg
Normal file
2
client/assets/right-point.svg
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg" id="memory-menu-right-fill"><path d="M9 5H8V17H9V16H10V15H11V14H12V13H13V12H14V10H13V9H12V8H11V7H10V6H9" /></svg>
|
||||||
|
After Width: | Height: | Size: 336 B |
2
client/assets/unread.svg
Normal file
2
client/assets/unread.svg
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg" id="memory-tooltip-above-text"><path d="M2 1H20V2H21V16H20V17H15V18H14V19H13V20H12V21H10V20H9V19H8V18H7V17H2V16H1V2H2V1M3 3V15H8V16H9V17H10V18H12V17H13V16H14V15H19V3H3M5 6H17V8H5V6M5 10H15V12H5V10Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 430 B |
2
client/assets/user-box.svg
Normal file
2
client/assets/user-box.svg
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg" id="memory-account-box"><path d="M4 2H18V3H19V4H20V18H19V19H18V20H4V19H3V18H2V4H3V3H4V2M4 16H5V15H7V14H15V15H17V16H18V5H17V4H5V5H4V16M16 18V17H14V16H8V17H6V18H16M9 5H13V6H14V7H15V11H14V12H13V13H9V12H8V11H7V7H8V6H9V5M12 8V7H10V8H9V10H10V11H12V10H13V8H12Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 486 B |
@@ -3,10 +3,11 @@ import {
|
|||||||
createBrowserRouter,
|
createBrowserRouter,
|
||||||
Navigate,
|
Navigate,
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
|
import { useState } from 'react';
|
||||||
import Chat from './pages/Chat.tsx';
|
import Chat from './pages/Chat.tsx';
|
||||||
import Login from './pages/Login.tsx';
|
import Login from './pages/Login.tsx';
|
||||||
import Signup from './pages/Signup.tsx';
|
import Signup from './pages/Signup.tsx';
|
||||||
import ProtectedRoutes from './utils/ProtectedRoutes.tsx';
|
import ProtectedRoutes, { AuthContext } from './utils/ProtectedRoutes.tsx';
|
||||||
import Settings from './pages/Settings.tsx';
|
import Settings from './pages/Settings.tsx';
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
@@ -42,6 +43,13 @@ const router = createBrowserRouter([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return <RouterProvider router={router} />;
|
const [authorized, setAuthorized] = useState<boolean | null>(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AuthContext.Provider value={{ authorized, setAuthorized }}>
|
||||||
|
<RouterProvider router={router} />
|
||||||
|
</AuthContext.Provider>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
58
client/src/components/chat/MessageForm.tsx
Normal file
58
client/src/components/chat/MessageForm.tsx
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { sendMessage } from '../../socket/socket.tsx';
|
||||||
|
import { useForm, SubmitHandler } from 'react-hook-form';
|
||||||
|
type Input = {
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
type MessaFormProps = {
|
||||||
|
contact: string;
|
||||||
|
};
|
||||||
|
function messageForm({ contact }: MessaFormProps) {
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
reset,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm<Input>();
|
||||||
|
|
||||||
|
// Sending message
|
||||||
|
const submitMessage: SubmitHandler<Input> = (data) => {
|
||||||
|
console.log(contact);
|
||||||
|
// block sending empty message
|
||||||
|
if (!data.message) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('sended message: ' + data.message + ' recipient: ', contact);
|
||||||
|
sendMessage(data.message, contact);
|
||||||
|
reset({ message: '' });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<form onSubmit={handleSubmit(submitMessage)}>
|
||||||
|
<div className="flex">
|
||||||
|
<input
|
||||||
|
className=" bg-green-50 text-black rounded-md w-full ml-1 mr-1 size-10"
|
||||||
|
type="text"
|
||||||
|
autoFocus={!!contact}
|
||||||
|
disabled={!contact}
|
||||||
|
placeholder="Enter message"
|
||||||
|
{...register('message', {
|
||||||
|
maxLength: 500,
|
||||||
|
minLength: 1,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
{errors?.message?.type === 'maxLength' && (
|
||||||
|
<p>Maximum length of the message is 500</p>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
className="text-black bg-green-500 hover:bg-green-400 font-bold py-2 px-4 rounded mr-1 w-24 "
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default messageForm;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import io from 'socket.io-client';
|
import io from 'socket.io-client';
|
||||||
import Cookie from 'js-cookie';
|
import Cookie from 'js-cookie';
|
||||||
const token = Cookie.get('token');
|
const token = Cookie.get('token');
|
||||||
|
import { authorized } from '../utils/ProtectedRoutes.tsx';
|
||||||
//TODO socket is trying to connect on login page fix it
|
//TODO socket is trying to connect on login page fix it
|
||||||
|
|
||||||
const socket = io({
|
const socket = io({
|
||||||
@@ -9,7 +10,9 @@ const socket = io({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('connect', () => console.log('connected'));
|
if (authorized) {
|
||||||
|
socket.on('connect', () => console.log('connected'));
|
||||||
|
}
|
||||||
|
|
||||||
socket.on('disconnect', () => {
|
socket.on('disconnect', () => {
|
||||||
console.log('Disconnected from server');
|
console.log('Disconnected from server');
|
||||||
|
|||||||
61
client/src/utils/ProtectedRoutes.tsx
Normal file
61
client/src/utils/ProtectedRoutes.tsx
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// ProtectedRoutes.tsx
|
||||||
|
import { Navigate, Outlet } from 'react-router-dom';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { useState, useEffect, createContext, useContext } from 'react';
|
||||||
|
import Cookie from 'js-cookie';
|
||||||
|
|
||||||
|
export type UsernameType = {
|
||||||
|
username: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
type AuthContextType = {
|
||||||
|
authorized: boolean | null;
|
||||||
|
setAuthorized: (value: boolean | null) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AuthContext = createContext<AuthContextType>({
|
||||||
|
authorized: null,
|
||||||
|
setAuthorized: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const useAuth = () => useContext(AuthContext);
|
||||||
|
|
||||||
|
function ProtectedRoutes() {
|
||||||
|
const { authorized, setAuthorized } = useAuth();
|
||||||
|
const [username, setUsername] = useState<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function validateToken() {
|
||||||
|
const token = Cookie.get('token');
|
||||||
|
if (!token) {
|
||||||
|
setAuthorized(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
axios
|
||||||
|
.get('/api/auth/validate', { withCredentials: true })
|
||||||
|
.then((res) => {
|
||||||
|
setUsername(res.data.username);
|
||||||
|
console.log(res.data.username);
|
||||||
|
setAuthorized(true);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
setAuthorized(false);
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
validateToken();
|
||||||
|
}, [setAuthorized]);
|
||||||
|
|
||||||
|
if (authorized === null) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorized ? (
|
||||||
|
<Outlet context={{ username } satisfies UsernameType} />
|
||||||
|
) : (
|
||||||
|
<Navigate to="/login" replace />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProtectedRoutes;
|
||||||
1
server/.gitignore
vendored
Normal file
1
server/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
node_modules/
|
||||||
3
server/.prettierignore
Normal file
3
server/.prettierignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Ignore artifacts:
|
||||||
|
build
|
||||||
|
coverage
|
||||||
1
server/.prettierrc
Normal file
1
server/.prettierrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -17,8 +17,10 @@ function verifyJwtToken(token) {
|
|||||||
try {
|
try {
|
||||||
const decoded = jwt.verify(token, jwtSecret);
|
const decoded = jwt.verify(token, jwtSecret);
|
||||||
if (decoded.user_id) {
|
if (decoded.user_id) {
|
||||||
|
console.log("verifyJwtToken decoded: ", decoded);
|
||||||
return { username: decoded.username, user_id: decoded.user_id };
|
return { username: decoded.username, user_id: decoded.user_id };
|
||||||
}
|
}
|
||||||
|
console.log("verifyJwtToken decoded: ", decoded);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e.message);
|
console.error(e.message);
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
1907
server/package-lock.json
generated
Normal file
1907
server/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
18
server/package.json
Normal file
18
server/package.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"bcrypt": "^5.1.1",
|
||||||
|
"body-parser": "^1.20.3",
|
||||||
|
"cookie-parser": "^1.4.6",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
|
"express": "^4.21.0",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"nanoid": "^5.0.7",
|
||||||
|
"pg": "^8.13.0",
|
||||||
|
"socket.io": "^4.8.0",
|
||||||
|
"uuid": "^10.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"prettier": "3.3.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ function initializeSocket(io) {
|
|||||||
io.use((socket, next) => {
|
io.use((socket, next) => {
|
||||||
const token = socket.handshake.auth.token;
|
const token = socket.handshake.auth.token;
|
||||||
if (!token) {
|
if (!token) {
|
||||||
console.log("Not logged in");
|
console.log("(socket) Not logged in");
|
||||||
return next(new Error("Not logged in"));
|
return next(new Error("Not logged in"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user