Skip to content

Commit

Permalink
Merge pull request #233 from fahad-aot/feature/FWF-3435-permission-ma…
Browse files Browse the repository at this point in the history
…trix-admin

Feature/fwf-435 permission matrix Navbar & Admin module
  • Loading branch information
arun-s-aot authored Jul 10, 2024
2 parents 22ef85a + f611608 commit a6a028b
Show file tree
Hide file tree
Showing 5 changed files with 355 additions and 245 deletions.
38 changes: 38 additions & 0 deletions forms-flow-admin/src/components/AccessDenied/AccessDenied.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions forms-flow-admin/src/components/AccessDenied/accessDenied.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.access-denied-text {
font-family: Arial, Helvetica, sans-serif;
font-size: 2rem;
color: var(--ff-black);
opacity: 1;
}
.access-denied{
font-family: Arial, Helvetica, sans-serif;
font-size: 1rem;
color: var(--ff-black);
opacity: 1;
}
45 changes: 45 additions & 0 deletions forms-flow-admin/src/components/AccessDenied/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from "react";
import AccessDeniedIcon from "./AccessDenied.svg";
import './accessDenied.scss';
import { useTranslation } from "react-i18next";
import { BASE_ROUTE } from "../../constants/index";
import { useHistory } from "react-router-dom";


const AccessDenied = ({ userRoles }) => {
const { t } = useTranslation();
const history = useHistory();

const handleLogout = () => {
const kcInstance = kcServiceInstance();
kcInstance.userLogout();
};

const handleReturn = () => {
history.push(BASE_ROUTE);
};

const showReturnToLogin = userRoles?.length === 0;
const showReturnToHome = userRoles?.length > 0;

return (
<div className="d-flex flex-column align-items-center text-center" data-testid="access-denied-component">
<img src={AccessDeniedIcon} alt="Access Denied Icon" className="mb-4 mt-2" />
<h1 className="access-denied-text" data-testid="access-denied-title">{t("Access Denied")}</h1>
<span className="access-denied" data-testid="access-denied-message">{t("You don't have permission to access this page.")}</span>
<span className="access-denied" data-testid="access-denied-submessage">{t("Please contact your administrator or try again later.")}</span>
{showReturnToLogin && (
<button className="btn btn-primary me-1 mt-4" onClick={handleLogout} data-testid="return-to-login-button">
{t("Return to login")}
</button>
)}
{showReturnToHome && (
<button className="btn btn-primary me-1 mt-4" onClick={handleReturn} data-testid="return-to-home-button">
{t("Return to home")}
</button>
)}
</div>
);
};

export default AccessDenied;
105 changes: 64 additions & 41 deletions forms-flow-admin/src/index.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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;
Expand All @@ -27,10 +28,15 @@ 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)
);
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) => {
Expand Down Expand Up @@ -59,47 +65,53 @@ 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_ROLE)){
setIsAdmin(true);
}
const locale = localStorage.getItem("i18nextLng")
if(locale) i18n.changeLanguage(locale);
},[isAuth])

const headerList = () => {
return [
{
const headers =[];
if(isDashboardManager){
headers.push({
name: "Dashboard",
count: dashboardCount,
// icon: "user-circle-o",
onClick: () => history.push(`${baseUrl}admin/dashboard`),
},
{
onClick: () => history.push(`${baseUrl}admin/dashboard`)
})} if (isRoleManager){
headers.push({
name: "Roles",
count: roleCount,
// icon: "user-circle-o",
onClick: () => history.push(`${baseUrl}admin/roles`),
},
{
})} if(isUserManager){
headers.push({
name: "Users",
count: userCount,
// icon: "user-circle-o",
onClick: () => history.push(`${baseUrl}admin/users`),
},
];
onClick: () => history.push(`${baseUrl}admin/users`)
})}
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") ? (
<div className="main-container " tabIndex={0}>
<div className="container mt-5">
<div className="min-container-height ps-md-3">
<div className="container mt-5">
{!isAccessRestricted ?(
<div className="min-container-height ps-md-3">
<Head items={headerList()} page={page} />
<ToastContainer theme="colored" />
<Switch>
<Route
{ isDashboardManager && (
<Route
exact
path={`${BASE_ROUTE}admin/dashboard`}
render={() => (
Expand All @@ -109,19 +121,21 @@ const Admin = React.memo(({ props }: any) => {
setCount={setDashboardCount}
/>
)}
/>
<Route
exact
path={`${BASE_ROUTE}admin/roles`}
render={() => (
<RoleManagement
{...props}
setTab={setPage}
setCount={setRoleCount}
/>
)}
/>
<Route
/>)}
{isRoleManager &&
(<Route
exact
path={`${BASE_ROUTE}admin/roles`}
render={() => (
<RoleManagement
{...props}
setTab={setPage}
setCount={setRoleCount}
/>
)}
/>)}
{ isUserManager && (
<Route
exact
path={`${BASE_ROUTE}admin/users`}
render={() => (
Expand All @@ -131,14 +145,23 @@ const Admin = React.memo(({ props }: any) => {
setCount={setUserCount}
/>
)}
/>
<Redirect from="*" to="/404" />
/>)}
</Switch>
</div>
</div>):
<div className="min-container-height ps-md-3" >
<Accessdenied userRoles={userRoles} />
</div> }
<Footer />
</div>
</div>
)}
):<div className="main-container ">
<div className="container mt-5">
<div className="min-container-height ps-md-3" >
<Accessdenied userRoles={userRoles} />
</div>
<Footer />
</div>
</div>}
</>
);
});
Expand Down
Loading

0 comments on commit a6a028b

Please sign in to comment.