From c6d381431345d76aeaba92cabb2d25302b4f38e3 Mon Sep 17 00:00:00 2001 From: goodmice Date: Tue, 7 Dec 2021 19:45:13 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A7=D0=B0=D1=81=D1=82=D0=B8=D1=87=D0=BD?= =?UTF-8?q?=D0=BE=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=B2=D0=B7=D0=B0=D0=B8=D0=BC=D0=BE=D0=B4=D0=B5?= =?UTF-8?q?=D0=B9=D1=81=D1=82=D0=B2=D0=B8=D1=82=D0=B5=20=D1=81=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=B0=D0=BC=D0=B8=20=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8F;=20=D0=94?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=20PrivateContent,=20PrivateMenuItem=20=D0=B8=20Pri?= =?UTF-8?q?vateRoute=20=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=20=D1=83=D0=BA=D0=B0?= =?UTF-8?q?=D0=B7=D1=8B=D0=B2=D0=B0=D1=82=D1=8C=20=D1=82=D1=80=D0=B5=D0=B1?= =?UTF-8?q?=D1=83=D0=B5=D0=BC=D1=8B=D0=B5=20=D0=BF=D1=80=D0=B0=D0=B2=D0=B0?= =?UTF-8?q?=20=D0=B8/=D0=B8=D0=BB=D0=B8=20=D1=80=D0=BE=D0=BB=D0=B8=20?= =?UTF-8?q?=D0=B8=20=D1=81=D0=BF=D0=BE=D1=81=D0=BE=D0=B1=20=D0=B8=D1=85=20?= =?UTF-8?q?=D1=81=D0=BE=D0=B2=D0=BC=D0=B5=D1=89=D0=B5=D0=BD=D0=B8=D1=8F;?= =?UTF-8?q?=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B2=D0=B0=D1=8F=20=D0=BF=D0=BE=D0=B4?= =?UTF-8?q?=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B0=20=D1=81=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=86=20=D0=B4=D0=BB=D1=8F=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Private/PrivateContent.tsx | 33 ++--- src/components/Private/PrivateMenuItem.tsx | 13 +- src/components/Private/PrivateRoute.tsx | 31 ++--- src/components/Private/index.ts | 2 +- src/pages/AdminPanel/index.jsx | 55 ++++---- src/utils/permissions.ts | 140 +++++++++++++++++++++ 6 files changed, 200 insertions(+), 74 deletions(-) create mode 100644 src/utils/permissions.ts diff --git a/src/components/Private/PrivateContent.tsx b/src/components/Private/PrivateContent.tsx index dd195d4..2fbecc1 100644 --- a/src/components/Private/PrivateContent.tsx +++ b/src/components/Private/PrivateContent.tsx @@ -1,28 +1,13 @@ -export type Role = string - -const admins: Role[] = ['администратор', 'админ', 'admin'] - -export const isInRole = (roles?: Role[]): boolean => { - // if (localStorage['login'] === 'dev') - // return true - if(!roles?.length) - return true - const role: Role = localStorage['roleName']?.toLowerCase() - if(admins.indexOf(role) > -1) - return true - for(const r of roles) - if(r.toLowerCase() === role) - return true - return false -} - -export const privateContent = (roles?: Role[], children?: T): T | null | undefined => { - return isInRole(roles) ? children : null -} +import React from 'react' +import { Role, Permissions, hasAccess, PermissionMixingType } from '../../utils/permissions' type PrivateContentProps = { - roles?: Role[] - children?: any + permissions?: Permissions + roles?: Role[] + mixing?: PermissionMixingType + children?: any } -export const PrivateContent: React.FC = ({ roles, children }) => privateContent(roles, children) +export const PrivateContent: React.FC = ({ permissions, roles, mixing, children }) => { + return (hasAccess({ permissions, roles, mixing }) && children) || null +} diff --git a/src/components/Private/PrivateMenuItem.tsx b/src/components/Private/PrivateMenuItem.tsx index 6de159f..d3722e4 100644 --- a/src/components/Private/PrivateMenuItem.tsx +++ b/src/components/Private/PrivateMenuItem.tsx @@ -1,12 +1,15 @@ import React from 'react' import { Menu } from 'antd' -import { isInRole, Role } from './PrivateContent' +import { hasAccess, Role, Permissions, PermissionMixingType } from '../../utils/permissions' + type PrivateMenuItemProps = { - roles: Role[] - [props: string]: any + roles?: Role[] + permissions?: Permissions + mixing?: PermissionMixingType + [props: string]: any } -export const PrivateMenuItem: React.FC = ({ roles, ...props }) => { - return isInRole(roles) ? : null +export const PrivateMenuItem: React.FC = ({ roles, permissions, mixing, ...props }) => { + return hasAccess({ permissions, roles, mixing }) ? : null } diff --git a/src/components/Private/PrivateRoute.tsx b/src/components/Private/PrivateRoute.tsx index 49be595..1f301e4 100644 --- a/src/components/Private/PrivateRoute.tsx +++ b/src/components/Private/PrivateRoute.tsx @@ -1,21 +1,24 @@ import React from 'react' import { Route, Redirect } from 'react-router-dom' -import { isInRole, Role } from './PrivateContent' +import { Role, Permissions, hasAccess } from '../../utils/permissions' type PrivateRouteProps = { - children: any - roles: Role[] - [other: string]: any + permissions?: Permissions + roles: Role[] + component?: any + children?: any + [other: string]: any } -export const PrivateRoute: React.FC = ({ children, roles, ...other }) => { - const token = localStorage['token'] - return ( - token && isInRole(roles) ? children : ( - ) - } - /> - ) +export const PrivateRoute: React.FC = ({ permissions, roles, component, children, ...other }) => { + const available = localStorage['token'] && hasAccess({ permissions, roles }) + + return ( + available ? children : ( + + )} + /> + ) } diff --git a/src/components/Private/index.ts b/src/components/Private/index.ts index ab1f42a..a8db623 100644 --- a/src/components/Private/index.ts +++ b/src/components/Private/index.ts @@ -1,3 +1,3 @@ export { PrivateRoute } from './PrivateRoute' -export { privateContent, PrivateContent } from './PrivateContent' +export { PrivateContent } from './PrivateContent' export { PrivateMenuItem } from './PrivateMenuItem' diff --git a/src/pages/AdminPanel/index.jsx b/src/pages/AdminPanel/index.jsx index 580ab93..dbb490a 100644 --- a/src/pages/AdminPanel/index.jsx +++ b/src/pages/AdminPanel/index.jsx @@ -1,11 +1,14 @@ +import React, { Suspense } from 'react' import { Layout, Menu } from 'antd' import { Switch, Link, useParams, Redirect, Route } from 'react-router-dom' import { PrivateMenuItem, PrivateRoute } from '../../components/Private' -import { ClusterController } from './ClusterController' -import { CompanyController } from './CompanyController' -import { DepositController } from './DepositController' -import { UserController } from './UserController' -import { WellController } from './WellController' +import { PermissionNames, PermissionValue } from '../../utils/permissions' + +const ClusterController = React.lazy(() => import('./ClusterController')) +const CompanyController = React.lazy(() => import('./CompanyController')) +const DepositController = React.lazy(() => import('./DepositController')) +const UserController = React.lazy(() => import('./UserController')) +const WellController = React.lazy(() => import('./WellController')) export const AdminPanel = () => { const { tab } = useParams() @@ -18,45 +21,37 @@ export const AdminPanel = () => { selectable={true} selectedKeys={[tab]} > - + Месторождения - + Кусты - + Скважины - + Пользователи - + Компании - - - - - - - - - - - - - - - - - - - - + Loading...}> + + + + + + + + + + + diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts new file mode 100644 index 0000000..3e30d61 --- /dev/null +++ b/src/utils/permissions.ts @@ -0,0 +1,140 @@ +export type Role = string +export type PermissionName = string +export enum PermissionValue { + Nothing = 0, + Read = 1 << 0, + Write = 1 << 1, + Aprove = 1 << 1, + Update = 1 << 1, + Insert = 1 << 2, + Delete = 1 << 3, +} +export type PermissionMixingType = 'and' | 'or' +export type Permissions = [PermissionName, PermissionValue][] + +export const PermissionNames = { + deposit: 'deposit', + cluster: 'cluster', + well: { + _self: 'well', + archive: 'well/archive', + measure: 'well/measure', + message: 'well/message', + report: 'well/report', + drillingProgram: 'well/drillingProgram', + telemetry: { + _self: 'well/telemetry', + status: 'well/telemetry/status', + rop: 'well/telemetry/rop', + }, + operations: { + _self: 'well/operations', + tvd: 'well/operations/tvd', + sections: 'well/operations/sections', + plan: 'well/operations/plan', + fact: 'well/operations/fact', + drillProccesFlow: 'well/operations/drillProccesFlow', + params: 'well/operations/params', + composite: { + _self: 'well/operations/composite', + wells: 'well/operations/composite/wells', + sections: 'well/operations/composite/sections', + } + }, + document: { + _self: 'well/document', + fluidService: 'well/document/fluidService', + cementing: 'well/document/cementing', + nnb: 'well/document/nnb', + gti: 'well/document/gti', + documentsForWell: 'well/document/documentsForWell', + supervisor: 'well/document/supervisor', + master: 'well/document/master' + }, + }, + admin: { + _self: 'admin', + deposit: 'admin/deposit', + cluster: 'admin/cluster', + well: 'admin/well', + user: 'admin/user', + company: 'admin/company', + } +} + +const admins: Role[] = ['администратор', 'админ', 'admin'] + +export const hasPermissions = (permissions?: Permissions): boolean => { + if (!permissions?.length) + return true + return true // TODO: Написать проверку на доступ через права + return false +} + +export const isInRole = (roles?: Role[]): boolean => { + if (localStorage['login'] === 'dev') return true // TODO: Удалить строку + if (!roles?.length) + return true + // TODO: Переписать проверку на доступ через роли + const role: Role = localStorage['roleName']?.toLowerCase() + if (admins.indexOf(role) > -1) + return true + for (const r of roles) + if (r.toLowerCase() === role) + return true + return false +} + +export type hasAccessProps = { + permissions?: Permissions + roles?: Role[] + mixing?: PermissionMixingType +} + +export const hasAccess = ({permissions, roles, mixing}: hasAccessProps): boolean => { + switch (mixing) { + case 'or': + return hasPermissions(permissions) || isInRole(roles) + case 'and': + default: + return hasPermissions(permissions) && isInRole(roles) + } +} + +/* + deposit + cluster + well (R) + well/archive (R) + well/message (R) + well/report (R) + well/measure (RW) + well/drillingProgram (RU согласовать) + well/telemetry (R) + well/telemetry:status (RW) + well/telemetry:rop (RW) + well/operations (R) + well/operations/tvd (R) + well/operations/sections (R) + well/operations/plan (RW) + well/operations/fact (RW) + well/operations/drillProccesFlow (RW) + well/operations/params (RW) + well/operations/composite (R) + well/operations/composite/wells (R) + well/operations/composite/sections (RW) + well/document (R) + well/document/fluidService (RU) + well/document/cementing (RU) + well/document/nnb (RU) + well/document/gti (RU) + well/document/documentsForWell (RU) + well/document/supervisor (RU) + well/document/master (RU) + admin (R) + admin/deposit (RAED) + admin/cluster (RAED) + admin/well (RAED) + admin/user (RAED) + admin/company (RAED) +*/