forked from ddrilling/asb_cloud_front
Исправлены методы работы с правами и хранилищем
Добавлено описание сайта
This commit is contained in:
parent
37889cb6ce
commit
d27d3a1632
@ -7,7 +7,7 @@
|
|||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="Web site created using create-react-app"
|
content="онлайн мониторинг процесса бурения в реальном времени в офисе заказчика"
|
||||||
/>
|
/>
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
<title>АСБ Vision</title>
|
<title>АСБ Vision</title>
|
||||||
@ -17,3 +17,4 @@
|
|||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
ц
|
@ -12,7 +12,7 @@ import { OpenAPI } from './services/api'
|
|||||||
import { PrivateRoute } from './components/Private'
|
import { PrivateRoute } from './components/Private'
|
||||||
|
|
||||||
//OpenAPI.BASE = 'http://localhost:3000'
|
//OpenAPI.BASE = 'http://localhost:3000'
|
||||||
OpenAPI.TOKEN = localStorage['token']
|
OpenAPI.TOKEN = localStorage.getItem('token')
|
||||||
OpenAPI.HEADERS = {'Content-Type': 'application/json'}
|
OpenAPI.HEADERS = {'Content-Type': 'application/json'}
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
|
@ -8,6 +8,7 @@ import { passwordRules, createPasswordRules } from '../utils/validationRules'
|
|||||||
import LoaderPortal from './LoaderPortal'
|
import LoaderPortal from './LoaderPortal'
|
||||||
import { invokeWebApiWrapperAsync } from './factory'
|
import { invokeWebApiWrapperAsync } from './factory'
|
||||||
import { UserView } from './Views'
|
import { UserView } from './Views'
|
||||||
|
import { getUserId, getUserLogin } from '../utils/storage'
|
||||||
|
|
||||||
const formLayout: FormProps = { labelCol: { span: 11 }, wrapperCol: { span: 16 } }
|
const formLayout: FormProps = { labelCol: { span: 11 }, wrapperCol: { span: 16 } }
|
||||||
|
|
||||||
@ -38,11 +39,11 @@ export const ChangePassword = memo<ChangePasswordProps>(({ user, visible, onCanc
|
|||||||
|
|
||||||
const onFormFinish = () => invokeWebApiWrapperAsync(
|
const onFormFinish = () => invokeWebApiWrapperAsync(
|
||||||
async() => {
|
async() => {
|
||||||
await AuthService.changePassword(user?.id ?? localStorage['userId'], `"${password}"`)
|
await AuthService.changePassword(user?.id ?? getUserId() ?? -1, `"${password}"`)
|
||||||
onOk?.()
|
onOk?.()
|
||||||
},
|
},
|
||||||
setShowLoader,
|
setShowLoader,
|
||||||
`Не удалось сменить пароль пользователя ${localStorage['login']}`
|
`Не удалось сменить пароль пользователя ${getUserLogin()}`
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Role, Permission, hasPermission, isInRole } from '../../utils/PermissionService'
|
import { Role, Permission, hasPermission, isInRole } from '../../utils/permissions'
|
||||||
|
|
||||||
type PrivateContentProps = {
|
type PrivateContentProps = {
|
||||||
roles?: Role[] | Role
|
roles?: Role[] | Role
|
||||||
@ -8,4 +8,4 @@ type PrivateContentProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PrivateContent: React.FC<PrivateContentProps> = ({ permission, roles, children = null }) =>
|
export const PrivateContent: React.FC<PrivateContentProps> = ({ permission, roles, children = null }) =>
|
||||||
hasPermission(permission) || isInRole(roles) ? children : null
|
hasPermission(permission) && isInRole(roles) ? children : null
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Menu } from 'antd'
|
import { Menu } from 'antd'
|
||||||
import { Role, Permission, hasPermission, isInRole } from '../../utils/PermissionService'
|
import { Role, Permission, hasPermission, isInRole } from '../../utils/permissions'
|
||||||
|
|
||||||
|
|
||||||
type PrivateMenuItemProps = {
|
type PrivateMenuItemProps = {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { StaticContext } from 'react-router'
|
import { StaticContext } from 'react-router'
|
||||||
import { Route, Redirect, RouteComponentProps } from 'react-router-dom'
|
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 = {
|
type PrivateRouteProps = {
|
||||||
roles: Role[] | Role
|
roles: Role[] | Role
|
||||||
@ -12,7 +13,7 @@ type PrivateRouteProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PrivateRoute: React.FC<PrivateRouteProps> = ({ permission, roles, component, children, ...other }) => {
|
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 (
|
return (
|
||||||
<Route {...other}
|
<Route {...other}
|
||||||
|
@ -18,7 +18,6 @@ export const EditableCell = ({
|
|||||||
dataIndex,
|
dataIndex,
|
||||||
input,
|
input,
|
||||||
isRequired,
|
isRequired,
|
||||||
title,
|
|
||||||
formItemClass,
|
formItemClass,
|
||||||
formItemRules,
|
formItemRules,
|
||||||
children,
|
children,
|
||||||
|
@ -3,14 +3,11 @@ import { Link, useHistory } from 'react-router-dom'
|
|||||||
import { Button, Dropdown, Menu } from 'antd'
|
import { Button, Dropdown, Menu } from 'antd'
|
||||||
import { UserOutlined } from '@ant-design/icons'
|
import { UserOutlined } from '@ant-design/icons'
|
||||||
|
|
||||||
|
import { getUserLogin, removeUser } from '../utils/storage'
|
||||||
|
|
||||||
import { PrivateMenuItem } from './Private'
|
import { PrivateMenuItem } from './Private'
|
||||||
import { ChangePassword } from './ChangePassword'
|
import { ChangePassword } from './ChangePassword'
|
||||||
|
|
||||||
const handleLogout = () => {
|
|
||||||
localStorage.removeItem('login')
|
|
||||||
localStorage.removeItem('token')
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserMenuProps = {
|
type UserMenuProps = {
|
||||||
isAdmin?: boolean
|
isAdmin?: boolean
|
||||||
}
|
}
|
||||||
@ -36,7 +33,7 @@ export const UserMenu: React.FC<UserMenuProps> = ({ isAdmin }) => {
|
|||||||
placement={'bottomRight'}
|
placement={'bottomRight'}
|
||||||
overlay={(
|
overlay={(
|
||||||
<Menu style={{ textAlign: 'right' }}>
|
<Menu style={{ textAlign: 'right' }}>
|
||||||
<PrivateMenuItem roles={'admin'}>
|
<PrivateMenuItem permission={'admin_panel'}>
|
||||||
{isAdmin ? (
|
{isAdmin ? (
|
||||||
<Link to={'/'}>Вернуться на сайт</Link>
|
<Link to={'/'}>Вернуться на сайт</Link>
|
||||||
) : (
|
) : (
|
||||||
@ -47,12 +44,12 @@ export const UserMenu: React.FC<UserMenuProps> = ({ isAdmin }) => {
|
|||||||
<Link to={'/'} onClick={onChangePasswordClick}>Сменить пароль</Link>
|
<Link to={'/'} onClick={onChangePasswordClick}>Сменить пароль</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item>
|
<Menu.Item>
|
||||||
<Link to={'/login'} onClick={handleLogout}>Выход</Link>
|
<Link to={'/login'} onClick={removeUser}>Выход</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</Menu>
|
</Menu>
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Button icon={<UserOutlined/>}>{localStorage['login']}</Button>
|
<Button icon={<UserOutlined/>}>{getUserLogin()}</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<ChangePassword
|
<ChangePassword
|
||||||
visible={isModalVisible}
|
visible={isModalVisible}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { notification } from 'antd'
|
import { notification } from 'antd'
|
||||||
import { Dispatch, SetStateAction } from 'react'
|
import { Dispatch, SetStateAction } from 'react'
|
||||||
import { FileInfoDto } from '../services/api'
|
import { FileInfoDto } from '../services/api'
|
||||||
|
import { getUserToken } from '../utils/storage'
|
||||||
|
|
||||||
const notificationTypeDictionary = new Map([
|
const notificationTypeDictionary = new Map([
|
||||||
['error' , { notifyInstance: notification.error , caption: 'Ошибка' }],
|
['error' , { notifyInstance: notification.error , caption: 'Ошибка' }],
|
||||||
@ -55,7 +56,7 @@ export const invokeWebApiWrapperAsync = async (
|
|||||||
export const download = async (url: string, fileName?: string) => {
|
export const download = async (url: string, fileName?: string) => {
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${localStorage['token']}`
|
Authorization: `Bearer ${getUserToken()}`
|
||||||
},
|
},
|
||||||
method: 'Get'
|
method: 'Get'
|
||||||
})
|
})
|
||||||
@ -83,7 +84,7 @@ export const download = async (url: string, fileName?: string) => {
|
|||||||
export const upload = async (url: string, formData: FormData) => {
|
export const upload = async (url: string, formData: FormData) => {
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${localStorage['token']}`
|
Authorization: `Bearer ${getUserToken()}`
|
||||||
},
|
},
|
||||||
method: 'Post',
|
method: 'Post',
|
||||||
body: formData,
|
body: formData,
|
||||||
|
@ -59,7 +59,7 @@ export const AdminPanel = () => {
|
|||||||
<PrivateRoute permission={'permission_editor'} path={`${rootPath}/permission`} component={PermissionController} />
|
<PrivateRoute permission={'permission_editor'} path={`${rootPath}/permission`} component={PermissionController} />
|
||||||
<PrivateRoute path={`${rootPath}/visit_log`} component={VisitLog} />
|
<PrivateRoute path={`${rootPath}/visit_log`} component={VisitLog} />
|
||||||
<Route path={'/'}>
|
<Route path={'/'}>
|
||||||
<Redirect to={`${rootPath}/deposit`}/>
|
<Redirect to={`${rootPath}/visit_log`}/>
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
@ -4,7 +4,7 @@ import { Layout, Menu } from 'antd'
|
|||||||
import { FolderOutlined } from '@ant-design/icons'
|
import { FolderOutlined } from '@ant-design/icons'
|
||||||
import { Switch, useParams, Link, Route } from 'react-router-dom'
|
import { Switch, useParams, Link, Route } from 'react-router-dom'
|
||||||
import { PrivateMenuItem } from '../../components/Private'
|
import { PrivateMenuItem } from '../../components/Private'
|
||||||
import { isInRole } from '../../utils/PermissionService'
|
import { isInRole } from '../../utils/permissions'
|
||||||
import DocumentsTemplate from './DocumentsTemplate'
|
import DocumentsTemplate from './DocumentsTemplate'
|
||||||
|
|
||||||
const { Content } = Layout
|
const { Content } = Layout
|
||||||
|
@ -2,23 +2,18 @@ import { Card, Form, Input, Button } from 'antd'
|
|||||||
import { UserOutlined, LockOutlined } from '@ant-design/icons'
|
import { UserOutlined, LockOutlined } from '@ant-design/icons'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { Link, useHistory } from 'react-router-dom'
|
import { Link, useHistory } from 'react-router-dom'
|
||||||
import { AuthService, OpenAPI } from '../services/api/'
|
|
||||||
|
import { AuthService } from '../services/api/'
|
||||||
import LoaderPortal from '../components/LoaderPortal'
|
import LoaderPortal from '../components/LoaderPortal'
|
||||||
import { invokeWebApiWrapperAsync } from '../components/factory'
|
import { invokeWebApiWrapperAsync } from '../components/factory'
|
||||||
import { loginRules, passwordRules } from '../utils/validationRules'
|
import { loginRules, passwordRules } from '../utils/validationRules'
|
||||||
|
import { setUser } from '../utils/storage'
|
||||||
|
|
||||||
import '../styles/index.css'
|
import '../styles/index.css'
|
||||||
import logo from '../images/logo_32.png'
|
import logo from '../images/logo_32.png'
|
||||||
|
|
||||||
const logoIcon = <img src={logo} alt={'АСБ'} className={'logo'} width={130}/>
|
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() {
|
export default function Login() {
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
const [showLoader, setShowLoader] = useState(false)
|
const [showLoader, setShowLoader] = useState(false)
|
||||||
|
@ -8,7 +8,7 @@ import AdminPanel from './AdminPanel'
|
|||||||
|
|
||||||
export const Main = () => (
|
export const Main = () => (
|
||||||
<Switch>
|
<Switch>
|
||||||
<PrivateRoute path={'/admin/:tab?'} roles={['admin']}>
|
<PrivateRoute path={'/admin/:tab?'} permission={'admin_panel'}>
|
||||||
<AdminLayoutPortal title={'Администраторская панель'}>
|
<AdminLayoutPortal title={'Администраторская панель'}>
|
||||||
<AdminPanel />
|
<AdminPanel />
|
||||||
</AdminLayoutPortal>
|
</AdminLayoutPortal>
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
import { getArrayFromLocalStorage } from './storage'
|
import { getUserPermissions, getUserRoles } from './storage'
|
||||||
|
|
||||||
export type Role = string
|
export type Role = string
|
||||||
export type Permission = 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 => {
|
export const hasPermission = (permission?: Permission): boolean => {
|
||||||
if (typeof permission !== 'string') return true
|
if (typeof permission !== 'string') return true
|
||||||
|
|
||||||
if (localStorage.getItem('login') === 'dev') return true // TODO: Удалить строку
|
return getUserPermissions().includes(permission)
|
||||||
|
|
||||||
return permission in getUserPermissions()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isInRole = (roles?: Role[] | Role): boolean => {
|
export const isInRole = (roles?: Role[] | Role): boolean => {
|
||||||
@ -20,8 +14,6 @@ export const isInRole = (roles?: Role[] | Role): boolean => {
|
|||||||
roles = [roles]
|
roles = [roles]
|
||||||
if (!roles?.length) return true
|
if (!roles?.length) return true
|
||||||
|
|
||||||
if (localStorage.getItem('login') === 'dev') return true // TODO: Удалить строку
|
|
||||||
|
|
||||||
const user_roles = getUserRoles()
|
const user_roles = getUserRoles()
|
||||||
return roles.some((role) => role in user_roles)
|
return roles.some((role) => role in user_roles)
|
||||||
}
|
}
|
@ -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 => {
|
export const getArrayFromLocalStorage = <T extends string = string>(name: string, sep: string | RegExp = ','): T[] | null => {
|
||||||
const raw = localStorage.getItem(name)
|
const raw = localStorage.getItem(name)
|
||||||
if (!raw) return null
|
if (!raw) return null
|
||||||
return raw.split(sep).map<T>(elm => elm as T)
|
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)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user