forked from ddrilling/asb_cloud_front
Частично реализовано взаимодействите с правами пользователя;
Для компоненов PrivateContent, PrivateMenuItem и PrivateRoute можно указывать требуемые права и/или роли и способ их совмещения; Добавлена ленивая подгрузка страниц для тестирования;
This commit is contained in:
parent
741449fb99
commit
c6d3814313
@ -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 = <T extends unknown>(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 = {
|
||||
permissions?: Permissions
|
||||
roles?: Role[]
|
||||
mixing?: PermissionMixingType
|
||||
children?: any
|
||||
}
|
||||
|
||||
export const PrivateContent: React.FC<PrivateContentProps> = ({ roles, children }) => privateContent(roles, children)
|
||||
export const PrivateContent: React.FC<PrivateContentProps> = ({ permissions, roles, mixing, children }) => {
|
||||
return (hasAccess({ permissions, roles, mixing }) && children) || null
|
||||
}
|
||||
|
@ -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[]
|
||||
roles?: Role[]
|
||||
permissions?: Permissions
|
||||
mixing?: PermissionMixingType
|
||||
[props: string]: any
|
||||
}
|
||||
|
||||
export const PrivateMenuItem: React.FC<PrivateMenuItemProps> = ({ roles, ...props }) => {
|
||||
return isInRole(roles) ? <Menu.Item {...props}/> : null
|
||||
export const PrivateMenuItem: React.FC<PrivateMenuItemProps> = ({ roles, permissions, mixing, ...props }) => {
|
||||
return hasAccess({ permissions, roles, mixing }) ? <Menu.Item {...props}/> : null
|
||||
}
|
||||
|
@ -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
|
||||
permissions?: Permissions
|
||||
roles: Role[]
|
||||
component?: any
|
||||
children?: any
|
||||
[other: string]: any
|
||||
}
|
||||
|
||||
export const PrivateRoute: React.FC<PrivateRouteProps> = ({ children, roles, ...other }) => {
|
||||
const token = localStorage['token']
|
||||
export const PrivateRoute: React.FC<PrivateRouteProps> = ({ permissions, roles, component, children, ...other }) => {
|
||||
const available = localStorage['token'] && hasAccess({ permissions, roles })
|
||||
|
||||
return (
|
||||
<Route
|
||||
{...other}
|
||||
render={({ location }) => token && isInRole(roles) ? children : (
|
||||
<Redirect to={{ pathname: "/login", state: { from: location } }} />)
|
||||
}
|
||||
<Route {...other}
|
||||
component={available && component}
|
||||
render={({ location }) => available ? children : (
|
||||
<Redirect to={{ pathname: '/login', state: { from: location } }} />
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
export { PrivateRoute } from './PrivateRoute'
|
||||
export { privateContent, PrivateContent } from './PrivateContent'
|
||||
export { PrivateContent } from './PrivateContent'
|
||||
export { PrivateMenuItem } from './PrivateMenuItem'
|
||||
|
@ -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]}
|
||||
>
|
||||
<PrivateMenuItem roles={['deposit_admin']} key={'deposit'}>
|
||||
<PrivateMenuItem key={'deposit'} permissions={[[PermissionNames.admin.deposit, PermissionValue.Read]]}>
|
||||
<Link to={`${rootPath}/deposit`}>Месторождения</Link>
|
||||
</PrivateMenuItem>
|
||||
<PrivateMenuItem roles={['cluster_admin']} key={'cluster'}>
|
||||
<PrivateMenuItem key={'cluster'} permissions={[[PermissionNames.admin.cluster, PermissionValue.Read]]}>
|
||||
<Link to={`${rootPath}/cluster`}>Кусты</Link>
|
||||
</PrivateMenuItem>
|
||||
<PrivateMenuItem roles={['well_admin']} key={'well'}>
|
||||
<PrivateMenuItem key={'well'} permissions={[[PermissionNames.admin.well, PermissionValue.Read]]}>
|
||||
<Link to={`${rootPath}/well`}>Скважины</Link>
|
||||
</PrivateMenuItem>
|
||||
<PrivateMenuItem roles={['user_admin']} key={'user'}>
|
||||
<PrivateMenuItem key={'user'} permissions={[[PermissionNames.admin.user, PermissionValue.Read]]}>
|
||||
<Link to={`${rootPath}/user`}>Пользователи</Link>
|
||||
</PrivateMenuItem>
|
||||
<PrivateMenuItem roles={['company_admin']} key={'company'}>
|
||||
<PrivateMenuItem key={'company'} permissions={[[PermissionNames.admin.company, PermissionValue.Read]]}>
|
||||
<Link to={`${rootPath}/company`}>Компании</Link>
|
||||
</PrivateMenuItem>
|
||||
</Menu>
|
||||
|
||||
<Layout>
|
||||
<Layout.Content className={'site-layout-background'}>
|
||||
<Suspense fallback={<div>Loading...</div>}>
|
||||
<Switch>
|
||||
<PrivateRoute roles={['deposit_admin']} path={`${rootPath}/deposit`}>
|
||||
<DepositController />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute roles={['cluster_admin']} path={`${rootPath}/cluster`}>
|
||||
<ClusterController />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute roles={['well_admin']} path={`${rootPath}/well`}>
|
||||
<WellController />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute roles={['user_admin']} path={`${rootPath}/user`}>
|
||||
<UserController />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute roles={['company_admin']} path={`${rootPath}/company`}>
|
||||
<CompanyController />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute roles={['deposit_admin']} path={`${rootPath}/deposit`} component={DepositController} />
|
||||
<PrivateRoute roles={['cluster_admin']} path={`${rootPath}/cluster`} component={ClusterController} />
|
||||
<PrivateRoute roles={[ 'well_admin']} path={`${rootPath}/well` } component={ WellController} />
|
||||
<PrivateRoute roles={[ 'user_admin']} path={`${rootPath}/user` } component={ UserController} />
|
||||
<PrivateRoute roles={['company_admin']} path={`${rootPath}/company`} component={CompanyController} />
|
||||
<Route path={'/'}>
|
||||
<Redirect to={`${rootPath}/deposit`}/>
|
||||
</Route>
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</Layout.Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
|
140
src/utils/permissions.ts
Normal file
140
src/utils/permissions.ts
Normal file
@ -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)
|
||||
*/
|
Loading…
Reference in New Issue
Block a user