Методы работы с правами переработаны, стили исправлены

This commit is contained in:
Александр Сироткин 2021-12-15 11:01:18 +05:00
parent 6ce6ba04ea
commit d9abe87ba4
13 changed files with 298 additions and 436 deletions

View File

@ -1,13 +1,11 @@
import React from 'react'
import { Role, Permissions, hasAccess, PermissionMixingType } from '../../utils/permissions'
import { Role, Permission, hasPermission, isInRole } from '../../utils/PermissionService'
type PrivateContentProps = {
permissions?: Permissions
roles?: Role[]
mixing?: PermissionMixingType
children?: any
roles?: Role[] | Role
permission?: Permission
children?: React.ReactElement<any, any>
}
export const PrivateContent: React.FC<PrivateContentProps> = ({ permissions, roles, mixing, children }) => {
return (hasAccess({ permissions, roles, mixing }) && children) || null
}
export const PrivateContent: React.FC<PrivateContentProps> = ({ permission, roles, children = null }) =>
hasPermission(permission) || isInRole(roles) ? children : null

View File

@ -1,15 +1,13 @@
import React from 'react'
import { Menu } from 'antd'
import { hasAccess, Role, Permissions, PermissionMixingType } from '../../utils/permissions'
import { Role, Permission, hasPermission, isInRole } from '../../utils/PermissionService'
type PrivateMenuItemProps = {
roles?: Role[]
permissions?: Permissions
mixing?: PermissionMixingType
roles?: Role[] | Role
permission?: Permission
[props: string]: any
}
export const PrivateMenuItem: React.FC<PrivateMenuItemProps> = ({ roles, permissions, mixing, ...props }) => {
return hasAccess({ permissions, roles, mixing }) ? <Menu.Item {...props}/> : null
}
export const PrivateMenuItem: React.FC<PrivateMenuItemProps> = ({ roles, permission, mixing, ...props }) =>
hasPermission(permission) || isInRole(roles) ? <Menu.Item {...props}/> : null

View File

