From 461d8105e6577079500336a6505fd81f59247169 Mon Sep 17 00:00:00 2001 From: Ajay krishna Date: Tue, 11 Jun 2024 14:26:27 +0530 Subject: [PATCH 01/15] FWF-3324: [Feature] Added permmision mapping to roles --- .../src/components/roles/roles.tsx | 108 +++++++++++++++--- forms-flow-admin/src/endpoints/index.ts | 1 + forms-flow-admin/src/services/roles/index.ts | 18 +++ .../src/resourceBundles/bg/resourceBundles.ts | 19 ++- .../src/resourceBundles/de/resourceBundles.ts | 19 ++- .../src/resourceBundles/en/resourceBundles.ts | 19 ++- .../src/resourceBundles/es/resourceBundles.ts | 19 ++- .../src/resourceBundles/fr/resourceBundles.ts | 20 +++- .../src/resourceBundles/pt/resourceBundles.ts | 19 ++- .../src/resourceBundles/zh/resourceBundles.ts | 19 ++- 10 files changed, 241 insertions(+), 20 deletions(-) diff --git a/forms-flow-admin/src/components/roles/roles.tsx b/forms-flow-admin/src/components/roles/roles.tsx index eb86e468d..c19115f27 100644 --- a/forms-flow-admin/src/components/roles/roles.tsx +++ b/forms-flow-admin/src/components/roles/roles.tsx @@ -7,7 +7,7 @@ import paginationFactory from "react-bootstrap-table2-paginator"; import Form from "react-bootstrap/Form"; import Button from "react-bootstrap/Button"; import { fetchUsers } from "../../services/users"; -import { CreateRole, DeleteRole, UpdateRole } from "../../services/roles"; +import { CreateRole, DeleteRole, UpdateRole, fetchPermissions } from "../../services/roles"; import Modal from "react-bootstrap/Modal"; import Loading from "../loading"; import DropdownButton from "react-bootstrap/DropdownButton"; @@ -36,13 +36,14 @@ const Roles = React.memo((props: any) => { const [showRoleModal, setShowRoleModal] = useState(false); const [showEditRoleModal, setShowEditRoleModal] = useState(false); const [loading, setLoading] = React.useState(false); - const [payload, setPayload] = React.useState({ name: "", description: "" }); + const [payload, setPayload] = React.useState({ name: "", description: "" , permissions: [] }); // Toggle for Delete Confirm modal const [showConfirmDelete, setShowConfirmDelete] = React.useState(false); const initialRoleType = { name: "", id: "", description: "", + permissions: [] }; const [deleteCandidate, setDeleteCandidate] = React.useState(initialRoleType); const [selectedRoleIdentifier, setSelectedRoleIdentifier] = @@ -50,6 +51,7 @@ const Roles = React.memo((props: any) => { const [editCandidate, setEditCandidate] = React.useState(initialRoleType); const [disabled, setDisabled] = React.useState(true); const [search, setSerach] = React.useState(""); + const [permission, setPermission] = React.useState([]) const filterList = (filterTerm, List) => { let roleList = List.filter((role) => { @@ -59,12 +61,12 @@ const Roles = React.memo((props: any) => { }; React.useEffect(() => { - setDisabled(!(payload.name?.trim() && payload.description?.trim())); + setDisabled(!(payload.name?.trim() && payload.description?.trim() && payload.permissions.length !== 0)); }, [payload]); React.useEffect(() => { setDisabled( - !(editCandidate.name?.trim() && editCandidate.description?.trim()) + !(editCandidate.name?.trim() && editCandidate.description?.trim() && editCandidate.permissions.length !== 0) ); }, [editCandidate]); @@ -75,6 +77,14 @@ const Roles = React.memo((props: any) => { setRoles(props.roles); }, [props.roles]); + React.useEffect(() => { + fetchPermissions((data) => { + setPermission(data); + }, (err)=>{ + setError(err); + }); + }, []); + const handlFilter = (e) => { setSerach(e.target.value); setRoles(filterList(e.target.value, props.roles)); @@ -103,6 +113,25 @@ const Roles = React.memo((props: any) => { const handleChangeDescription = (e) => { setPayload({ ...payload, description: e.target.value }); }; + const handleCheckboxChange = (permissionName: string, dependsOn: string[]) => { + let updatedPermissions: string[] = [...payload.permissions]; + const isChecked = updatedPermissions.includes(permissionName); + + if (!isChecked) { + updatedPermissions.push(permissionName); + dependsOn.forEach(dependency => { + if (!updatedPermissions.includes(dependency)) { + updatedPermissions.push(dependency); + } + }); + } else { + updatedPermissions = updatedPermissions.filter(permission => permission !== permissionName); + dependsOn.forEach(dependency => { + updatedPermissions = updatedPermissions.filter(permission => permission !== dependency); + }); + } + setPayload ({ ...payload, permissions: updatedPermissions }); +}; const validateRolePayload = (payload) => { return !(payload.name === "" || payload.description === ""); @@ -186,8 +215,7 @@ const Roles = React.memo((props: any) => { } ); }; - - // handlers for user list popover + // handlers for user list popover const handleClick = (event, rowData) => { setShow(!show); setLoading(true); @@ -216,10 +244,30 @@ const Roles = React.memo((props: any) => { setEditCandidate({ ...editCandidate, description: e.target.value }); }; + const handleEditCheckboxChange = (permissionName: string, dependsOn: string[]) => { + let updatedPermissions: string[] = [...editCandidate.permissions]; + const isChecked = updatedPermissions.includes(permissionName); + + if (!isChecked) { + updatedPermissions.push(permissionName); + dependsOn.forEach(dependency => { + if (!updatedPermissions.includes(dependency)) { + updatedPermissions.push(dependency); + } + }); + } else { + updatedPermissions = updatedPermissions.filter(permission => permission !== permissionName); + dependsOn.forEach(dependency => { + updatedPermissions = updatedPermissions.filter(permission => permission !== dependency); + }); + } + setEditCandidate ({ ...editCandidate, permissions: updatedPermissions }); +}; + // handlers for role create/edit modal const handleCloseRoleModal = () => { setShowRoleModal(false); - setPayload({ name: "", description: "" }); + setPayload({ name: "", description: "" , permissions: []}); }; const handleShowRoleModal = () => setShowRoleModal(true); const handleCloseEditRoleModal = () => { @@ -259,7 +307,6 @@ const Roles = React.memo((props: any) => { } }; // Delete confirmation - const confirmDelete = () => (
@@ -302,7 +349,7 @@ const Roles = React.memo((props: any) => { {t("Role Name")} - * + * { {t("Description")} - * + * { onChange={handleChangeDescription} title={t("Enter Description")} /> - + + + {t("Permissions")} + + * +
+ {permission.map((permission) => ( +
+ handleCheckboxChange(permission.name, permission.depends_on)} + /> +
+ ))} +
+ + )} + {showReturnToHome && ( + + )} +
+ ); +}; + +export default AccessDenied; diff --git a/forms-flow-admin/src/index.tsx b/forms-flow-admin/src/index.tsx index fd9aca5c2..4bfdef3b6 100644 --- a/forms-flow-admin/src/index.tsx +++ b/forms-flow-admin/src/index.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Route, Switch, Redirect, useHistory, useParams } from "react-router-dom"; +import { Route, Switch,useHistory, useParams,useLocation } from "react-router-dom"; import { ToastContainer } from "react-toastify"; import "react-toastify/dist/ReactToastify.css"; import { KeycloakService, StorageService } from "@formsflow/service"; @@ -9,13 +9,14 @@ import { KEYCLOAK_CLIENT, } from "./endpoints/config"; import Footer from "./components/footer"; -import { BASE_ROUTE, ADMIN_ROLE, MULTITENANCY_ENABLED } from "./constants"; +import { BASE_ROUTE, MULTITENANCY_ENABLED } from "./constants"; import AdminDashboard from "./components/dashboard"; import RoleManagement from "./components/roles"; import UserManagement from "./components/users"; import Head from "./containers/head"; import i18n from "./resourceBundles/i18n"; import "./index.scss"; +import Accessdenied from "./components/AccessDenied"; const Admin = React.memo(({ props }: any) => { const { publish, subscribe } = props; @@ -27,7 +28,6 @@ const Admin = React.memo(({ props }: any) => { const [dashboardCount, setDashboardCount] = React.useState(); const [roleCount, setRoleCount] = React.useState(); const [userCount, setUserCount] = React.useState(); - const [isAdmin, setIsAdmin] = React.useState(false); const baseUrl = MULTITENANCY_ENABLED ? `/tenant/${tenantId}/` : "/"; const userRoles = JSON.parse( StorageService.get(StorageService.User.USER_ROLE) @@ -35,6 +35,8 @@ const Admin = React.memo(({ props }: any) => { const isDashboardManager = userRoles.includes("manage_dashboard_authorizations"); const isRoleManager = userRoles.includes("manage_roles"); const isUserManager = userRoles.includes("manage_users"); + const location =useLocation().pathname; + const [isAccessRestricted, setIsAccessRestricted] = React.useState(false); React.useEffect(() => { publish("ES_ROUTE", { pathname: `${baseUrl}admin` }); subscribe("ES_CHANGE_LANGUAGE", (msg, data) => { @@ -63,10 +65,6 @@ const Admin = React.memo(({ props }: any) => { React.useEffect(()=>{ if(!isAuth) return - const roles = JSON.parse(StorageService.get(StorageService.User.USER_ROLE)); - if(roles.includes("admin")){ - setIsAdmin(true); - } const locale = localStorage.getItem("i18nextLng") if(locale) i18n.changeLanguage(locale); },[isAuth]) @@ -94,13 +92,21 @@ const Admin = React.memo(({ props }: any) => { })} return headers ; }; - + + React.useEffect(()=>{ + const restricted = + (location === '/admin/dashboard' && !isDashboardManager) || + (location === '/admin/roles' && !isRoleManager) || + (location === '/admin/users' && !isUserManager); + setIsAccessRestricted(restricted); + },[location,userRoles]); return ( <> - {isAdmin && ( + {userRoles.includes("admin") ? (
-
-
+
+ {!isAccessRestricted ?( +
@@ -140,13 +146,22 @@ const Admin = React.memo(({ props }: any) => { /> )} />)} - -
+
): +
+ +
}
- )} + ):
+
+
+ +
+
+
+
} ); }); diff --git a/forms-flow-nav/src/Navbar.jsx b/forms-flow-nav/src/Navbar.jsx index 33570d50f..bbc273a86 100644 --- a/forms-flow-nav/src/Navbar.jsx +++ b/forms-flow-nav/src/Navbar.jsx @@ -316,7 +316,7 @@ const isUserManager = userRoles.includes("manage_users"); {t("Forms")} )} - {userRoles.includes("admin") ? ( + {userRoles.includes("admin") && ( {t("Admin")} - ) : null} + ) } {userRoles.includes("create_designs") && ENABLE_PROCESSES_MODULE && ( From 19a7d380f94c7dab9dba582437325e3eea97fc45 Mon Sep 17 00:00:00 2001 From: Sumesh Punakkal Kariyil Date: Wed, 3 Jul 2024 11:02:53 -0700 Subject: [PATCH 08/15] Updating version tag to create new version for rbac changes --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index fb5d1e208..07abcadc7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v6.1.0-alpha +v6.1.0-rbac-alpha From 25b3535adafd131d2636a804932e50c52a4f7ea4 Mon Sep 17 00:00:00 2001 From: Sumesh Punakkal Kariyil Date: Wed, 3 Jul 2024 11:05:55 -0700 Subject: [PATCH 09/15] Updating github actions to trigger for feature rbac changes --- .github/workflows/forms-flow-admin-cd.yml | 1 + .github/workflows/forms-flow-integration-cd.yml | 1 + .github/workflows/forms-flow-nav.cd.yml | 1 + .github/workflows/forms-flow-service.yml | 1 + .github/workflows/forms-flow-theme.yml | 1 + 5 files changed, 5 insertions(+) diff --git a/.github/workflows/forms-flow-admin-cd.yml b/.github/workflows/forms-flow-admin-cd.yml index d99fd6bc9..31ec73cb9 100644 --- a/.github/workflows/forms-flow-admin-cd.yml +++ b/.github/workflows/forms-flow-admin-cd.yml @@ -6,6 +6,7 @@ on: - main - develop - release/* + - feature/FWF-3316-permission-matrix paths: - "forms-flow-admin/**" - "VERSION" diff --git a/.github/workflows/forms-flow-integration-cd.yml b/.github/workflows/forms-flow-integration-cd.yml index 92e8da83a..53f8ddcb6 100644 --- a/.github/workflows/forms-flow-integration-cd.yml +++ b/.github/workflows/forms-flow-integration-cd.yml @@ -6,6 +6,7 @@ on: - main - develop - release/* + - feature/FWF-3316-permission-matrix paths: - "forms-flow-integration/**" - "VERSION" diff --git a/.github/workflows/forms-flow-nav.cd.yml b/.github/workflows/forms-flow-nav.cd.yml index d157d4fa0..c9ad5b775 100644 --- a/.github/workflows/forms-flow-nav.cd.yml +++ b/.github/workflows/forms-flow-nav.cd.yml @@ -6,6 +6,7 @@ on: - main - develop - release/* + - feature/FWF-3316-permission-matrix paths: - "forms-flow-nav/**" - "VERSION" diff --git a/.github/workflows/forms-flow-service.yml b/.github/workflows/forms-flow-service.yml index 9bf4596a3..8f6ede2a8 100644 --- a/.github/workflows/forms-flow-service.yml +++ b/.github/workflows/forms-flow-service.yml @@ -6,6 +6,7 @@ on: - main - develop - release/* + - feature/FWF-3316-permission-matrix paths: - "forms-flow-service/**" - "VERSION" diff --git a/.github/workflows/forms-flow-theme.yml b/.github/workflows/forms-flow-theme.yml index 33037713e..6f5dfa948 100644 --- a/.github/workflows/forms-flow-theme.yml +++ b/.github/workflows/forms-flow-theme.yml @@ -6,6 +6,7 @@ on: - main - develop - release/* + - feature/FWF-3316-permission-matrix paths: - "forms-flow-theme/**" - "VERSION" From f6116086b1ec9dfa49d1eeec9a88de9962a49baf Mon Sep 17 00:00:00 2001 From: fahad-aot Date: Mon, 8 Jul 2024 01:35:09 -0700 Subject: [PATCH 10/15] Updated role permissions to individual variables --- forms-flow-nav/src/Navbar.jsx | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/forms-flow-nav/src/Navbar.jsx b/forms-flow-nav/src/Navbar.jsx index bbc273a86..f45c9c942 100644 --- a/forms-flow-nav/src/Navbar.jsx +++ b/forms-flow-nav/src/Navbar.jsx @@ -107,7 +107,14 @@ const NavBar = React.memo(({ props }) => { const formTenant = form?.tenantKey; const baseUrl = MULTITENANCY_ENABLED ? `/tenant/${tenantKey}/` : "/"; const navbarRef = useRef(null); - +const isCreateSubmissions = userRoles.includes("create_submissions"); +const isViewSubmissions = userRoles.includes("view_submissions"); +const isCreateDesigns =userRoles.includes("create_designs"); +const isViewDesigns = userRoles.includes("view_designs"); +const isAdmin =userRoles.includes("admin"); +const isViewTask =userRoles.includes("view_tasks"); +const isManageTask=userRoles.includes("manage_tasks"); +const isViewDashboard=userRoles.includes("view_dashboards") const isDashboardManager = userRoles.includes("manage_dashboard_authorizations"); const isRoleManager = userRoles.includes("manage_roles"); const isUserManager = userRoles.includes("manage_users"); @@ -295,9 +302,9 @@ const isUserManager = userRoles.includes("manage_users"); data-testid="main-menu-nav" > {ENABLE_FORMS_MODULE && - (userRoles.includes("create_submissions") || - userRoles.includes("create_designs") || - userRoles.includes("view_designs")) && ( + (isCreateSubmissions || + isCreateDesigns || + isViewDesigns) && ( )} - {userRoles.includes("admin") && ( + {isAdmin && ( ) } - {userRoles.includes("create_designs") && + {isCreateDesigns && ENABLE_PROCESSES_MODULE && ( )} - {userRoles.includes("view_tasks") && + {(isViewTask ||isManageTask) && ENABLE_TASKS_MODULE && ( )} - {userRoles.includes("view_dashboards") && + {isViewDashboard && ENABLE_DASHBOARDS_MODULE && ( Date: Wed, 17 Jul 2024 16:20:38 +0530 Subject: [PATCH 11/15] [Bugfix] added unique id for checkbox --- .../src/components/roles/roles.tsx | 449 ++++++++++-------- 1 file changed, 256 insertions(+), 193 deletions(-) diff --git a/forms-flow-admin/src/components/roles/roles.tsx b/forms-flow-admin/src/components/roles/roles.tsx index 5dc855d0a..cb6e9eed4 100644 --- a/forms-flow-admin/src/components/roles/roles.tsx +++ b/forms-flow-admin/src/components/roles/roles.tsx @@ -7,7 +7,12 @@ import paginationFactory from "react-bootstrap-table2-paginator"; import Form from "react-bootstrap/Form"; import Button from "react-bootstrap/Button"; import { fetchUsers } from "../../services/users"; -import { CreateRole, DeleteRole, UpdateRole, fetchPermissions } from "../../services/roles"; +import { + CreateRole, + DeleteRole, + UpdateRole, + fetchPermissions, +} from "../../services/roles"; import Modal from "react-bootstrap/Modal"; import Loading from "../loading"; import DropdownButton from "react-bootstrap/DropdownButton"; @@ -36,14 +41,18 @@ const Roles = React.memo((props: any) => { const [showRoleModal, setShowRoleModal] = useState(false); const [showEditRoleModal, setShowEditRoleModal] = useState(false); const [loading, setLoading] = React.useState(false); - const [payload, setPayload] = React.useState({ name: "", description: "" , permissions: [] }); + const [payload, setPayload] = React.useState({ + name: "", + description: "", + permissions: [], + }); // Toggle for Delete Confirm modal const [showConfirmDelete, setShowConfirmDelete] = React.useState(false); const initialRoleType = { name: "", id: "", description: "", - permissions: [] + permissions: [], }; const [deleteCandidate, setDeleteCandidate] = React.useState(initialRoleType); const [selectedRoleIdentifier, setSelectedRoleIdentifier] = @@ -51,46 +60,59 @@ const Roles = React.memo((props: any) => { const [editCandidate, setEditCandidate] = React.useState(initialRoleType); const [disabled, setDisabled] = React.useState(true); const [search, setSerach] = React.useState(""); - const [permission, setPermission] = React.useState([]) + const [permission, setPermission] = React.useState([]); const filterList = (filterTerm, List) => { let roleList = removingTenantId(List); let newRoleList = roleList.filter((role) => { return role.name.toLowerCase().search(filterTerm.toLowerCase()) !== -1; }); - return newRoleList + return newRoleList; }; React.useEffect(() => { - setDisabled(!(payload.name?.trim() && payload.description?.trim() && payload.permissions.length !== 0)); + setDisabled( + !( + payload.name?.trim() && + payload.description?.trim() && + payload.permissions.length !== 0 + ) + ); }, [payload]); React.useEffect(() => { setDisabled( - !(editCandidate.name?.trim() && editCandidate.description?.trim() && editCandidate.permissions.length !== 0) + !( + editCandidate.name?.trim() && + editCandidate.description?.trim() && + editCandidate.permissions.length !== 0 + ) ); }, [editCandidate]); React.useEffect(() => { let updatedRoles = props.roles; - + if (search) { updatedRoles = filterList(search, updatedRoles); } - + if (updatedRoles.length > 0) { updatedRoles = removingTenantId(updatedRoles); } - + setRoles(updatedRoles); }, [props.roles, search]); React.useEffect(() => { - fetchPermissions((data) => { - setPermission(data); - }, (err)=>{ - setError(err); - }); + fetchPermissions( + (data) => { + setPermission(data); + }, + (err) => { + setError(err); + } + ); }, []); const handlFilter = (e) => { @@ -121,28 +143,39 @@ const Roles = React.memo((props: any) => { const handleChangeDescription = (e) => { setPayload({ ...payload, description: e.target.value }); }; - const handlePermissionCheck = (permissionName: string, dependsOn: string[]) => { + const handlePermissionCheck = ( + permissionName: string, + dependsOn: string[] + ) => { let updatedPermissions: string[] = [...payload.permissions]; const isChecked = updatedPermissions.includes(permissionName); - + if (!isChecked) { - updatedPermissions.push(permissionName); - dependsOn.forEach(dependency => { - if (!updatedPermissions.includes(dependency)) { - updatedPermissions.push(dependency); - } - }); + updatedPermissions.push(permissionName); + dependsOn.forEach((dependency) => { + if (!updatedPermissions.includes(dependency)) { + updatedPermissions.push(dependency); + } + }); } else { - updatedPermissions = updatedPermissions.filter(permission => permission !== permissionName); - dependsOn.forEach(dependency => { - updatedPermissions = updatedPermissions.filter(permission => permission !== dependency); - }); + updatedPermissions = updatedPermissions.filter( + (permission) => permission !== permissionName + ); + dependsOn.forEach((dependency) => { + updatedPermissions = updatedPermissions.filter( + (permission) => permission !== dependency + ); + }); } - setPayload ({ ...payload, permissions: updatedPermissions }); -}; + setPayload({ ...payload, permissions: updatedPermissions }); + }; const validateRolePayload = (payload) => { - return !(payload.name === "" || payload.description === "" || payload.permissions.length === 0); + return !( + payload.name === "" || + payload.description === "" || + payload.permissions.length === 0 + ); }; //check regex exept _ - const hasSpecialCharacters = (text) => { @@ -166,12 +199,12 @@ const Roles = React.memo((props: any) => { // return; // } // } else { - if (hasSpecialCharacterswithslash(payload.name)) { - toast.error( - t("Role names cannot contain special characters except _ , - , / ") - ); - return; - } + if (hasSpecialCharacterswithslash(payload.name)) { + toast.error( + t("Role names cannot contain special characters except _ , - , / ") + ); + return; + } // } setDisabled(true); CreateRole( @@ -200,12 +233,12 @@ const Roles = React.memo((props: any) => { // return; // } // } else { - if (hasSpecialCharacterswithslash(editCandidate.name)) { - toast.error( - t("Role names cannot contain special characters except _ , - , / ") - ); - return; - } + if (hasSpecialCharacterswithslash(editCandidate.name)) { + toast.error( + t("Role names cannot contain special characters except _ , - , / ") + ); + return; + } // } setDisabled(true); UpdateRole( @@ -223,7 +256,7 @@ const Roles = React.memo((props: any) => { } ); }; - // handlers for user list popover + // handlers for user list popover const handleClick = (event, rowData) => { setShow(!show); setLoading(true); @@ -252,30 +285,37 @@ const Roles = React.memo((props: any) => { setEditCandidate({ ...editCandidate, description: e.target.value }); }; - const handleEditPermissionCheck = (permissionName: string, dependsOn: string[]) => { + const handleEditPermissionCheck = ( + permissionName: string, + dependsOn: string[] + ) => { let updatedPermissions: string[] = [...editCandidate.permissions]; const isChecked = updatedPermissions.includes(permissionName); - - if (!isChecked) { - updatedPermissions.push(permissionName); - dependsOn.forEach(dependency => { - if (!updatedPermissions.includes(dependency)) { - updatedPermissions.push(dependency); - } - }); + + if (!isChecked) { + updatedPermissions.push(permissionName); + dependsOn.forEach((dependency) => { + if (!updatedPermissions.includes(dependency)) { + updatedPermissions.push(dependency); + } + }); } else { - updatedPermissions = updatedPermissions.filter(permission => permission !== permissionName); - dependsOn.forEach(dependency => { - updatedPermissions = updatedPermissions.filter(permission => permission !== dependency); - }); + updatedPermissions = updatedPermissions.filter( + (permission) => permission !== permissionName + ); + dependsOn.forEach((dependency) => { + updatedPermissions = updatedPermissions.filter( + (permission) => permission !== dependency + ); + }); } - setEditCandidate ({ ...editCandidate, permissions: updatedPermissions }); -}; + setEditCandidate({ ...editCandidate, permissions: updatedPermissions }); + }; // handlers for role create/edit modal const handleCloseRoleModal = () => { setShowRoleModal(false); - setPayload({ name: "", description: "" , permissions: []}); + setPayload({ name: "", description: "", permissions: [] }); }; const handleShowRoleModal = () => setShowRoleModal(true); const handleCloseEditRoleModal = () => { @@ -317,16 +357,16 @@ const Roles = React.memo((props: any) => { const removingTenantId = (roles) => { if (MULTITENANCY_ENABLED && tenantId) { - const updatedRoles = roles.map(role => { + const updatedRoles = roles.map((role) => { if (role.name.startsWith(`/${tenantId}-`)) { return { ...role, - name: role.name.replace(`/${tenantId}-`, '/') + name: role.name.replace(`/${tenantId}-`, "/"), }; } return role; }); - return updatedRoles; + return updatedRoles; } return roles; }; @@ -372,157 +412,180 @@ const Roles = React.memo((props: any) => { const showCreateModal = () => (
- - {t("Create Role")} - - - - - {t("Role Name")} - - * - - - {t("Description")} - - * - + + {t("Create Role")} + + + + + {t("Role Name")} + + * + + + {t("Description")} + + * + - - {t("Permissions")} + + {t("Permissions")} *
- {permission.map((permission) => ( -
- handlePermissionCheck(permission.name, permission.depends_on)} - aria-label={t(permission.description)} - /> -
- ))} -
+ {permission.map((permission) => ( +
+ + handlePermissionCheck( + permission.name, + permission.depends_on + ) + } + aria-label={t(permission.description)} + /> +
+ ))} +
- - - - - + + + + +
); const showEditModal = () => (
- - {t("Edit Role")} - - - - - {t("Role Name")} - - * - - - {t("Description")} - - * - - - {t("Permissions")} + + {t("Edit Role")} + + + + + {t("Role Name")} + + * + + + {t("Description")} + + * + + + {t("Permissions")} *
- {permission.map((permission) => ( -
+ {permission.map((permission) => ( +
handleEditPermissionCheck(permission.name, permission.depends_on)} + checked={editCandidate.permissions.includes( + permission.name + )} + onChange={() => + handleEditPermissionCheck( + permission.name, + permission.depends_on + ) + } aria-label={t(permission.description)} /> -
- ))} +
+ ))}
-
- - - - +
+ + + +
); @@ -658,7 +721,7 @@ const Roles = React.memo((props: any) => { { dataField: "id", text: {(t) => t("Actions")}, - formatter: (cell, rowData, rowIdx, formatExtraData) => { + formatter: (cell, rowData, rowIdx, formatExtraData) => { return checkDefaultRoleOrNot(rowData.name) ? null : (
Date: Mon, 22 Jul 2024 20:32:26 +0530 Subject: [PATCH 12/15] changed svg to component --- .../components/AccessDenied/AccessDenied.js | 46 +++++++++++++++++++ .../components/AccessDenied/AccessDenied.svg | 38 --------------- .../src/components/AccessDenied/index.js | 4 +- 3 files changed, 48 insertions(+), 40 deletions(-) create mode 100644 forms-flow-admin/src/components/AccessDenied/AccessDenied.js delete mode 100644 forms-flow-admin/src/components/AccessDenied/AccessDenied.svg diff --git a/forms-flow-admin/src/components/AccessDenied/AccessDenied.js b/forms-flow-admin/src/components/AccessDenied/AccessDenied.js new file mode 100644 index 000000000..b0478f8c9 --- /dev/null +++ b/forms-flow-admin/src/components/AccessDenied/AccessDenied.js @@ -0,0 +1,46 @@ +// AccessDeniedIcon.js +import React from 'react'; + +const AccessDeniedIcon = () => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); + +export default AccessDeniedIcon; diff --git a/forms-flow-admin/src/components/AccessDenied/AccessDenied.svg b/forms-flow-admin/src/components/AccessDenied/AccessDenied.svg deleted file mode 100644 index e0e0acd51..000000000 --- a/forms-flow-admin/src/components/AccessDenied/AccessDenied.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/forms-flow-admin/src/components/AccessDenied/index.js b/forms-flow-admin/src/components/AccessDenied/index.js index 040855b3c..a97b564f6 100644 --- a/forms-flow-admin/src/components/AccessDenied/index.js +++ b/forms-flow-admin/src/components/AccessDenied/index.js @@ -1,5 +1,5 @@ import React from "react"; -import AccessDeniedIcon from "./AccessDenied.svg"; +import AccessDeniedIcon from "./AccessDenied.js"; import './accessDenied.scss'; import { useTranslation } from "react-i18next"; import { BASE_ROUTE } from "../../constants/index"; @@ -24,7 +24,7 @@ const AccessDenied = ({ userRoles }) => { return (
- Access Denied Icon +

{t("Access Denied")}

{t("You don't have permission to access this page.")} {t("Please contact your administrator or try again later.")} From dd7a83666af237fb7758a2e03cd8b19221113aff Mon Sep 17 00:00:00 2001 From: abilpraju-aot Date: Tue, 23 Jul 2024 12:52:29 +0530 Subject: [PATCH 13/15] resolved comment --- forms-flow-admin/src/components/AccessDenied/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forms-flow-admin/src/components/AccessDenied/index.js b/forms-flow-admin/src/components/AccessDenied/index.js index a97b564f6..fa0e4a3c1 100644 --- a/forms-flow-admin/src/components/AccessDenied/index.js +++ b/forms-flow-admin/src/components/AccessDenied/index.js @@ -24,7 +24,7 @@ const AccessDenied = ({ userRoles }) => { return (
- +

{t("Access Denied")}

{t("You don't have permission to access this page.")} {t("Please contact your administrator or try again later.")} From a38efee0cdd211c5ba83db9d04fcb06e47d24889 Mon Sep 17 00:00:00 2001 From: abilpraju-aot Date: Wed, 24 Jul 2024 14:29:18 +0530 Subject: [PATCH 14/15] navbar initial render fix --- forms-flow-nav/src/Navbar.jsx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/forms-flow-nav/src/Navbar.jsx b/forms-flow-nav/src/Navbar.jsx index f45c9c942..dca62b4dd 100644 --- a/forms-flow-nav/src/Navbar.jsx +++ b/forms-flow-nav/src/Navbar.jsx @@ -107,17 +107,17 @@ const NavBar = React.memo(({ props }) => { const formTenant = form?.tenantKey; const baseUrl = MULTITENANCY_ENABLED ? `/tenant/${tenantKey}/` : "/"; const navbarRef = useRef(null); -const isCreateSubmissions = userRoles.includes("create_submissions"); -const isViewSubmissions = userRoles.includes("view_submissions"); -const isCreateDesigns =userRoles.includes("create_designs"); -const isViewDesigns = userRoles.includes("view_designs"); -const isAdmin =userRoles.includes("admin"); -const isViewTask =userRoles.includes("view_tasks"); -const isManageTask=userRoles.includes("manage_tasks"); -const isViewDashboard=userRoles.includes("view_dashboards") -const isDashboardManager = userRoles.includes("manage_dashboard_authorizations"); -const isRoleManager = userRoles.includes("manage_roles"); -const isUserManager = userRoles.includes("manage_users"); +const isCreateSubmissions = userRoles?.includes("create_submissions"); +const isViewSubmissions = userRoles?.includes("view_submissions"); +const isCreateDesigns =userRoles?.includes("create_designs"); +const isViewDesigns = userRoles?.includes("view_designs"); +const isAdmin =userRoles?.includes("admin"); +const isViewTask =userRoles?.includes("view_tasks"); +const isManageTask=userRoles?.includes("manage_tasks"); +const isViewDashboard=userRoles?.includes("view_dashboards") +const isDashboardManager = userRoles?.includes("manage_dashboard_authorizations"); +const isRoleManager = userRoles?.includes("manage_roles"); +const isUserManager = userRoles?.includes("manage_users"); const ADMIN_BASE_ROUTE = isDashboardManager ? `${baseUrl}admin/dashboard` : isRoleManager @@ -360,7 +360,7 @@ const isUserManager = userRoles.includes("manage_users"); )} - {userRoles.includes("manage_integrations") + {userRoles?.includes("manage_integrations") ? (integrationEnabled || ENABLE_INTEGRATION_PREMIUM) && ( Date: Thu, 25 Jul 2024 13:28:57 +0530 Subject: [PATCH 15/15] FWF-3521 [bugfix] Removed tenantKey from group listing (#243) --- .../src/components/roles/roles.tsx | 23 ++++----------- .../src/components/users/index.tsx | 28 +++++++++++++++---- forms-flow-admin/src/utils/utils.js | 24 ++++++++++++++++ 3 files changed, 51 insertions(+), 24 deletions(-) create mode 100644 forms-flow-admin/src/utils/utils.js diff --git a/forms-flow-admin/src/components/roles/roles.tsx b/forms-flow-admin/src/components/roles/roles.tsx index cb6e9eed4..5f62c3cda 100644 --- a/forms-flow-admin/src/components/roles/roles.tsx +++ b/forms-flow-admin/src/components/roles/roles.tsx @@ -26,6 +26,7 @@ import { } from "../../constants"; import { DEFAULT_ROLES } from "../../constants"; +import {removingTenantId} from "../../utils/utils.js"; const Roles = React.memo((props: any) => { const { t } = useTranslation(); const { tenantId } = useParams(); @@ -63,7 +64,7 @@ const Roles = React.memo((props: any) => { const [permission, setPermission] = React.useState([]); const filterList = (filterTerm, List) => { - let roleList = removingTenantId(List); + let roleList = removingTenantId(List,tenantId); let newRoleList = roleList.filter((role) => { return role.name.toLowerCase().search(filterTerm.toLowerCase()) !== -1; }); @@ -98,7 +99,7 @@ const Roles = React.memo((props: any) => { } if (updatedRoles.length > 0) { - updatedRoles = removingTenantId(updatedRoles); + updatedRoles = removingTenantId(updatedRoles,tenantId); } setRoles(updatedRoles); @@ -355,25 +356,11 @@ const Roles = React.memo((props: any) => { } }; - const removingTenantId = (roles) => { - if (MULTITENANCY_ENABLED && tenantId) { - const updatedRoles = roles.map((role) => { - if (role.name.startsWith(`/${tenantId}-`)) { - return { - ...role, - name: role.name.replace(`/${tenantId}-`, "/"), - }; - } - return role; - }); - return updatedRoles; - } - return roles; - }; + const clearSearch = () => { setSerach(""); - let updatedRoleName = removingTenantId(props.roles); + let updatedRoleName = removingTenantId(props.roles,tenantId); setRoles(updatedRoleName); }; diff --git a/forms-flow-admin/src/components/users/index.tsx b/forms-flow-admin/src/components/users/index.tsx index 2dbd60e96..f5314819e 100644 --- a/forms-flow-admin/src/components/users/index.tsx +++ b/forms-flow-admin/src/components/users/index.tsx @@ -4,9 +4,12 @@ import { fetchRoles } from "../../services/roles"; import { fetchUsers } from "../../services/users"; import Users from "./users"; import {useTranslation} from "react-i18next"; - +import {removingTenantId} from "../../utils/utils.js"; +import { useParams } from "react-router-dom"; +import { MULTITENANCY_ENABLED } from "../../constants"; const UserManagement = React.memo((props: any) => { const { setTab, setCount } = props; + const { tenantId } = useParams(); const [users, setUsers] = React.useState([]); const [roles, setRoles] = React.useState([]); @@ -27,7 +30,7 @@ const UserManagement = React.memo((props: any) => { 1, search, (results) => { - setUsers(results.data); + setUsers(removeTenantIdFromUserRoles(results.data)); setInvalidated(false); setPageNo(1); setLoading(false); @@ -52,7 +55,7 @@ const UserManagement = React.memo((props: any) => { 1, search, (results) => { - setUsers(results.data); + setUsers(removeTenantIdFromUserRoles(results.data)); setInvalidated(false); setPageNo(1); setTotal(results.count); @@ -78,7 +81,7 @@ const UserManagement = React.memo((props: any) => { pageNo, search, (results) => { - setUsers(results.data); + setUsers(removeTenantIdFromUserRoles(results.data)); setTotal(results.count); setInvalidated(false); setLoading(false); @@ -101,7 +104,8 @@ const UserManagement = React.memo((props: any) => { pageNo, null, (results) => { - setUsers(results.data); + + setUsers(removeTenantIdFromUserRoles(results.data)); setCount(results.count); setTotal(results.count); setLoading(false); @@ -113,13 +117,25 @@ const UserManagement = React.memo((props: any) => { ); fetchRoles((data) => { - setRoles(data); + setRoles(removingTenantId(data,tenantId)); }, (err)=>{ setError(err); toast.error(t("Failed to fetch roles!")) }); }, []); + const removeTenantIdFromUserRoles = (data)=>{ + let updatedUserData = [] + if(MULTITENANCY_ENABLED){ + data?.forEach((user)=>{ + user.role = removingTenantId(user.role, tenantId,true) + updatedUserData.push(user) + }) + }else{ + updatedUserData = data + } + return updatedUserData + } return ( <> { + if (MULTITENANCY_ENABLED && tenantId) { + const updatedRoles = roles.map((role) => { + if (role[tenantIdInPath ? "path" : "name"].startsWith(`/${tenantId}-`)) { + if (tenantIdInPath) { + return { + ...role, + name: role.name.replace(`${tenantId}-`, ""), + path: role.path.replace(`/${tenantId}-`, "/"), + }; + } + return { + ...role, + name: role.name.replace(`/${tenantId}-`, "/"), + }; + } + return role; + }); + return updatedRoles; + } + return roles; +};