update permion server
This commit is contained in:
@@ -0,0 +1,175 @@
|
|||||||
|
export enum PermissionEnum {
|
||||||
|
SERVICES_CREATE = "services_create",
|
||||||
|
SERVICES_READ = "services_read",
|
||||||
|
SERVICES_UPDATE = "services_update",
|
||||||
|
SERVICES_DELETE = "services_delete",
|
||||||
|
|
||||||
|
CUSTOMERS_CREATE = "customers_create",
|
||||||
|
CUSTOMERS_READ = "customers_read",
|
||||||
|
CUSTOMERS_UPDATE = "customers_update",
|
||||||
|
CUSTOMERS_DELETE = "customers_delete",
|
||||||
|
|
||||||
|
AGENTS_CREATE = "agents_create",
|
||||||
|
AGENTS_READ = "agents_read",
|
||||||
|
AGENTS_UPDATE = "agents_update",
|
||||||
|
AGENTS_DELETE = "agents_delete",
|
||||||
|
|
||||||
|
DEVELOPERS_CREATE = "developers_create",
|
||||||
|
DEVELOPERS_READ = "developers_read",
|
||||||
|
DEVELOPERS_UPDATE = "developers_update",
|
||||||
|
DEVELOPERS_DELETE = "developers_delete",
|
||||||
|
|
||||||
|
INVOICES_CREATE = "invoices_create",
|
||||||
|
INVOICES_READ = "invoices_read",
|
||||||
|
INVOICES_UPDATE = "invoices_update",
|
||||||
|
INVOICES_DELETE = "invoices_delete",
|
||||||
|
|
||||||
|
TRANSACTIONS_CREATE = "transactions_create",
|
||||||
|
TRANSACTIONS_READ = "transactions_read",
|
||||||
|
TRANSACTIONS_UPDATE = "transactions_update",
|
||||||
|
TRANSACTIONS_DELETE = "transactions_delete",
|
||||||
|
|
||||||
|
DISCOUNTS_CREATE = "discounts_create",
|
||||||
|
DISCOUNTS_READ = "discounts_read",
|
||||||
|
DISCOUNTS_UPDATE = "discounts_update",
|
||||||
|
DISCOUNTS_DELETE = "discounts_delete",
|
||||||
|
|
||||||
|
ADMINS_CREATE = "admins_create",
|
||||||
|
ADMINS_READ = "admins_read",
|
||||||
|
ADMINS_UPDATE = "admins_update",
|
||||||
|
ADMINS_DELETE = "admins_delete",
|
||||||
|
|
||||||
|
TICKETS_CREATE = "tickets_create",
|
||||||
|
TICKETS_READ = "tickets_read",
|
||||||
|
TICKETS_UPDATE = "tickets_update",
|
||||||
|
TICKETS_DELETE = "tickets_delete",
|
||||||
|
|
||||||
|
CRITICISMS_CREATE = "criticisms_create",
|
||||||
|
CRITICISMS_READ = "criticisms_read",
|
||||||
|
CRITICISMS_UPDATE = "criticisms_update",
|
||||||
|
CRITICISMS_DELETE = "criticisms_delete",
|
||||||
|
|
||||||
|
CONTACTS_US_CREATE = "contacts_us_create",
|
||||||
|
CONTACTS_US_READ = "contacts_us_read",
|
||||||
|
CONTACTS_US_UPDATE = "contacts_us_update",
|
||||||
|
CONTACTS_US_DELETE = "contacts_us_delete",
|
||||||
|
|
||||||
|
ADVERTISEMENTS_CREATE = "advertisements_create",
|
||||||
|
ADVERTISEMENTS_READ = "advertisements_read",
|
||||||
|
ADVERTISEMENTS_UPDATE = "advertisements_update",
|
||||||
|
ADVERTISEMENTS_DELETE = "advertisements_delete",
|
||||||
|
|
||||||
|
ANNOUNCEMENTS_CREATE = "announcements_create",
|
||||||
|
ANNOUNCEMENTS_READ = "announcements_read",
|
||||||
|
ANNOUNCEMENTS_UPDATE = "announcements_update",
|
||||||
|
ANNOUNCEMENTS_DELETE = "announcements_delete",
|
||||||
|
|
||||||
|
BLOGS_CREATE = "blogs_create",
|
||||||
|
BLOGS_READ = "blogs_read",
|
||||||
|
BLOGS_UPDATE = "blogs_update",
|
||||||
|
BLOGS_DELETE = "blogs_delete",
|
||||||
|
|
||||||
|
LEARNINGS_CREATE = "learnings_create",
|
||||||
|
LEARNINGS_READ = "learnings_read",
|
||||||
|
LEARNINGS_UPDATE = "learnings_update",
|
||||||
|
LEARNINGS_DELETE = "learnings_delete",
|
||||||
|
|
||||||
|
SETTINGS_CREATE = "settings_create",
|
||||||
|
SETTINGS_READ = "settings_read",
|
||||||
|
SETTINGS_UPDATE = "settings_update",
|
||||||
|
SETTINGS_DELETE = "settings_delete",
|
||||||
|
|
||||||
|
BANK_ACCOUNTS_CREATE = "bank_accounts_create",
|
||||||
|
BANK_ACCOUNTS_READ = "bank_accounts_read",
|
||||||
|
BANK_ACCOUNTS_UPDATE = "bank_accounts_update",
|
||||||
|
BANK_ACCOUNTS_DELETE = "bank_accounts_delete",
|
||||||
|
|
||||||
|
PAYMENTS_CREATE = "payments_create",
|
||||||
|
PAYMENTS_READ = "payments_read",
|
||||||
|
PAYMENTS_UPDATE = "payments_update",
|
||||||
|
PAYMENTS_DELETE = "payments_delete",
|
||||||
|
|
||||||
|
SUPPORT_PLAN_CREATE = "support_plan_create",
|
||||||
|
SUPPORT_PLAN_READ = "support_plan_read",
|
||||||
|
SUPPORT_PLAN_UPDATE = "support_plan_update",
|
||||||
|
SUPPORT_PLAN_DELETE = "support_plan_delete",
|
||||||
|
|
||||||
|
RESELLER_CREATE = "reseller_create",
|
||||||
|
RESELLER_READ = "reseller_read",
|
||||||
|
RESELLER_UPDATE = "reseller_update",
|
||||||
|
RESELLER_DELETE = "reseller_delete",
|
||||||
|
|
||||||
|
WORKSPACE_CREATE = "workspace_create",
|
||||||
|
WORKSPACE_READ = "workspace_read",
|
||||||
|
WORKSPACE_UPDATE = "workspace_update",
|
||||||
|
WORKSPACE_DELETE = "workspace_delete",
|
||||||
|
|
||||||
|
PROJECT_CREATE = "project_create",
|
||||||
|
PROJECT_READ = "project_read",
|
||||||
|
PROJECT_UPDATE = "project_update",
|
||||||
|
PROJECT_DELETE = "project_delete",
|
||||||
|
|
||||||
|
TASK_CREATE = "task_create",
|
||||||
|
TASK_READ = "task_read",
|
||||||
|
TASK_UPDATE = "task_update",
|
||||||
|
TASK_DELETE = "task_delete",
|
||||||
|
|
||||||
|
TASK_PHASE_CREATE = "task_phase_create",
|
||||||
|
TASK_PHASE_READ = "task_phase_read",
|
||||||
|
TASK_PHASE_UPDATE = "task_phase_update",
|
||||||
|
TASK_PHASE_DELETE = "task_phase_delete",
|
||||||
|
|
||||||
|
LOGS = "logs",
|
||||||
|
MANAGE_SSO_CLIENTS = "manage_sso_clients",
|
||||||
|
DMENU = "dmenu",
|
||||||
|
DKALA = "dkala",
|
||||||
|
DPAGE = "dpage",
|
||||||
|
DMAIL = "dmail",
|
||||||
|
}
|
||||||
|
|
||||||
|
const CRUD_ACTIONS = ["create", "read", "update", "delete"] as const;
|
||||||
|
|
||||||
|
export const CONTENT_PERMISSION_RESOURCES = ["blogs", "learnings", "advertisements", "announcements"] as const;
|
||||||
|
export const FINANCIAL_PERMISSION_RESOURCES = ["payments", "invoices", "transactions", "discounts", "bank_accounts"] as const;
|
||||||
|
export const SUPPORT_PERMISSION_RESOURCES = ["support_plan", "tickets"] as const;
|
||||||
|
export const TASK_MANAGER_PERMISSION_RESOURCES = ["workspace", "project", "task", "task_phase"] as const;
|
||||||
|
export const PRODUCT_PERMISSION_RESOURCES = ["dmenu", "dkala", "dpage", "dmail"] as const;
|
||||||
|
|
||||||
|
type PermissionEntry = { name: string };
|
||||||
|
|
||||||
|
export const getPermissionNames = (permissions: PermissionEntry[] | undefined): string[] =>
|
||||||
|
permissions?.map((permission) => permission.name) ?? [];
|
||||||
|
|
||||||
|
export const hasPermission = (
|
||||||
|
permissions: PermissionEntry[] | undefined,
|
||||||
|
resourceOrPermission: string,
|
||||||
|
): boolean => {
|
||||||
|
const names = getPermissionNames(permissions);
|
||||||
|
|
||||||
|
if (names.includes(resourceOrPermission)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CRUD_ACTIONS.some((action) => names.includes(`${resourceOrPermission}_${action}`));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hasAnyPermission = (
|
||||||
|
permissions: PermissionEntry[] | undefined,
|
||||||
|
resources: readonly string[],
|
||||||
|
): boolean => resources.some((resource) => hasPermission(permissions, resource));
|
||||||
|
|
||||||
|
export const canAccessMenuItem = (
|
||||||
|
permissions: PermissionEntry[] | undefined,
|
||||||
|
activeName?: string,
|
||||||
|
activeNames?: readonly string[],
|
||||||
|
): boolean => {
|
||||||
|
if (activeNames && activeNames.length > 0) {
|
||||||
|
return hasAnyPermission(permissions, activeNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!activeName) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasPermission(permissions, activeName);
|
||||||
|
};
|
||||||
+20
-12
@@ -19,6 +19,14 @@ import LogoSmall from "../assets/images/logo-small.svg";
|
|||||||
import LogoImage from "../assets/images/logo.svg";
|
import LogoImage from "../assets/images/logo.svg";
|
||||||
import { Pages } from "../config/Pages";
|
import { Pages } from "../config/Pages";
|
||||||
import { getSubMenuNameFromPath } from "../config/SideBarSubMenu";
|
import { getSubMenuNameFromPath } from "../config/SideBarSubMenu";
|
||||||
|
import {
|
||||||
|
CONTENT_PERMISSION_RESOURCES,
|
||||||
|
FINANCIAL_PERMISSION_RESOURCES,
|
||||||
|
hasAnyPermission,
|
||||||
|
hasPermission,
|
||||||
|
PRODUCT_PERMISSION_RESOURCES,
|
||||||
|
SUPPORT_PERMISSION_RESOURCES,
|
||||||
|
} from "../helpers/permissions";
|
||||||
import { clx } from "../helpers/utils";
|
import { clx } from "../helpers/utils";
|
||||||
import { useGetProfile } from "../pages/profile/hooks/useProfileData";
|
import { useGetProfile } from "../pages/profile/hooks/useProfileData";
|
||||||
import { useGetAdminPermissions } from "../pages/users/hooks/useUserData";
|
import { useGetAdminPermissions } from "../pages/users/hooks/useUserData";
|
||||||
@@ -44,16 +52,16 @@ const SideBar: FC = () => {
|
|||||||
const isGroupActive = (name: string) => subMenuName === name || getSubMenuNameFromPath(location.pathname) === name;
|
const isGroupActive = (name: string) => subMenuName === name || getSubMenuNameFromPath(location.pathname) === name;
|
||||||
const isPathActive = (name: string) => location.pathname.includes(name);
|
const isPathActive = (name: string) => location.pathname.includes(name);
|
||||||
|
|
||||||
const hasProductPermission = adminPermissions?.data?.permissions?.some((permission: { name: string }) =>
|
const permissions = adminPermissions?.data?.permissions;
|
||||||
["dmenu", "dkala", "dpage", "dmail"].includes(permission.name),
|
|
||||||
);
|
const hasProductPermission = hasAnyPermission(permissions, PRODUCT_PERMISSION_RESOURCES);
|
||||||
|
|
||||||
const productsDefaultLink = (() => {
|
const productsDefaultLink = (() => {
|
||||||
const permissions = adminPermissions?.data?.permissions?.map((p: { name: string }) => p.name) ?? [];
|
const permissionNames = permissions?.map((p: { name: string }) => p.name) ?? [];
|
||||||
if (permissions.includes("dmenu")) return Pages.dmenu.icons.list;
|
if (permissionNames.includes("dmenu")) return Pages.dmenu.icons.list;
|
||||||
if (permissions.includes("dkala")) return Pages.dkala.icons.list;
|
if (permissionNames.includes("dkala")) return Pages.dkala.icons.list;
|
||||||
if (permissions.includes("dmail")) return Pages.dmail.list;
|
if (permissionNames.includes("dmail")) return Pages.dmail.list;
|
||||||
if (permissions.includes("dpage")) return Pages.dpage.stickers.list;
|
if (permissionNames.includes("dpage")) return Pages.dpage.stickers.list;
|
||||||
return Pages.dashboard;
|
return Pages.dashboard;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
@@ -148,7 +156,7 @@ const SideBar: FC = () => {
|
|||||||
activeName="customers"
|
activeName="customers"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === "reseller") && (
|
{hasPermission(permissions, "reseller") && (
|
||||||
<SideBarItem
|
<SideBarItem
|
||||||
icon={
|
icon={
|
||||||
<UserTick
|
<UserTick
|
||||||
@@ -206,7 +214,7 @@ const SideBar: FC = () => {
|
|||||||
isActive={isGroupActive("content")}
|
isActive={isGroupActive("content")}
|
||||||
link={Pages.blog.list}
|
link={Pages.blog.list}
|
||||||
name="content"
|
name="content"
|
||||||
activeName=""
|
activeNames={CONTENT_PERMISSION_RESOURCES}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SideBarItem
|
<SideBarItem
|
||||||
@@ -221,7 +229,7 @@ const SideBar: FC = () => {
|
|||||||
isActive={isGroupActive("financial")}
|
isActive={isGroupActive("financial")}
|
||||||
link={Pages.payment.list}
|
link={Pages.payment.list}
|
||||||
name="financial"
|
name="financial"
|
||||||
activeName=""
|
activeNames={FINANCIAL_PERMISSION_RESOURCES}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SideBarItem
|
<SideBarItem
|
||||||
@@ -236,7 +244,7 @@ const SideBar: FC = () => {
|
|||||||
isActive={isGroupActive("support")}
|
isActive={isGroupActive("support")}
|
||||||
link={Pages.support.list}
|
link={Pages.support.list}
|
||||||
name="support"
|
name="support"
|
||||||
activeName=""
|
activeNames={SUPPORT_PERMISSION_RESOURCES}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{profile?.data?.user?.roles?.some((role: { name: string }) => role.name === "super_admin") && (
|
{profile?.data?.user?.roles?.some((role: { name: string }) => role.name === "super_admin") && (
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { clx } from '../helpers/utils'
|
|||||||
import { Pages } from '../config/Pages'
|
import { Pages } from '../config/Pages'
|
||||||
import { useSharedStore } from './store/sharedStore'
|
import { useSharedStore } from './store/sharedStore'
|
||||||
import { removeToken, removeRefreshToken } from '../config/func'
|
import { removeToken, removeRefreshToken } from '../config/func'
|
||||||
|
import { canAccessMenuItem } from '../helpers/permissions'
|
||||||
import { useGetAdminPermissions } from '../pages/users/hooks/useUserData'
|
import { useGetAdminPermissions } from '../pages/users/hooks/useUserData'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -13,7 +14,8 @@ type Props = {
|
|||||||
link: string,
|
link: string,
|
||||||
isLogout?: boolean,
|
isLogout?: boolean,
|
||||||
name?: string,
|
name?: string,
|
||||||
activeName?: string
|
activeName?: string,
|
||||||
|
activeNames?: readonly string[],
|
||||||
}
|
}
|
||||||
|
|
||||||
const SideBarItem: FC<Props> = (props: Props) => {
|
const SideBarItem: FC<Props> = (props: Props) => {
|
||||||
@@ -32,7 +34,7 @@ const SideBarItem: FC<Props> = (props: Props) => {
|
|||||||
setSubtMenu(true)
|
setSubtMenu(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (props.activeName === '' || props.activeName && adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === props.activeName)) {
|
if (canAccessMenuItem(adminPermissions?.data?.permissions, props.activeName, props.activeNames)) {
|
||||||
return (
|
return (
|
||||||
<Link onClick={props.isLogout ? handleLogout : handleClick} to={props.link} className={clx(
|
<Link onClick={props.isLogout ? handleLogout : handleClick} to={props.link} className={clx(
|
||||||
'flex text-xs gap-9 mt-4',
|
'flex text-xs gap-9 mt-4',
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
import { ArrowDown2 } from "iconsax-react";
|
import { ArrowDown2 } from "iconsax-react";
|
||||||
import { FC, ReactNode, useEffect, useState } from "react";
|
import { FC, ReactNode, useEffect, useState } from "react";
|
||||||
import { clx } from "../../helpers/utils";
|
import { clx } from "../../helpers/utils";
|
||||||
|
import { canAccessMenuItem } from "../../helpers/permissions";
|
||||||
import { useGetAdminPermissions } from "../../pages/users/hooks/useUserData";
|
import { useGetAdminPermissions } from "../../pages/users/hooks/useUserData";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
title: string;
|
title: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
activeName?: string;
|
activeName?: string;
|
||||||
|
activeNames?: readonly string[];
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SubMenuAccordion: FC<Props> = ({ title, isActive, activeName = "", children }) => {
|
const SubMenuAccordion: FC<Props> = ({ title, isActive, activeName, activeNames, children }) => {
|
||||||
const { data: adminPermissions } = useGetAdminPermissions();
|
const { data: adminPermissions } = useGetAdminPermissions();
|
||||||
const [open, setOpen] = useState(isActive);
|
const [open, setOpen] = useState(isActive);
|
||||||
|
|
||||||
@@ -20,10 +22,7 @@ const SubMenuAccordion: FC<Props> = ({ title, isActive, activeName = "", childre
|
|||||||
}
|
}
|
||||||
}, [isActive]);
|
}, [isActive]);
|
||||||
|
|
||||||
if (
|
if (!canAccessMenuItem(adminPermissions?.data?.permissions, activeName, activeNames)) {
|
||||||
activeName !== "" &&
|
|
||||||
!adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === activeName)
|
|
||||||
) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { clx } from "../../helpers/utils";
|
import { clx } from "../../helpers/utils";
|
||||||
|
import { canAccessMenuItem } from "../../helpers/permissions";
|
||||||
import { useGetAdminPermissions } from "../../pages/users/hooks/useUserData";
|
import { useGetAdminPermissions } from "../../pages/users/hooks/useUserData";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -9,16 +10,13 @@ type Props = {
|
|||||||
link: string;
|
link: string;
|
||||||
isLogout?: boolean;
|
isLogout?: boolean;
|
||||||
activeName?: string;
|
activeName?: string;
|
||||||
|
activeNames?: readonly string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const SubMenuItem: FC<Props> = (props: Props) => {
|
const SubMenuItem: FC<Props> = (props: Props) => {
|
||||||
const { data: adminPermissions } = useGetAdminPermissions();
|
const { data: adminPermissions } = useGetAdminPermissions();
|
||||||
|
|
||||||
if (
|
if (!canAccessMenuItem(adminPermissions?.data?.permissions, props.activeName, props.activeNames)) {
|
||||||
props.activeName !== undefined &&
|
|
||||||
props.activeName !== "" &&
|
|
||||||
!adminPermissions?.data?.permissions?.some((permission: { name: string }) => permission.name === props.activeName)
|
|
||||||
) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { FC } from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
import { Pages } from "../../config/Pages";
|
import { Pages } from "../../config/Pages";
|
||||||
|
import { TASK_MANAGER_PERMISSION_RESOURCES } from "../../helpers/permissions";
|
||||||
import SubMenuItem from "./SubMenuItem";
|
import SubMenuItem from "./SubMenuItem";
|
||||||
|
|
||||||
const UsersSubMenu: FC = () => {
|
const UsersSubMenu: FC = () => {
|
||||||
@@ -54,6 +55,7 @@ const UsersSubMenu: FC = () => {
|
|||||||
title={t("sidebar.taskmanager")}
|
title={t("sidebar.taskmanager")}
|
||||||
isActive={isTaskManagerActive}
|
isActive={isTaskManagerActive}
|
||||||
link={Pages.taskmanager.workspaceList}
|
link={Pages.taskmanager.workspaceList}
|
||||||
|
activeNames={TASK_MANAGER_PERMISSION_RESOURCES}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user