Skip to content

Commit 47e7c60

Browse files
Feature : Added server side verification for all routes . (#3491)
* added securitty for routing from server side * fixed test cases fail for Routing * taken suggestion from ai * Update src/components/SecuredRoute/SecuredRoute.tsx line 20 Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update src/components/SecuredRoute/SecuredRoute.tsx line 30 Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * taken suggestion from ai * added signOut button on PageNotFound page and fixed App.spec.tsx failed test cases * added condition in secureRouteForUser such that if the admin or superAdmin have user Account also access to login through User section * modify App.spec.tsx * test cases * taken suggestion from ai and fixed test cases * Update src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx line 57 Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fixed failing test cases * Update src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx line number 50 Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * taken suggestion from ai --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent c0ac5ec commit 47e7c60

File tree

14 files changed

+449
-127
lines changed

14 files changed

+449
-127
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[Admin Docs](/)
2+
3+
***
4+
5+
# Variable: VERIFY\_ROLE
6+
7+
> `const` **VERIFY\_ROLE**: `DocumentNode`
8+
9+
Defined in: [src/GraphQl/Queries/Queries.ts:867](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/GraphQl/Queries/Queries.ts#L867)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[Admin Docs](/)
2+
3+
***
4+
5+
# Enumeration: UserRole
6+
7+
Defined in: [src/components/CheckIn/types.ts:45](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/CheckIn/types.ts#L45)
8+
9+
## Enumeration Members
10+
11+
### ADMIN
12+
13+
> **ADMIN**: `"admin"`
14+
15+
Defined in: [src/components/CheckIn/types.ts:47](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/CheckIn/types.ts#L47)
16+
17+
***
18+
19+
### SUPER\_ADMIN
20+
21+
> **SUPER\_ADMIN**: `"superAdmin"`
22+
23+
Defined in: [src/components/CheckIn/types.ts:48](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/CheckIn/types.ts#L48)
24+
25+
***
26+
27+
### USER
28+
29+
> **USER**: `"user"`
30+
31+
Defined in: [src/components/CheckIn/types.ts:46](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/CheckIn/types.ts#L46)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[Admin Docs](/)
2+
3+
***
4+
5+
# Type Alias: VerifyRoleResponse
6+
7+
> **VerifyRoleResponse**: `object`
8+
9+
Defined in: [src/components/CheckIn/types.ts:51](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/CheckIn/types.ts#L51)
10+
11+
## Type declaration
12+
13+
### verifyRole
14+
15+
> **verifyRole**: `object`
16+
17+
#### verifyRole.isAuthorized
18+
19+
> **isAuthorized**: `boolean`
20+
21+
#### verifyRole.role
22+
23+
> **role**: [`UserRole`](../enumerations/UserRole.md)

docs/docs/auto-docs/components/SecuredRoute/SecuredRoute/functions/default.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
> **default**(): `Element`
88
9-
Defined in: [src/components/SecuredRoute/SecuredRoute.tsx:16](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/SecuredRoute/SecuredRoute.tsx#L16)
9+
Defined in: [src/components/SecuredRoute/SecuredRoute.tsx:19](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/SecuredRoute/SecuredRoute.tsx#L19)
1010

1111
A route guard that checks if the user is logged in and has the necessary permissions.
1212

docs/docs/auto-docs/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser/functions/default.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
> **default**(): `Element`
88
9-
Defined in: [src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx:14](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx#L14)
9+
Defined in: [src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx:18](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/components/UserPortal/SecuredRouteForUser/SecuredRouteForUser.tsx#L18)
1010

1111
A component that guards routes by checking if the user is logged in.
1212
If the user is logged in and does not have 'AdminFor' set, the child routes are rendered.

docs/docs/auto-docs/screens/PageNotFound/PageNotFound/functions/default.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
> **default**(): `Element`
88
9-
Defined in: [src/screens/PageNotFound/PageNotFound.tsx:15](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/PageNotFound/PageNotFound.tsx#L15)
9+
Defined in: [src/screens/PageNotFound/PageNotFound.tsx:16](https://github.com/PalisadoesFoundation/talawa-admin/blob/main/src/screens/PageNotFound/PageNotFound.tsx#L16)
1010

1111
The `PageNotFound` component displays a 404 error page when a user navigates to a non-existent route.
1212
It shows a message indicating that the page was not found and provides a link to redirect users back

src/App.spec.tsx

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ import { Provider } from 'react-redux';
44
import { MockedProvider } from '@apollo/react-testing';
55
import { BrowserRouter } from 'react-router-dom';
66
import { I18nextProvider } from 'react-i18next';
7-
import { describe, it, expect, vi } from 'vitest';
7+
import { describe, it, expect, vi, beforeEach } from 'vitest';
88
import App from './App';
99
import { store } from 'state/store';
10-
import { CHECK_AUTH } from 'GraphQl/Queries/Queries';
10+
import { CHECK_AUTH, VERIFY_ROLE } from 'GraphQl/Queries/Queries';
1111
import i18nForTest from './utils/i18nForTest';
1212
import { StaticMockLink } from 'utils/StaticMockLink';
1313

14+
// Mock external dependencies
1415
vi.mock('@mui/x-charts/PieChart', () => ({
1516
pieArcLabelClasses: vi.fn(),
1617
PieChart: vi.fn().mockImplementation(() => <>Test</>),
@@ -55,19 +56,45 @@ const MOCKS = [
5556
},
5657
},
5758
},
59+
{
60+
request: {
61+
query: VERIFY_ROLE,
62+
},
63+
result: {
64+
data: {
65+
verifyRole: {
66+
isAuthorized: true,
67+
role: 'user',
68+
},
69+
},
70+
},
71+
},
5872
];
5973

6074
const link = new StaticMockLink(MOCKS, true);
61-
const link2 = new StaticMockLink([], true);
75+
const link2 = new StaticMockLink(
76+
[
77+
{
78+
request: { query: CHECK_AUTH },
79+
result: { data: { checkAuth: null } }, // Simulating logged-out state
80+
},
81+
{
82+
request: { query: VERIFY_ROLE },
83+
result: { data: { verifyRole: { isAuthorized: false, role: '' } } },
84+
}, // Ensure verifyRole exists, even if null
85+
],
86+
true,
87+
);
88+
89+
const wait = (ms = 100): Promise<void> =>
90+
new Promise((resolve) => setTimeout(resolve, ms));
6291

63-
async function wait(ms = 100): Promise<void> {
64-
await new Promise((resolve) => {
65-
setTimeout(resolve, ms);
92+
describe('App Component Tests', () => {
93+
beforeEach(() => {
94+
window.history.pushState({}, '', '/');
6695
});
67-
}
6896

69-
describe('Testing the App Component', () => {
70-
it('Component should be rendered properly and user is logged in', async () => {
97+
it('should render properly when user is logged in', async () => {
7198
render(
7299
<MockedProvider addTypename={false} link={link}>
73100
<BrowserRouter>
@@ -84,15 +111,16 @@ describe('Testing the App Component', () => {
84111

85112
window.history.pushState({}, '', '/orglist');
86113
await wait();
114+
87115
expect(window.location.pathname).toBe('/orglist');
88116
expect(
89117
screen.getByText(
90118
'An open source application by Palisadoes Foundation volunteers',
91119
),
92-
).toBeTruthy();
120+
).toBeInTheDocument();
93121
});
94122

95-
it('Component should be rendered properly and user is logged out', async () => {
123+
it('should render properly when user is logged out', async () => {
96124
render(
97125
<MockedProvider addTypename={false} link={link2}>
98126
<BrowserRouter>

src/GraphQl/Queries/Queries.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,14 @@ export const GET_COMMUNITY_SESSION_TIMEOUT_DATA = gql`
864864
}
865865
}
866866
`;
867+
export const VERIFY_ROLE = gql`
868+
query verifyRole {
869+
verifyRole {
870+
isAuthorized
871+
role
872+
}
873+
}
874+
`;
867875

868876
// get the list of Action Item Categories
869877
export { ACTION_ITEM_CATEGORY_LIST } from './ActionItemCategoryQueries';

src/components/CheckIn/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,15 @@ export interface InterfaceTableData {
4242
id: string;
4343
checkInData: InterfaceTableCheckIn;
4444
}
45+
export enum UserRole {
46+
USER = 'user',
47+
ADMIN = 'admin',
48+
SUPER_ADMIN = 'superAdmin',
49+
}
50+
51+
export type VerifyRoleResponse = {
52+
verifyRole: {
53+
isAuthorized: boolean;
54+
role: UserRole;
55+
};
56+
};

src/components/SecuredRoute/SecuredRoute.tsx

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
import React from 'react';
2-
import { Navigate, Outlet } from 'react-router-dom';
1+
import { useQuery } from '@apollo/client';
2+
import { UserRole, type VerifyRoleResponse } from 'components/CheckIn/types';
3+
import { VERIFY_ROLE } from 'GraphQl/Queries/Queries';
4+
import React, { useEffect } from 'react';
5+
import { Navigate, Outlet, useLocation } from 'react-router-dom';
36
import { toast } from 'react-toastify';
47
import PageNotFound from 'screens/PageNotFound/PageNotFound';
58
import useLocalStorage from 'utils/useLocalstorage';
@@ -14,14 +17,57 @@ const { getItem, setItem } = useLocalStorage();
1417
* @returns The JSX element representing the secured route.
1518
*/
1619
const SecuredRoute = (): JSX.Element => {
17-
const isLoggedIn = getItem('IsLoggedIn');
18-
const adminFor = getItem('AdminFor');
19-
20-
return isLoggedIn === 'TRUE' ? (
21-
<>{adminFor != null ? <Outlet /> : <PageNotFound />}</>
22-
) : (
23-
<Navigate to="/" replace />
20+
const location = useLocation();
21+
const { data, loading, error, refetch } = useQuery<VerifyRoleResponse>(
22+
VERIFY_ROLE,
23+
{
24+
skip: !getItem('token'),
25+
context: {
26+
headers: {
27+
Authorization: `Bearer ${getItem('token')}`,
28+
},
29+
},
30+
},
2431
);
32+
const [token, setToken] = React.useState(getItem('token'));
33+
34+
useEffect(() => {
35+
const newToken = getItem('token');
36+
if (newToken !== token) {
37+
setToken(newToken);
38+
}
39+
}, []);
40+
41+
useEffect(() => {
42+
refetch(); // Refetch when token updates
43+
}, [token]);
44+
45+
if (loading) {
46+
return <div> Loading.....</div>;
47+
} else if (error) {
48+
return <div>Error During Routing ...</div>;
49+
} else {
50+
if (!data?.verifyRole) {
51+
return <Navigate to="/" replace />;
52+
}
53+
const { isAuthorized = false, role = '' } = (data as VerifyRoleResponse)
54+
.verifyRole;
55+
const restrictedRoutesForAdmin = ['/member', '/users', '/communityProfile'];
56+
if (isAuthorized) {
57+
if (role == UserRole.SUPER_ADMIN) {
58+
return <Outlet />;
59+
} else if (role == UserRole.ADMIN) {
60+
if (restrictedRoutesForAdmin.includes(location.pathname)) {
61+
return <PageNotFound />;
62+
}
63+
return <Outlet />;
64+
} else {
65+
return <PageNotFound />;
66+
}
67+
} else {
68+
return <Navigate to="/" replace />;
69+
}
70+
}
2571
};
2672

2773
// Time constants for session timeout and inactivity interval

0 commit comments

Comments
 (0)