([]);
- const user: UsernameType = useOutletContext();
+ const user: UserType = useOutletContext();
const getParticipants = async () => {
try {
const response = await axiosClient.get(
@@ -90,22 +90,23 @@ function ParticipantsBar() {
};
useEffect(() => {
- if (participants.length > 0 && user?.user_id) {
+ console.error(participants.length, user.id);
+ if (participants.length > 0 && user?.id) {
const userIsAdmin = participants.some(
- (participant) =>
- participant.user_id === user.user_id && participant.isadmin,
+ (participant) => participant.user_id === user.id && participant.isadmin,
);
const userIsOwner = participants.some(
- (participant) =>
- participant.user_id === user.user_id && participant.isowner,
+ (participant) => participant.user_id === user.id && participant.isowner,
);
+
const whoIsOwner = participants.find(
(participant) => participant.isowner,
);
setGroupOwner(whoIsOwner?.user_id);
setMe({ isGroupAdmin: userIsAdmin, isGroupOwner: userIsOwner });
+ console.error('SETME: ', userIsAdmin, userIsOwner);
}
- }, [participants, user?.user_id]);
+ }, [participants, user?.id]);
useEffect(() => {
if (currentContact) {
@@ -140,7 +141,7 @@ function ParticipantsBar() {
const { group_id } = msg;
if (
msg.group_id == currentContact?.conversation_id &&
- msg.user_id == user?.user_id
+ msg.user_id == user?.id
) {
initializeContact({
read: true,
@@ -172,7 +173,7 @@ function ParticipantsBar() {
const handleLeftGroup = (msg: { user_id: string; group_id: string }) => {
if (
msg.group_id == currentContact?.conversation_id &&
- msg.user_id == user?.user_id
+ msg.user_id == user?.id
) {
setParticipants([]);
initializeContact(currentContact);
@@ -200,7 +201,7 @@ function ParticipantsBar() {
}) => {
console.log('(socket) removed administrator: ', msg);
if (msg.group_id === currentContact.conversation_id) {
- if (msg.user_id === user?.user_id) {
+ if (msg.user_id === user?.id) {
setMe({ isGroupAdmin: false, isGroupOwner: false });
}
setParticipants((prevMembers) =>
@@ -222,7 +223,7 @@ function ParticipantsBar() {
socket?.off('added to group');
socket?.off('left group');
};
- }, [socket, currentContact, currentContact, user?.user_id]);
+ }, [socket, currentContact, currentContact, user?.id]);
const ParticipantsList = sortedParticipants?.map(
(participant: ParticipantsProps) => (
@@ -255,7 +256,7 @@ function ParticipantsBar() {
- {user.user_id !== participant.user_id &&
+ {user.id !== participant.user_id &&
me.isGroupAdmin &&
(!participant.isadmin || me.isGroupOwner) ? (
@@ -298,7 +299,6 @@ function ParticipantsBar() {
Members
-
);
diff --git a/client/src/components/ui/sidebar.tsx b/client/src/components/ui/sidebar.tsx
index c1091cb..95d8426 100644
--- a/client/src/components/ui/sidebar.tsx
+++ b/client/src/components/ui/sidebar.tsx
@@ -93,7 +93,7 @@ const SidebarProvider = React.forwardRef<
: setOpen((open) => !open);
}, [isMobile, setOpen, setOpenMobile]);
- useEffect(() => {
+ React.useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (
event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
diff --git a/client/src/pages/Login.tsx b/client/src/pages/Login.tsx
index bf0ee8b..82a40c6 100644
--- a/client/src/pages/Login.tsx
+++ b/client/src/pages/Login.tsx
@@ -2,7 +2,7 @@ import { useForm, SubmitHandler } from 'react-hook-form';
import icon from '../../assets/icon.png';
import { Link, useNavigate } from 'react-router-dom';
import { useContext, useState } from 'react';
-import { AuthContext } from '../utils/AuthProvider.tsx';
+import { AuthContext } from '@/utils/AuthContext.tsx';
import LoadingWheel from '../components/chat/LoadingWheel.tsx';
import { axiosClient } from '@/utils/axiosClient.ts';
diff --git a/client/src/pages/Signup.tsx b/client/src/pages/Signup.tsx
index 892cd9a..e545a94 100644
--- a/client/src/pages/Signup.tsx
+++ b/client/src/pages/Signup.tsx
@@ -2,7 +2,7 @@ import icon from '../../assets/icon.png';
import { useForm, SubmitHandler } from 'react-hook-form';
import { Link, useNavigate } from 'react-router-dom';
import { useContext, useState } from 'react';
-import { AuthContext } from '../utils/AuthProvider.tsx';
+import { AuthContext } from '@/utils/AuthContext.tsx';
import LoadingWheel from '../components/chat/LoadingWheel.tsx';
import { axiosClient } from '@/utils/axiosClient.ts';
diff --git a/client/src/types/types.ts b/client/src/types/types.ts
index 4ac30fe..1ae871f 100644
--- a/client/src/types/types.ts
+++ b/client/src/types/types.ts
@@ -39,9 +39,9 @@ export type FileWithPreviewProps = {
preview: string | null;
};
-export type UsernameType = {
+export type UserType = {
username: string | null;
- user_id: string | null;
+ id: string | null;
};
export type ChatContextType = {
diff --git a/client/src/utils/AuthContext.tsx b/client/src/utils/AuthContext.tsx
new file mode 100644
index 0000000..1caed72
--- /dev/null
+++ b/client/src/utils/AuthContext.tsx
@@ -0,0 +1,16 @@
+import { createContext } from 'react';
+import { UserType } from '@/types/types.ts';
+
+interface AuthContextType {
+ authorized: boolean;
+ isLoading: boolean;
+ user: UserType | null;
+ setAuthorized: (value: boolean) => void;
+}
+
+export const AuthContext = createContext
({
+ authorized: false,
+ isLoading: true,
+ user: null,
+ setAuthorized: () => {},
+});
diff --git a/client/src/utils/AuthProvider.tsx b/client/src/utils/AuthProvider.tsx
index 991d944..226b25a 100644
--- a/client/src/utils/AuthProvider.tsx
+++ b/client/src/utils/AuthProvider.tsx
@@ -1,13 +1,48 @@
-import { createContext } from 'react';
+import { AuthContext } from './AuthContext';
+import Cookies from 'js-cookie';
+import { axiosClient } from '@/utils/axiosClient.ts';
+import { ReactNode, useEffect, useState } from 'react';
+import { UserType } from '@/types/types.ts';
-type AuthContextType = {
- authorized: boolean;
- isLoading: boolean;
- setAuthorized: (value: boolean) => void;
-};
+export function AuthProvider({ children }: { children: ReactNode }) {
+ const [authorized, setAuthorized] = useState(false);
+ const [isLoading, setIsLoading] = useState(true);
+ const [user, setUser] = useState(null);
+ const token = Cookies.get('token');
-export const AuthContext = createContext({
- authorized: false,
- isLoading: true,
- setAuthorized: () => {},
-});
+ useEffect(() => {
+ async function validateAuth() {
+ if (!token) {
+ setIsLoading(false);
+ return;
+ }
+
+ try {
+ const response = await axiosClient.get('/api/auth/validate', {
+ withCredentials: true,
+ });
+ setUser({
+ username: response.data.username,
+ id: response.data.user_id,
+ });
+ setAuthorized(true);
+ } catch (error) {
+ console.error('Auth validation failed:', error);
+ setAuthorized(false);
+ setUser(null);
+ } finally {
+ setIsLoading(false);
+ }
+ }
+
+ validateAuth();
+ }, [token]);
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/client/src/utils/ProtectedRoutes.tsx b/client/src/utils/ProtectedRoutes.tsx
index e09acfb..5dd4d87 100644
--- a/client/src/utils/ProtectedRoutes.tsx
+++ b/client/src/utils/ProtectedRoutes.tsx
@@ -1,34 +1,15 @@
import { Navigate, Outlet } from 'react-router-dom';
-import { useContext, useEffect, useState } from 'react';
-import { AuthContext } from './AuthProvider.tsx';
-import LoadingScreen from '../components/LoadingScreen.tsx';
-import { UsernameType } from '@/types/types.ts';
-import { axiosClient } from '@/utils/axiosClient.ts';
+import { useAuth } from '@/utils/useAuth.tsx';
+import LoadingScreen from '@/components/LoadingScreen';
function ProtectedRoutes() {
- const { authorized, isLoading } = useContext(AuthContext);
- const [user, setUser] = useState({
- username: null,
- user_id: null,
- });
-
- useEffect(() => {
- if (authorized) {
- axiosClient
- .get('/api/auth/validate', { withCredentials: true })
- .then((res) => {
- setUser(res.data);
- })
- .catch(console.error);
- }
- }, [authorized]);
-
+ const { authorized, isLoading, user } = useAuth();
if (isLoading) {
return ;
}
return authorized ? (
-
+
) : (
);
diff --git a/client/src/utils/PublicRoute.tsx b/client/src/utils/PublicRoute.tsx
index d784e91..850c890 100644
--- a/client/src/utils/PublicRoute.tsx
+++ b/client/src/utils/PublicRoute.tsx
@@ -1,10 +1,9 @@
import { Navigate, Outlet } from 'react-router-dom';
-import { useContext } from 'react';
-import { AuthContext } from './AuthProvider';
-import LoadingScreen from '../components/LoadingScreen';
+import { useAuth } from '@/utils/useAuth.tsx';
+import LoadingScreen from '@/components/LoadingScreen';
function PublicRoute() {
- const { authorized, isLoading } = useContext(AuthContext);
+ const { authorized, isLoading } = useAuth();
if (isLoading) {
return ;
diff --git a/client/src/utils/useAuth.tsx b/client/src/utils/useAuth.tsx
index 44db8f4..239ef19 100644
--- a/client/src/utils/useAuth.tsx
+++ b/client/src/utils/useAuth.tsx
@@ -1,33 +1,4 @@
-import { useState, useEffect } from 'react';
-import Cookies from 'js-cookie';
+import { useContext } from 'react';
+import { AuthContext } from '@/utils/AuthContext.tsx';
-import { axiosClient } from '@/utils/axiosClient.ts';
-
-function useAuth() {
- const [authorized, setAuthorized] = useState(false);
-
- useEffect(() => {
- async function validateToken() {
- const token = Cookies.get('token');
- if (!token) {
- setAuthorized(false);
- return;
- }
-
- try {
- await axiosClient.get('/api/auth/validate', { withCredentials: true });
-
- setAuthorized(true);
- } catch (e) {
- setAuthorized(false);
- console.log('Failed to validate token: ', e);
- }
- }
-
- validateToken();
- }, []);
-
- return authorized;
-}
-
-export default useAuth;
+export const useAuth = () => useContext(AuthContext);
diff --git a/docker-compose.yml b/docker-compose.yml
index c6549f6..91f05cc 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -13,6 +13,8 @@ services:
PG_HOST: db
ports:
- "3000"
+ volumes:
+ - attachments:/app/client/server/attachments
depends_on:
db:
condition: service_healthy