Исправлены методы работы с правами и хранилищем

Добавлено описание сайта
This commit is contained in:
Александр Сироткин 2021-12-29 17:48:10 +05:00
parent 37889cb6ce
commit d27d3a1632
15 changed files with 64 additions and 41 deletions

View File

@ -7,7 +7,7 @@
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
content="онлайн мониторинг процесса бурения в реальном времени в офисе заказчика"
/>
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>АСБ Vision</title>
@ -17,3 +17,4 @@
<div id="root"></div>
</body>
</html>
ц

View File

@ -12,7 +12,7 @@ import { OpenAPI } from './services/api'
import { PrivateRoute } from './components/Private'
//OpenAPI.BASE = 'http://localhost:3000'
OpenAPI.TOKEN = localStorage['token']
OpenAPI.TOKEN = localStorage.getItem('token')
OpenAPI.HEADERS = {'Content-Type': 'application/json'}
export default function App() {

View File

@ -8,6 +8,7 @@ import { passwordRules, createPasswordRules } from '../utils/validationRules'
import LoaderPortal from './LoaderPortal'
import { invokeWebApiWrapperAsync } from './factory'
import { UserView } from './Views'
import { getUserId, getUserLogin } from '../utils/storage'
const formLayout: FormProps = { labelCol: { span: 11 }, wrapperCol: { span: 16 } }
@ -38,11 +39,11 @@ export const ChangePassword = memo<ChangePasswordProps>(({ user, visible, onCanc
const onFormFinish = () => invokeWebApiWrapperAsync(
async() => {
await AuthService.changePassword(user?.id ?? localStorage['userId'], `"${password}"`)
await AuthService.changePassword(user?.id ?? getUserId() ?? -1, `"${password}"`)
onOk?.()
},
setShowLoader,
`Не удалось сменить пароль пользователя ${localStorage['login']}`
`Не удалось сменить пароль пользователя ${getUserLogin()}`
)
return (

View File

@ -1,5 +1,5 @@
import React from 'react'
import { Role, Permission, hasPermission, isInRole } from '../../utils/PermissionService'
import { Role, Permission, hasPermission, isInRole } from '../../utils/permissions'
type PrivateContentProps = {
roles?: Role[] | Role
@ -8,4 +8,4 @@ type PrivateContentProps = {
}
export const PrivateContent: React.FC<PrivateContentProps> = ({ permission, roles, children = null }) =>
hasPermission(permission) || isInRole(roles) ? children : null
hasPermission(permission) && isInRole(roles) ? children : null

View File

@ -1,6 +1,6 @@
import React from 'react'
import { Menu } from 'antd'
import { Role, Permission, hasPermission, isInRole } from '../../utils/PermissionService'
import { Role, Permission, hasPermission, isInRole } from '../../utils/permissions'
type PrivateMenuItemProps = {

View File

@ -1,7 +1,8 @@
import React from 'react'
import { StaticContext } from 'react-router'
import { Route, Redirect, RouteComponentProps } from 'react-router-dom'
import { Role, Permission, hasPermission, isInRole } from '../../utils/PermissionService'
import { Role, Permission, hasPermission, isInRole } from '../../utils/permissions'
import { getUserToken } from '../../utils/storage'
type PrivateRouteProps = {
roles: Role[] | Role
@ -12,7 +13,7 @@ type PrivateRouteProps = {
}
export const PrivateRoute: React.FC<PrivateRouteProps> = ({ permission, roles, component, children, ...other }) => {
const available = localStorage.getItem('token') && (hasPermission(permission) || isInRole(roles))
const available = getUserToken() && (hasPermission(permission) && isInRole(roles))
return (
<Route {...other}

View File

@ -18,7 +18,6 @@ export const EditableCell = ({
dataIndex,
input,
isRequired,
title,
formItemClass,
formItemRules,
children,

View File

@ -3,14 +3,11 @@ import { Link, useHistory } from 'react-router-dom'
import { Button, Dropdown, Menu } from 'antd'
import { UserOutlined } from '@ant-design/icons'
import { getUserLogin, removeUser } from '../utils/storage'
import { PrivateMenuItem } from './Private'
import { ChangePassword } from './ChangePassword'
const handleLogout = () => {
localStorage.removeItem('login')
localStorage.removeItem('token')
}
type UserMenuProps = {
isAdmin?: boolean
}
@ -36,7 +33,7 @@ export const UserMenu: React.FC<UserMenuProps> = ({ isAdmin }) => {
placement={'bottomRight'}
overlay={(
<Menu style={{ textAlign: 'right' }}>
<PrivateMenuItem roles={'admin'}>
<PrivateMenuItem permission={'admin_panel'}>
{isAdmin ? (
<Link to={'/'}>Вернуться на сайт</Link>
) : (
@ -47,12 +44,12 @@ export const UserMenu: React.FC<UserMenuProps> = ({ isAdmin }) => {
<Link to={'/'} onClick={onChangePasswordClick}>Сменить пароль</Link>
</Menu.Item>
<Menu.Item>
<Link to={'/login'} onClick={handleLogout}>Выход</Link>
<Link to={'/login'} onClick={removeUser}>Выход</Link>
</Menu.Item>
</Menu>
)}
>
<Button icon={<UserOutlined/>}>{localStorage['login']}</Button>
<Button icon={<UserOutlined/>}>{getUserLogin()}</Button>
</Dropdown>
<ChangePassword
visible={isModalVisible}

View File

@ -1,6 +1,7 @@
import { notification } from 'antd'
import { Dispatch, SetStateAction } from 'react'
import { FileInfoDto } from '../services/api'
import { getUserToken } from '../utils/storage'
const notificationTypeDictionary = new Map([
['error' , { notifyInstance: notification.error , caption: 'Ошибка' }],
@ -55,7 +56,7 @@ export const invokeWebApiWrapperAsync = async (
export const download = async (url: string, fileName?: string) => {
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${localStorage['token']}`
Authorization: `Bearer ${getUserToken()}`
},
method: 'Get'
})
@ -83,7 +84,7 @@ export const download = async (url: string, fileName?: string) => {
export const upload = async (url: string, formData: FormData) => {
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${localStorage['token']}`
Authorization: `Bearer ${getUserToken()}`
},
method: 'Post',
body: formData,

View File

@ -59,7 +59,7 @@ export const AdminPanel = () => {
<PrivateRoute permission={'permission_editor'} path={`${rootPath}/permission`} component={PermissionController} />
<PrivateRoute path={`${rootPath}/visit_log`} component={VisitLog} />
<Route path={'/'}>
<Redirect to={`${rootPath}/deposit`}/>
<Redirect to={`${rootPath}/visit_log`}/>
</Route>
</Switch>
</Suspense>

View File

@ -4,7 +4,7 @@ import { Layout, Menu } from 'antd'
import { FolderOutlined } from '@ant-design/icons'
import { Switch, useParams, Link, Route } from 'react-router-dom'
import { PrivateMenuItem } from '../../components/Private'
import { isInRole } from '../../utils/PermissionService'
import { isInRole } from '../../utils/permissions'
import DocumentsTemplate from './DocumentsTemplate'
const { Content } = Layout

View File

@ -2,23 +2,18 @@ import { Card, Form, Input, Button } from 'antd'
import { UserOutlined, LockOutlined } from '@ant-design/icons'
import { useState } from 'react'
import { Link, useHistory } from 'react-router-dom'
import { AuthService, OpenAPI } from '../services/api/'
import { AuthService } from '../services/api/'
import LoaderPortal from '../components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '../components/factory'
import { loginRules, passwordRules } from '../utils/validationRules'
import { setUser } from '../utils/storage'
import '../styles/index.css'
import logo from '../images/logo_32.png'
const logoIcon = <img src={logo} alt={'АСБ'} className={'logo'} width={130}/>
const setUser = (user) => {
OpenAPI.TOKEN = user.token
localStorage['userId'] = user.id
localStorage['token'] = user.token
localStorage['login'] = user.login
}
export default function Login() {
const history = useHistory()
const [showLoader, setShowLoader] = useState(false)

View File

@ -8,7 +8,7 @@ import AdminPanel from './AdminPanel'
export const Main = () => (
<Switch>
<PrivateRoute path={'/admin/:tab?'} roles={['admin']}>
<PrivateRoute path={'/admin/:tab?'} permission={'admin_panel'}>
<AdminLayoutPortal title={'Администраторская панель'}>
<AdminPanel />
</AdminLayoutPortal>

View File

@ -1,18 +1,12 @@
import { getArrayFromLocalStorage } from './storage'
import { getUserPermissions, getUserRoles } 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
if (localStorage.getItem('login') === 'dev') return true // TODO: Удалить строку
return permission in getUserPermissions()
return getUserPermissions().includes(permission)
}
export const isInRole = (roles?: Role[] | Role): boolean => {
@ -20,8 +14,6 @@ export const isInRole = (roles?: Role[] | Role): boolean => {
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)
}

View File

@ -1,5 +1,41 @@
import { OpenAPI, UserTokenDto } from '../services/api'
import { Role, Permission } from './permissions'
export enum StorageNames {
userId = 'userId',
token = 'token',
login = 'login',
permissions = 'permissions',
roles = 'roles',
}
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)
}
export const getUserRoles = (): Role[] => getArrayFromLocalStorage<Role>(StorageNames.roles) ?? []
export const getUserPermissions = (): Permission[] => getArrayFromLocalStorage<Permission>(StorageNames.permissions) ?? []
export const getUserId = () => Number(localStorage.getItem(StorageNames.userId)) || null
export const getUserLogin = () => localStorage.getItem(StorageNames.login)
export const getUserToken = () => localStorage.getItem(StorageNames.token)
export const setUser = (user: UserTokenDto) => {
OpenAPI.TOKEN = user.token ?? undefined
localStorage.setItem(StorageNames.userId, String(user.id))
localStorage.setItem(StorageNames.token, String(user.token))
localStorage.setItem(StorageNames.login, String(user.login))
if (user.permissions)
localStorage.setItem(StorageNames.permissions, user.permissions.map((permission) => permission.name).join(','))
if (user.roleNames)
localStorage.setItem(StorageNames.roles, user.roleNames.join(','))
}
export const removeUser = () => {
localStorage.removeItem(StorageNames.userId)
localStorage.removeItem(StorageNames.login)
localStorage.removeItem(StorageNames.token)
localStorage.removeItem(StorageNames.permissions)
localStorage.removeItem(StorageNames.roles)
}