From aae67d2db54c44de69aa9c247733cc9e156ca76f Mon Sep 17 00:00:00 2001 From: codermehraj Date: Fri, 29 Mar 2024 05:43:45 +0600 Subject: [PATCH 1/8] fixed layout of rbac admin panel --- .../mainContent/systemAdminContents/Roles.tsx | 13 +++++-------- server/src/controllers/rbac.ts | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx b/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx index 8950880..7a80208 100644 --- a/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx +++ b/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx @@ -23,17 +23,14 @@ export default function AdminRolesManagementPanel() {
-
-
+
+
Roles List
-
+
Permisson List -
-
- Role Distribution chart -
-
+
+
Role Requests
diff --git a/server/src/controllers/rbac.ts b/server/src/controllers/rbac.ts index 53acc4e..9c27894 100644 --- a/server/src/controllers/rbac.ts +++ b/server/src/controllers/rbac.ts @@ -59,7 +59,7 @@ const getPermissions = errorWrapper( async (req: Request, res: Response) => { const permissions = await prisma.permission.findMany({}); - const permissionNames = permissions.map((permission) => permission.name); + const permissionNames = permissions; res.json(permissionNames); }, From 5bab2c80966b156e3fb69f6f1143d39776131f8e Mon Sep 17 00:00:00 2001 From: codermehraj Date: Fri, 29 Mar 2024 07:45:42 +0600 Subject: [PATCH 2/8] backend call of fetching permisson and roles done --- client/data/apiRoutes.ts | 2 ++ client/hooks/user_data/getAllPermissonList.ts | 26 ++++++++++++++ client/hooks/user_data/useGetAllRole.tsx | 34 +++++++++++++++---- server/src/controllers/rbac.ts | 10 ++++-- 4 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 client/hooks/user_data/getAllPermissonList.ts diff --git a/client/data/apiRoutes.ts b/client/data/apiRoutes.ts index 6b80a02..e8c9bce 100644 --- a/client/data/apiRoutes.ts +++ b/client/data/apiRoutes.ts @@ -31,6 +31,8 @@ export const apiRoutes = { getByRole: `${baseUrl}/rbac/roles/get/`, delete: `${baseUrl}/rbac/`, edit: `${baseUrl}/rbac/`, + getAllRolesWithPermisson: `${baseUrl}/rbac/all`, + fetchAllPermissons: `${baseUrl}/rbac/permissions`, }, vehicle: { create: `${baseUrl}/vehicles/create`, diff --git a/client/hooks/user_data/getAllPermissonList.ts b/client/hooks/user_data/getAllPermissonList.ts new file mode 100644 index 0000000..9bf5a50 --- /dev/null +++ b/client/hooks/user_data/getAllPermissonList.ts @@ -0,0 +1,26 @@ +import { apiRoutes } from "@/data/apiRoutes"; +import { jwtToken } from "@/data/cookieNames"; +import { getCookie } from "@/lib/cookieFunctions"; +import axios from "axios"; + +export async function fetchAllPermissons() { + try { + const token = getCookie(jwtToken); + const response = await axios.get(apiRoutes.rbac.fetchAllPermissons, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + + //console.log(response.data); + return response.data.map((permisson: any) => { + return { + name: permisson.name, + description: permisson.description, + }; + }); + } catch (error: any) { + alert("Error fetching permissons... Are you authorized?"); + console.log(error.message); + } +} diff --git a/client/hooks/user_data/useGetAllRole.tsx b/client/hooks/user_data/useGetAllRole.tsx index 933d946..c6431f7 100644 --- a/client/hooks/user_data/useGetAllRole.tsx +++ b/client/hooks/user_data/useGetAllRole.tsx @@ -5,20 +5,42 @@ import { admin, landfillManager, stsManager, unassigned } from "@/data/roles"; import { getCookie } from "@/lib/cookieFunctions"; import axios from "axios"; import { useState, useEffect, use } from "react"; +import { set } from "react-hook-form"; -type User = { +type RolesWithPermisson = { id: string; - username: string; - email: string; - role: string; + name: string; + permissions: [{ + name: string; + description: string; +}] }; export default function useGetAllRole() { const [roles, setRoles] = useState([]); + const [rolesWithPermissions, setRolesWithPermissions] = useState([]); async function fetchAllRoles() { try { - await setRoles([unassigned, admin, landfillManager, stsManager]); + const token = getCookie(jwtToken); + const response = await axios.get(apiRoutes.rbac.getAllRolesWithPermisson, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + setRolesWithPermissions(response.data.map((role: RolesWithPermisson) => { + return { + id: role.id, + name: role.name, + permissions: role.permissions.map((permission: any) => { + return { + name: permission.name, + description: permission.description, + }; + }, + )}; + })); + await setRoles([unassigned, admin, landfillManager, stsManager]); console.log(roles); } catch (error: any) { alert("Error fetching roles... Are you authorized?"); @@ -30,5 +52,5 @@ export default function useGetAllRole() { fetchAllRoles(); }, []); - return {fetchAllRoles, roles}; + return {fetchAllRoles, roles, rolesWithPermissions}; } diff --git a/server/src/controllers/rbac.ts b/server/src/controllers/rbac.ts index 9c27894..a5d3612 100644 --- a/server/src/controllers/rbac.ts +++ b/server/src/controllers/rbac.ts @@ -7,11 +7,15 @@ const prisma = new PrismaClient(); const getAllRoles = errorWrapper( async (req: Request, res: Response) => { - const roles = await prisma.role.findMany({}); + const roles = await prisma.role.findMany({ + include: { + User: true, + }, + }); - const roleNames = roles.map((role) => role.name); + // const roleNames = roles.map((role) => role.name); - res.json(roleNames); + res.json(roles); }, { statusCode: 500, message: "Couldn't fetch roles" } ); From be316dec0e6b560c075668913f516eba62a7f8d0 Mon Sep 17 00:00:00 2001 From: codermehraj Date: Fri, 29 Mar 2024 07:45:57 +0600 Subject: [PATCH 3/8] Completed rendering role base permisson list --- .../cards/EmptyFillContainer.tsx | 4 +- .../mainContent/systemAdminContents/Roles.tsx | 25 +++-- client/components/lists/PermissonList.tsx | 103 ++++++++++++++++++ client/components/ui/radio-group.tsx | 44 ++++++++ client/package-lock.json | 33 ++++++ client/package.json | 1 + 6 files changed, 199 insertions(+), 11 deletions(-) create mode 100644 client/components/lists/PermissonList.tsx create mode 100644 client/components/ui/radio-group.tsx diff --git a/client/components/dashboard-componenets/cards/EmptyFillContainer.tsx b/client/components/dashboard-componenets/cards/EmptyFillContainer.tsx index bab6f88..87137ee 100644 --- a/client/components/dashboard-componenets/cards/EmptyFillContainer.tsx +++ b/client/components/dashboard-componenets/cards/EmptyFillContainer.tsx @@ -1,6 +1,6 @@ -export default function EmptyFillContainer({children}: {children: React.ReactNode}) { +export default function EmptyFillContainer({children, className = ""}: {children: React.ReactNode, className?: string}) { return ( -
{children}
+
{children}
); } \ No newline at end of file diff --git a/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx b/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx index 7a80208..76b8314 100644 --- a/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx +++ b/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx @@ -1,9 +1,11 @@ import { Button } from "@/components/ui/button"; import { Cog, UserRoundCog } from "lucide-react"; import EmptyFillContainer from "../../cards/EmptyFillContainer"; -import { RoleCreateModal } from "@/components/modals/userControls/RoleModal"; +import { RoleCreateModal } from "@/components/modals/userControls/RoleModal"; +import PermissonList from "@/components/lists/PermissonList"; -export default function AdminRolesManagementPanel() { + +export default function AdminRolesManagementPanel() { return (
@@ -11,10 +13,10 @@ export default function AdminRolesManagementPanel() {
- +
); diff --git a/client/components/lists/PermissonList.tsx b/client/components/lists/PermissonList.tsx index 7dfa26b..4061a62 100644 --- a/client/components/lists/PermissonList.tsx +++ b/client/components/lists/PermissonList.tsx @@ -6,6 +6,18 @@ import { use, useEffect, useState } from "react"; import useGetAllRole from "@/hooks/user_data/useGetAllRole"; import { fetchAllPermissons } from "@/hooks/user_data/getAllPermissonList"; import { set } from "react-hook-form"; +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger, +} from "../ui/alert-dialog"; +import { Button } from "../ui/button"; type RolesWithPermisson = { id: string; @@ -19,21 +31,28 @@ type RolesWithPermisson = { }; type Permisson = { - name: string; - description: string; - }; + name: string; + description: string; +}; + +type EditPermisson = { + role: string; + permission: string; + action: string; +}; function PermissonList() { const { fetchAllRoles, rolesWithPermissions } = useGetAllRole(); const [roles, setRoles] = useState([]); const [permissions, setPermissions] = useState([]); - + const [msg, setMsg] = useState(); + async function getPermissons() { - setPermissions(await fetchAllPermissons()); - } - + setPermissions(await fetchAllPermissons()); + } + useEffect(() => { - fetchAllRoles(); + fetchAllRoles(); getPermissons(); }, []); @@ -55,7 +74,8 @@ function PermissonList() {
@@ -101,3 +187,24 @@ function PermissonList() { ); } export default PermissonList; + +{ + /* + + + + + + Are you absolutely sure? + + This action cannot be undone. This will permanently delete your account + and remove your data from our servers. + + + + Cancel + Continue + + +; */ +} From fa6203a11f69f74c7fd85e3b4a13d5b658eb3f8e Mon Sep 17 00:00:00 2001 From: codermehraj Date: Fri, 29 Mar 2024 08:54:33 +0600 Subject: [PATCH 5/8] RBAC permission add and delete integrated with backend --- client/components/lists/PermissonList.tsx | 13 +++++- client/data/apiRoutes.ts | 4 +- client/hooks/user_data/updatePermisson.tsx | 46 ++++++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 client/hooks/user_data/updatePermisson.tsx diff --git a/client/components/lists/PermissonList.tsx b/client/components/lists/PermissonList.tsx index 4061a62..fe605ca 100644 --- a/client/components/lists/PermissonList.tsx +++ b/client/components/lists/PermissonList.tsx @@ -18,6 +18,7 @@ import { AlertDialogTrigger, } from "../ui/alert-dialog"; import { Button } from "../ui/button"; +import { updatePermisson } from "@/hooks/user_data/updatePermisson"; type RolesWithPermisson = { id: string; @@ -58,7 +59,7 @@ function PermissonList() { useEffect(() => { setRoles(rolesWithPermissions); - setSelectedRole(rolesWithPermissions[0]?.name); + //setSelectedRole(rolesWithPermissions[0]?.name); }, [rolesWithPermissions]); const [selectedRole, setSelectedRole] = useState(); @@ -171,7 +172,15 @@ function PermissonList() { Cancel - Confirm + { + msg && alert(await updatePermisson(msg)); + await fetchAllRoles(); + setMsg(undefined); + }} + > + Confirm + diff --git a/client/data/apiRoutes.ts b/client/data/apiRoutes.ts index e8c9bce..798590c 100644 --- a/client/data/apiRoutes.ts +++ b/client/data/apiRoutes.ts @@ -29,8 +29,8 @@ export const apiRoutes = { rbac: { create: `${baseUrl}/rbac/create`, getByRole: `${baseUrl}/rbac/roles/get/`, - delete: `${baseUrl}/rbac/`, - edit: `${baseUrl}/rbac/`, + delete: `${baseUrl}/rbac/roles/`, + edit: `${baseUrl}/rbac/roles/`, getAllRolesWithPermisson: `${baseUrl}/rbac/all`, fetchAllPermissons: `${baseUrl}/rbac/permissions`, }, diff --git a/client/hooks/user_data/updatePermisson.tsx b/client/hooks/user_data/updatePermisson.tsx new file mode 100644 index 0000000..d155dcf --- /dev/null +++ b/client/hooks/user_data/updatePermisson.tsx @@ -0,0 +1,46 @@ +import { apiRoutes } from "@/data/apiRoutes"; +import { jwtToken } from "@/data/cookieNames"; +import { getCookie } from "@/lib/cookieFunctions"; +import axios from "axios"; + +type EditPermisson = { + role: string; + permission: string; + action: string; +}; + +export async function updatePermisson(payload: EditPermisson) { + try { + const token = getCookie(jwtToken); + let response; + payload.action === "ADD" + ? (response = await axios.post( + apiRoutes.rbac.edit + + payload.role + + "/permissions/" + + payload.permission, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + )) + : (response = await axios.delete( + apiRoutes.rbac.delete + + payload.role + + "/permissions/" + + payload.permission, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + )); + + //console.log(response.data); + return "Permisson updated successfully!"; + } catch (error: any) { + alert("Error updating permissons... Are you authorized?"); + console.log(error.message); + } +} From 488260c491701749f6c7f3f36d8f6333471b4120 Mon Sep 17 00:00:00 2001 From: codermehraj Date: Fri, 29 Mar 2024 09:13:26 +0600 Subject: [PATCH 6/8] Fixed RBAC component initial State --- .../mainContent/systemAdminContents/Roles.tsx | 4 +-- client/components/lists/PermissonList.tsx | 30 +++---------------- 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx b/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx index 4a17e38..639736e 100644 --- a/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx +++ b/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx @@ -23,8 +23,8 @@ export default function AdminRolesManagementPanel() {
-
- +
+

PERMISSON LIST BY ROLE

diff --git a/client/components/lists/PermissonList.tsx b/client/components/lists/PermissonList.tsx index fe605ca..b318c89 100644 --- a/client/components/lists/PermissonList.tsx +++ b/client/components/lists/PermissonList.tsx @@ -19,6 +19,7 @@ import { } from "../ui/alert-dialog"; import { Button } from "../ui/button"; import { updatePermisson } from "@/hooks/user_data/updatePermisson"; +import { Pointer, SquareMousePointer } from "lucide-react"; type RolesWithPermisson = { id: string; @@ -65,7 +66,7 @@ function PermissonList() { const [selectedRole, setSelectedRole] = useState(); return ( - <> +
setSelectedRole(e)} @@ -188,32 +189,9 @@ function PermissonList() {
) : ( - -

Select a role to view permissions

-
+

Select a role from above to view permissions

)} - +
); } export default PermissonList; - -{ - /* - - - - - - Are you absolutely sure? - - This action cannot be undone. This will permanently delete your account - and remove your data from our servers. - - - - Cancel - Continue - - -; */ -} From 48cc5b6cd594ac5c8516f8e0c5cea137905ee7dd Mon Sep 17 00:00:00 2001 From: codermehraj Date: Fri, 29 Mar 2024 09:39:36 +0600 Subject: [PATCH 7/8] Delete role functionality integrated with backend and added --- .../mainContent/systemAdminContents/Roles.tsx | 7 ++ .../modals/userControls/RoleDeleteModal.tsx | 72 +++++++++++++++++++ .../modals/userControls/RoleModal.tsx | 23 ++---- client/data/apiRoutes.ts | 4 +- client/hooks/user_data/addNewRole.ts | 27 +++++++ client/hooks/user_data/deleteRole.ts | 27 +++++++ 6 files changed, 140 insertions(+), 20 deletions(-) create mode 100644 client/components/modals/userControls/RoleDeleteModal.tsx create mode 100644 client/hooks/user_data/addNewRole.ts create mode 100644 client/hooks/user_data/deleteRole.ts diff --git a/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx b/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx index 639736e..7190efb 100644 --- a/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx +++ b/client/components/dashboard-componenets/mainContent/systemAdminContents/Roles.tsx @@ -3,6 +3,7 @@ import { Cog, UserRoundCog } from "lucide-react"; import EmptyFillContainer from "../../cards/EmptyFillContainer"; import { RoleCreateModal } from "@/components/modals/userControls/RoleModal"; import PermissonList from "@/components/lists/PermissonList"; +import { RoleDeleteModal } from "@/components/modals/userControls/RoleDeleteModal"; export default function AdminRolesManagementPanel() { return ( @@ -17,6 +18,12 @@ export default function AdminRolesManagementPanel() { ADD NEW ROLE + + + */} + {children} + + + + Delete Role + + Select a role to delete. Click delete when you're done. + + +
+
+ + setRoleName(e.target.value)} + /> +
+
+ + +
+ +
+
+
+ +
+ + ); +}; diff --git a/client/components/modals/userControls/RoleModal.tsx b/client/components/modals/userControls/RoleModal.tsx index fc9f7d0..cad0dd3 100644 --- a/client/components/modals/userControls/RoleModal.tsx +++ b/client/components/modals/userControls/RoleModal.tsx @@ -12,6 +12,7 @@ import { import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; +import addNewRole from "@/hooks/user_data/addNewRole"; import React , {useState} from "react"; interface DialogWrapperProps { @@ -21,13 +22,11 @@ interface DialogWrapperProps { export const RoleCreateModal: React.FC = ({ children, }) => { - const [description, setDescription] = useState(""); const [roleName, setRoleName] = useState(""); - const handleSaveChanges = () => { - console.log("Vehicle Number:", description); - console.log("Vehicle Number:", roleName); - + const handleSaveChanges = async () => { + await addNewRole(roleName); + window.location.reload(); }; @@ -56,19 +55,7 @@ export const RoleCreateModal: React.FC = ({ value={roleName} onChange={(e) => setRoleName(e.target.value)} /> -
-
- - setDescription(e.target.value)} - /> -
+ diff --git a/client/data/apiRoutes.ts b/client/data/apiRoutes.ts index 798590c..9af7026 100644 --- a/client/data/apiRoutes.ts +++ b/client/data/apiRoutes.ts @@ -27,9 +27,9 @@ export const apiRoutes = { edit: `${baseUrl}/landfills/`, }, rbac: { - create: `${baseUrl}/rbac/create`, + create: `${baseUrl}/rbac/roles`, getByRole: `${baseUrl}/rbac/roles/get/`, - delete: `${baseUrl}/rbac/roles/`, + delete: `${baseUrl}/rbac/roles/delete/`, edit: `${baseUrl}/rbac/roles/`, getAllRolesWithPermisson: `${baseUrl}/rbac/all`, fetchAllPermissons: `${baseUrl}/rbac/permissions`, diff --git a/client/hooks/user_data/addNewRole.ts b/client/hooks/user_data/addNewRole.ts new file mode 100644 index 0000000..bcab66b --- /dev/null +++ b/client/hooks/user_data/addNewRole.ts @@ -0,0 +1,27 @@ +"use client"; +import { UserData } from "@/components/graphs/Data"; +import { apiRoutes } from "@/data/apiRoutes"; +import { jwtToken } from "@/data/cookieNames"; +import { admin, landfillManager, stsManager, unassigned } from "@/data/roles"; +import { getCookie } from "@/lib/cookieFunctions"; +import axios from "axios"; +import { useState, useEffect, use } from "react"; + + +export default async function addNewRole(roleName: string) { + + if(!roleName) return "Enter a valid role name."; + try { + const res = await axios.post(apiRoutes.rbac.create, { roleName },{ + headers: { + Authorization: `Bearer ${await getCookie(jwtToken)}`, + }, + }); + + if(res) return "Role added successfully"; + } catch (error: any) { + alert("Error creating role... Are you authorized?"); + console.log(error.message); + } + +} diff --git a/client/hooks/user_data/deleteRole.ts b/client/hooks/user_data/deleteRole.ts new file mode 100644 index 0000000..4619a8c --- /dev/null +++ b/client/hooks/user_data/deleteRole.ts @@ -0,0 +1,27 @@ +"use client"; +import { UserData } from "@/components/graphs/Data"; +import { apiRoutes } from "@/data/apiRoutes"; +import { jwtToken } from "@/data/cookieNames"; +import { admin, landfillManager, stsManager, unassigned } from "@/data/roles"; +import { getCookie } from "@/lib/cookieFunctions"; +import axios from "axios"; +import { useState, useEffect, use } from "react"; + + +export default async function deleteRole(roleName: string) { + + if(!roleName) return "Enter a valid role name."; + try { + const res = await axios.delete(apiRoutes.rbac.delete + roleName ,{ + headers: { + Authorization: `Bearer ${await getCookie(jwtToken)}`, + }, + }); + + if(res) return "Role added successfully"; + } catch (error: any) { + alert("Error creating role... Are you authorized?"); + console.log(error.message); + } + +} From 88adc52ac5adba788862442548acbfa0b0a10ca1 Mon Sep 17 00:00:00 2001 From: codermehraj Date: Fri, 29 Mar 2024 09:42:09 +0600 Subject: [PATCH 8/8] next js popup removed --- client/app/globals.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/app/globals.css b/client/app/globals.css index a30a014..800182b 100644 --- a/client/app/globals.css +++ b/client/app/globals.css @@ -98,3 +98,7 @@ background: #0F172A; /* Color of the scrollbar handle on hover */ border: 2px solid white; /* Color of the scrollbar handle on hover */ } + +nextjs-portal { + display: none; +} \ No newline at end of file