@ -1,21 +1,22 @@
import React from 'react'
import { Route, Redirect } from 'react-router-dom'
import { Role, Permissions, hasAccess } from '../../utils/permissions'
import { StaticContext } from 'react-router'
import { Route, Redirect, RouteComponentProps } from 'react-router-dom'
import { Role, Permission, hasPermission, isInRole } from '../../utils/PermissionService'
type PrivateRouteProps = {
permissions?: Permissions
roles: Role[]
component?: any
children?: any
roles: Role[] | Role
permission?: Permission
component?: React.ComponentType<any> | React.ComponentType<RouteComponentProps<any, StaticContext, unknown>>
children?: React.ReactNode
[other: string]: any
}
export const PrivateRoute: React.FC<PrivateRouteProps> = ({ permissions, roles, component, children, ...other }) => {
const available = localStorage['token'] && hasAccess({ permissions, roles })
export const PrivateRoute: React.FC<PrivateRouteProps> = ({ permission, roles, component, children, ...other }) => {
const available = localStorage.getItem('token') && (hasPermission(permission) || isInRole(roles))
return (
<Route {...other}
component={available && component}
component={available ? component : undefined}
render={({ location }) => available ? children : (
<Redirect to={{ pathname: '/login', state: { from: location } }} />
)}

View File

@ -38,8 +38,8 @@ export const EditableTable = ({
dataSource,
onChange, // Метод вызывается со всем dataSource с измененными элементами после любого действия
onRowAdd, // Метод вызывается с новой добавленной записью. Если метод не определен, то кнопка добавления строки не показывается
onRowEdit,// Метод вызывается с новой отредактированной записью. Если метод не поределен, то кнопка редактирования строки не показывается
onRowDelete,// Метод вызывается с удаленной записью. Если метод не поределен, то кнопка удаления строки не показывается
onRowEdit, // Метод вызывается с новой отредактированной записью. Если метод не поределен, то кнопка редактирования строки не показывается
onRowDelete, // Метод вызывается с удаленной записью. Если метод не поределен, то кнопка удаления строки не показывается
...otherTableProps
}) => {
@ -73,10 +73,6 @@ export const EditableTable = ({
...form.initialValues,
key:newRowKeyValue
}
// const newRow = { key: newRowKeyValue }
// for (let column of columns)
// newRow[column.dataIndex] = form.initialValues?.[column.dataIndex] ?? column.initialValue
const newData = [newRow, ...data]
setData(newData)

View File

@ -27,15 +27,15 @@ export const makeNumericRender = (fixed?: number) => (value: any, row: object):
)
}
export const makeNumericColumnOptions = (fixed?: number, sorterKey?: string ) => ({
export const makeNumericColumnOptions = (fixed?: number, sorterKey?: string) => ({
editable: true,
initialValue: 0,
width:100,
sorter: sorterKey? makeNumericSorter(sorterKey) : null,
width: 100,
sorter: sorterKey ? makeNumericSorter(sorterKey) : null,
formItemRules: [
{
required: true,
message: `Введите число`,
message: 'Введите число',
pattern: RegExpIsFloat,
},
],
@ -58,7 +58,7 @@ interface columnPropsOther {
// массив правил валидации значений https://ant.design/components/form/#Rule
formItemRules?: Rule[]
// дефолтное значение при добавлении новой строки
initialValue?: string|number
initialValue?: string | number
render?: (...attributes: any) => any
}
@ -71,13 +71,13 @@ export const makeColumn = (title: string | ReactNode, key: string, other?: colum
})
export const makeColumnsPlanFact = (
title:string | ReactNode,
key:string | string[],
title: string | ReactNode,
key: string | string[],
columsOther?: any | any[],
gruopOther?: any
) => {
let keyPlanLocal = key
let keyFactLocal = key
let keyPlanLocal: string
let keyFactLocal: string
if (key instanceof Array) {
keyPlanLocal = key[0]
@ -87,29 +87,27 @@ export const makeColumnsPlanFact = (
keyFactLocal = key + 'Fact'
}
let columsOtherLoacl : any[2]
let columsOtherLocal : any[2]
if (columsOther instanceof Array)
columsOtherLoacl = [columsOther[0], columsOther[1]]
columsOtherLocal = [columsOther[0], columsOther[1]]
else
columsOtherLoacl = [columsOther, columsOther]
columsOtherLocal = [columsOther, columsOther]
return {
title: title,
...gruopOther,
children: [
makeColumn('план', keyPlanLocal, columsOtherLoacl[0]),
makeColumn('факт', keyFactLocal, columsOtherLoacl[1]),
makeColumn('план', keyPlanLocal, columsOtherLocal[0]),
makeColumn('факт', keyFactLocal, columsOtherLocal[1]),
]
}
}
export const makeFilterTextMatch = (key: string | number) => (filterValue: string | number, dataItem: any) =>
dataItem[key] === filterValue
export const makeFilterTextMatch = (key: string | number) => (
(filterValue: string | number, dataItem: any) => dataItem[key] === filterValue
)
export const makeGroupColumn = (title: string, children: object[]) => ({
title: title,
children: children,
})
export const makeGroupColumn = (title: string, children: object[]) => ({ title, children })
export const makeTextColumn = (
title: string,

View File

@ -1,123 +0,0 @@
import { Button, Modal, Select } from 'antd'
import React, { useEffect, useState } from 'react'
import { EditableTable, makeColumn } from '../../components/Table'
export const toHexString = (num, size) => '0x' + ('0'.repeat(size) + num.toString(16).toUpperCase()).slice(-size)
const bitCount = 32
const bitOptions = [...Array(bitCount).keys()].map((n) => ({
label: toHexString(1 << n, bitCount / 4),
value: n,
}))
const columns = [
makeColumn('Бит', 'bit', {
// initialValue: bitOptions[0]?.value ?? '--',
input: <Select options={bitOptions} />,
render: (value) => bitOptions.find(option => option?.value === value)?.label ?? '--',
width: 200,
editable: true,
formItemRules: [{
required: true,
message: 'Пожалуйста, выберите бит'
}],
}),
makeColumn('Описание', 'description', {
width: 400,
editable: true,
formItemRules: [{
required: true,
message: 'Пожалуйста, введите описание'
}],
}),
]
export const PermissionBits = React.memo(({ value, onChange }) => {
const [isModalVisible, setIsModalVisible] = useState(false)
const [bits, setBits] = useState([])
// const [columns, setColumns] = useState([])
useEffect(() => {
setBits(Object.entries(value ?? {}).map(([bit, description]) => ({ bit, description })))
}, [value])
// useEffect(() => {
// const options = bitOptions.filter((option) => !(bits?.length && bits.find((row) => row.bit === option.value)))
// const defaultValue = options?.[0]?.label ?? '--'
// setColumns([
// makeColumn('Бит', 'bit', {
// initialValue: options?.[0]?.value ?? 0,
// input: <Select options={options} />,
// render: (value) => bitOptions.find(option => option?.value === value)?.label ?? defaultValue,
// width: 200,
// editable: true,
// formItemRules: [{ required: true, message: 'Пожалуйста, выберите бит' }],
// }),
// makeColumn('Описание', 'description', {
// width: 400,
// editable: true,
// formItemRules: [{ required: true, message: 'Пожалуйста, введите описание' }],
// }),
// ])
// }, [bits])
const saveBits = () => {
const newValue = {}
bits.forEach(({bit, description}) => (newValue[bit] = description))
if(!onChange(newValue))
setIsModalVisible(false)
}
const addNewBit = (bit) => {
bit.key = Date.now()
setBits((prevBits) => [...(prevBits ?? []), bit])
}
const editBit = (bit) => {
if (!bit.key) return
const idx = bits.findIndex(v => v.key === bit.key)
if (idx < 0) return
setBits((prevBits) => {
prevBits[idx] = bit
return prevBits
})
}
const removeBit = (bit) => {
if (!bit.key) return
const idx = bits.findIndex(v => v.bit === bit.bit)
if (idx < 0) return
setBits((prevBits) => {
prevBits.splice(idx, 1)
return prevBits
})
}
return (
<>
<Button type={'link'} onClick={() => setIsModalVisible(true)}>Редактировать</Button>
<Modal
title={'Описание битов'}
centered
visible={isModalVisible}
width={750}
onCancel={() => setIsModalVisible(false)}
onOk={saveBits}
okText={'Сохранить'}
>
<EditableTable
size={'small'}
bordered
columns={columns}
dataSource={bits}
onRowAdd={addNewBit}
onRowEdit={editBit}
onRowDelete={removeBit}
/>
</Modal>
</>
)
})
export default PermissionBits

View File

@ -1,60 +0,0 @@
import { useEffect, useState } from 'react'
import { invokeWebApiWrapperAsync } from '../../components/factory'
import LoaderPortal from '../../components/LoaderPortal'
import { EditableTable, makeActionHandler, makeColumn } from '../../components/Table'
import { AdminPermissionInfoService } from '../../services/api'
import PermissionBits, { toHexString } from './PermissionBits'
export const PermissionController = () => {
const [permissions, setPermissions] = useState([])
const [showLoader, setShowLoader] = useState(false)
const columns = [
makeColumn('Название', 'name', { width: 200, editable: true }),
makeColumn('Описание', 'description', { width: 200, editable: true }),
makeColumn('Значения битов', 'bitDescription', {
width: 200,
editable: true,
input: <PermissionBits />, // TODO: Дописать колонку для описания битов права
render: (bits) => {
if (!bits) return '--'
const sum = Object.keys(bits).reduce((sum, key) => sum + (1 << parseInt(key)), 0)
return sum && toHexString(sum, 16)
},
})
]
const updateTable = () => invokeWebApiWrapperAsync(
async () => {
const permissions = await AdminPermissionInfoService.getAll()
setPermissions(permissions)
},
setShowLoader,
`Не удалось загрузить список прав`
)
useEffect(updateTable, [])
const handlerProps = {
service: AdminPermissionInfoService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
onComplete: updateTable
}
return (
<LoaderPortal show={showLoader}>
<EditableTable
size={'small'}
bordered
columns={columns}
dataSource={permissions}
onRowAdd={makeActionHandler('insert', handlerProps)}
onRowEdit={makeActionHandler('update', handlerProps)}
onRowDelete={makeActionHandler('delete', handlerProps)}
/>
</LoaderPortal>
)
}
export default PermissionController

View File

@ -0,0 +1,141 @@
import { Button, Modal } from 'antd'
import { useEffect, useState } from 'react'
import { AdminUserRoleService } from '../../services/api'
import LoaderPortal from '../../components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '../../components/factory'
import { EditableTable, makeActionHandler, makeColumn, makeSelectColumn } from '../../components/Table'
export const toHexString = (num, size) => '0x' + ('0'.repeat(size) + num.toString(16).toUpperCase()).slice(-size)
const columns = [
makeColumn('Имена прав', 'name', {
width: 400,
editable: true,
formItemRules: [{
required: true,
message: 'Пожалуйста, введите имя права'
}],
}),
]
export const RolePermissions = ({ value, onChange }) => {
const [isModalVisible, setIsModalVisible] = useState(false)
const [list, setList] = useState([])
const save = () => {
const newValue = list.map((value) => value.name)
if(!onChange(newValue))
setIsModalVisible(false)
}
const add = (permission) => {
permission.key = Date.now()
setList((prevList) => {
if (!prevList) prevList = []
prevList.push(permission)
return prevList
})
}
const edit = (permission) => {
if (!permission.key) return
const idx = list.findIndex(v => v.key === permission.key)
if (idx < 0) return
setList((prevList) => {
prevList[idx] = permission
return prevList
})
}
const remove = (permission) => {
if (!permission.key) return
const idx = list.findIndex(v => v.key === permission.key)
if (idx < 0) return
setList((prevList) => {
prevList.splice(idx, 1)
return prevList
})
}
return (
<>
<Button type={'link'} onClick={() => setIsModalVisible(true)}>Редактировать</Button>
<Modal
title={'Права доступа'}
centered
visible={isModalVisible}
width={750}
onCancel={() => setIsModalVisible(false)}
onOk={save}
okText={'Сохранить'}
>
<EditableTable
size={'small'}
bordered
columns={columns}
dataSource={list}
onRowAdd={add}
onRowEdit={edit}
onRowDelete={remove}
/>
</Modal>
</>
)
}
export const RoleController = () => {
const [roles, setRoles] = useState([])
const [showLoader, setShowLoader] = useState(false)
const [columns, setColumns] = useState([])
const updateTable = () => invokeWebApiWrapperAsync(
async () => {
const roles = await AdminUserRoleService.getAll()
setRoles(roles)
},
setShowLoader,
`Не удалось загрузить список прав`
)
useEffect(() => {
const options = roles?.map((r) => ({ value: r.id, label: r.caption })) ?? []
setColumns([
makeColumn('Название', 'caption', { width: 200, editable: true }),
makeSelectColumn('Роль-родитель', 'idParent', options, options[0], {
width: 200,
editable: true
}),
makeColumn('Права доступа', 'permissions', {
width: 200,
editable: true,
input: <RolePermissions />,
render: (permissions) => permissions?.join(', ') ?? '',
})
])
}, [roles])
useEffect(updateTable, [])
const handlerProps = {
service: AdminUserRoleService,
setLoader: setShowLoader,
errorMsg: `Не удалось выполнить операцию`,
onComplete: updateTable
}
return (
<LoaderPortal show={showLoader}>
<EditableTable
size={'small'}
bordered
columns={columns}
dataSource={roles}
onRowAdd={makeActionHandler('insert', handlerProps)}
onRowEdit={makeActionHandler('update', handlerProps)}
onRowDelete={makeActionHandler('delete', handlerProps)}
/>
</LoaderPortal>
)
}
export default RoleController

View File

@ -2,14 +2,13 @@ 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 { 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'))
const PermissionController = React.lazy(() => import('./PermissionController'))
const RoleController = React.lazy(() => import('./RoleController'))
export const AdminPanel = () => {
const { tab } = useParams()
@ -17,28 +16,24 @@ export const AdminPanel = () => {
return (
<Layout>
<Menu
mode={'horizontal'}
selectable={true}
selectedKeys={[tab]}
>
<PrivateMenuItem key={'deposit'} permissions={[[PermissionNames.admin.deposit, PermissionValue.Read]]}>
<Menu mode={'horizontal'} selectable={true} selectedKeys={[tab]}>
<PrivateMenuItem key={'deposit'} permission={'deposit_editor'}>
<Link to={`${rootPath}/deposit`}>Месторождения</Link>
</PrivateMenuItem>
<PrivateMenuItem key={'cluster'} permissions={[[PermissionNames.admin.cluster, PermissionValue.Read]]}>
<PrivateMenuItem key={'cluster'} permission={'cluster_editor'}>
<Link to={`${rootPath}/cluster`}>Кусты</Link>
</PrivateMenuItem>
<PrivateMenuItem key={'well'} permissions={[[PermissionNames.admin.well, PermissionValue.Read]]}>
<PrivateMenuItem key={'well'} permission={'well_editor'}>
<Link to={`${rootPath}/well`}>Скважины</Link>
</PrivateMenuItem>
<PrivateMenuItem key={'user'} permissions={[[PermissionNames.admin.user, PermissionValue.Read]]}>
<PrivateMenuItem key={'user'} permission={'user_editor'}>
<Link to={`${rootPath}/user`}>Пользователи</Link>
</PrivateMenuItem>
<PrivateMenuItem key={'company'} permissions={[[PermissionNames.admin.company, PermissionValue.Read]]}>
<PrivateMenuItem key={'company'} permission={'company_editor'}>
<Link to={`${rootPath}/company`}>Компании</Link>
</PrivateMenuItem>
<PrivateMenuItem key={'permission'} permissions={[[PermissionNames.admin.permissions, PermissionValue.Read]]}>
<Link to={`${rootPath}/permission`}>Права</Link>
<PrivateMenuItem key={'role'} permission={'role_editor'}>
<Link to={`${rootPath}/role`}>Права</Link>
</PrivateMenuItem>
</Menu>
@ -46,12 +41,12 @@ export const AdminPanel = () => {
<Layout.Content className={'site-layout-background'}>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<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} />
<PrivateRoute path={`${rootPath}/permission`} component={PermissionController} />
<PrivateRoute permission={'deposit_editor'} path={`${rootPath}/deposit`} component={DepositController} />
<PrivateRoute permission={'cluster_editor'} path={`${rootPath}/cluster`} component={ClusterController} />
<PrivateRoute permission={ 'well_editor'} path={`${rootPath}/well` } component={ WellController} />
<PrivateRoute permission={ 'user_editor'} path={`${rootPath}/user` } component={ UserController} />
<PrivateRoute permission={'company_editor'} path={`${rootPath}/company`} component={CompanyController} />
<PrivateRoute permission={ 'role_editor'} path={`${rootPath}/role` } component={ RoleController} />
<Route path={'/'}>
<Redirect to={`${rootPath}/deposit`}/>
</Route>

View File

@ -1,59 +1,50 @@
//import { Menu } from "antd";
import { FolderOutlined } from "@ant-design/icons";
import { Link, Route} from "react-router-dom";
import path from 'path'
import { FolderOutlined } from '@ant-design/icons'
import { Link, Route } from 'react-router-dom'
import { PrivateMenuItem } from '../../components/Private'
import { getUserRoles, isInRole } from "../../utils/PermissionService";
import DocumentsTemplate from './DocumentsTemplate'
import {PrivateMenuItem} from '../../components/Private'
export const documentCategories = [
{id:1, key:'fluidService', title:'Растворный сервис'/*, roles:['ff']*/},
{id:2, key:'cementing', title:'Цементирование'},
{id:3, key:'nnb', title:'ННБ'},
{id:4, key:'gti', title:'ГТИ'},
{id:5, key:'documentsForWell', title:'Документы по скважине'},
{id:6, key:'supervisor', title:'Супервайзер'},
{id:7, key:'master', title:'Мастер'},
{ id: 1, key: 'fluidService', title: 'Растворный сервис' },
{ id: 2, key: 'cementing', title: 'Цементирование' },
{ id: 3, key: 'nnb', title: 'ННБ' },
{ id: 4, key: 'gti', title: 'ГТИ' },
{ id: 5, key: 'documentsForWell', title: 'Документы по скважине' },
{ id: 6, key: 'supervisor', title: 'Супервайзер' },
{ id: 7, key: 'master', title: 'Мастер' },
]
const makeMenuItem = (keyValue, rootPath, title, other) => (
<PrivateMenuItem className="ant-menu-item"
key={`${keyValue}`}
{...other}>
<PrivateMenuItem className={'ant-menu-item'} key={`${keyValue}`} {...other}>
<Link to={{pathname: `${rootPath}/${keyValue}`}}>{title}</Link>
</PrivateMenuItem>)
</PrivateMenuItem>
)
const makeRouteItem = (keyValue, rootPath, other) => (
<Route
path={`${rootPath}/${keyValue}`}
key={`${keyValue}`}>
key={`${keyValue}`}
>
<DocumentsTemplate {...other}/>
</Route>)
</Route>
)
const formatRoutePath = (rootPath) =>{
let root = rootPath.endsWith('/')
? rootPath.slice(0,-1)
: rootPath
root = root.endsWith('/document')
? root
: `${root}/document`
return root
}
const getCategoriesByUserRole = (role) => documentCategories
.filter(cat => !cat.roles || cat.roles.includes('*') || cat.roles.includes(role))
const getCategoriesByUserRole = (role) => documentCategories.filter(cat => isInRole(cat.roles))
export const makeMenuItems = (rootPath) => {
const root = formatRoutePath(rootPath)
const categories = getCategoriesByUserRole(localStorage['roleName'])
const root = path.join(rootPath, '/document')
const categories = getCategoriesByUserRole(getUserRoles())
return categories.map(category =>
makeMenuItem(category.key, root, category.title, {icon:<FolderOutlined/>}))
}
export const makeRouteItems = (rootPath, idWell) => {
const root = formatRoutePath(rootPath)
const categories = getCategoriesByUserRole(localStorage['roleName'])
const routes = categories.map(category =>
makeRouteItem(category.key, root, {idCategory: category.id, idWell: idWell}))
return routes;
const root = path.join(rootPath, '/document')
const categories = getCategoriesByUserRole(getUserRoles())
const routes = categories.map(category => makeRouteItem(category.key, root, {
idCategory: category.id,
idWell: idWell
}))
return routes
}

View File

@ -0,0 +1,62 @@
import { getArrayFromLocalStorage } from './storage'
export type Role = string
export type Permission = string
export const getUserRoles = (): Role[] => getArrayFromLocalStorage<Role>('roles') ?? []
export const getUserPermissions = (): Permission[] =>
getArrayFromLocalStorage<Permission>('permissions') ?? []
export const hasPermission = (permission?: Permission): boolean => {
if (typeof permission !== 'string') return true
return permission in getUserPermissions()
}
export const isInRole = (roles?: Role[] | Role): boolean => {
if (typeof roles === 'string' && !Array.isArray(roles))
roles = [roles]
if (!roles?.length) return true
if (localStorage.getItem('login') === 'dev') return true // TODO: Удалить строку
const user_roles = getUserRoles()
return roles.some((role) => role in user_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)
*/

View File

@ -1,140 +0,0 @@
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)
*/

5
src/utils/storage.ts Normal file
View File

@ -0,0 +1,5 @@
export const getArrayFromLocalStorage = <T extends string = string>(name: string, sep: string | RegExp = ','): T[] | null => {
const raw = localStorage.getItem(name)
if (!raw) return null
return raw.split(sep).map<T>(elm => elm as T)
}