diff --git a/src/components/outlets/UserOutlet.tsx b/src/components/outlets/UserOutlet.tsx new file mode 100644 index 0000000..49a2859 --- /dev/null +++ b/src/components/outlets/UserOutlet.tsx @@ -0,0 +1,17 @@ +import { memo, useMemo } from 'react' +import { Outlet } from 'react-router-dom' + +import { UserContext } from '@asb/context' +import { getUser } from '@utils' + +export const UserOutlet = memo(() => { + const user = useMemo(() => getUser() ?? {}, []) + + return ( + + + + ) +}) + +export default UserOutlet diff --git a/src/components/outlets/index.ts b/src/components/outlets/index.ts new file mode 100644 index 0000000..77c9a70 --- /dev/null +++ b/src/components/outlets/index.ts @@ -0,0 +1 @@ +export * from './UserOutlet' diff --git a/src/context.ts b/src/context.ts index 22e62c1..4fddc4f 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,22 +1,31 @@ import { createContext, useContext } from 'react' -import { WellDto } from '@api' +import { UserTokenDto, WellDto } from '@api' /** Контекст текущей скважины */ export const WellContext = createContext<[WellDto, (well: WellDto) => void]>([{}, () => {}]) /** Контекст текущего корневого пути */ -export const RootPathContext = createContext('') +export const RootPathContext = createContext('/') +/** Контекст текущего пользователя */ +export const UserContext = createContext({}) /** - * Получение текущей скважины + * Получить текущую скважину * * @returns Текущая скважина, либо `null` */ export const useWell = () => useContext(WellContext) /** - * Получает текущий корневой путь + * Получить текущий корневой путь * * @returns Текущий корневой путь */ export const useRootPath = () => useContext(RootPathContext) + +/** + * Получить текущего пользователя + * + * @returns Текущий пользователь, либо `null` + */ +export const useUser = () => useContext(UserContext) diff --git a/src/utils/functions/permissions.tsx b/src/utils/functions/permissions.tsx index a8067b0..274a9c5 100644 --- a/src/utils/functions/permissions.tsx +++ b/src/utils/functions/permissions.tsx @@ -1,7 +1,7 @@ import { memo, NamedExoticComponent, ReactElement, ReactNode, useMemo } from 'react' import { Navigate, useParams } from 'react-router-dom' -import { getUserLogin, getUserPermissions, getUserRoles } from '@utils' +import { getUserLogin, getUserPermissions } from '@utils' import { isDev } from '@utils' import AccessDenied from '@pages/AccessDenied' @@ -31,22 +31,13 @@ export const getPermissions = (...values: PermissionRequest[]) => { export const hasPermission = (permission?: Permission | Permission[], userPermissions?: Permission[]): boolean => { if (!Array.isArray(permission) && typeof permission !== 'string') return true - const userPerms = userPermissions ?? getUserPermissions() + const userPerms = userPermissions ?? getUserPermissions() ?? [] if (typeof permission === 'string') permission = [permission] return permission.every((perm) => userPerms.includes(perm)) } -export const isInRole = (roles?: Role[] | Role): boolean => { - if (typeof roles === 'string' && !Array.isArray(roles)) - roles = [roles] - if (!roles?.length) return true - - const user_roles = getUserRoles() - return roles.some((role) => user_roles.includes(role)) -} - -const sectionAvailable = (section: PermissionRecord, userPermission: Permission[] = getUserPermissions()) => { +const sectionAvailable = (section: PermissionRecord, userPermission: Permission[]) => { for (const child of Object.values(section)) { if (!child) continue if (Array.isArray(child)) { @@ -81,7 +72,7 @@ export const isURLAvailable = (path: string, userPermissions?: Permission[]) => } if (!perms) return false - const userPerms: string[] = userPermissions ?? getUserPermissions() + const userPerms: string[] = userPermissions ?? getUserPermissions() ?? [] if (Array.isArray(perms)) { return perms.every((perm) => userPerms.includes(perm)) } diff --git a/src/utils/functions/storage.ts b/src/utils/functions/storage.ts index c4392f7..a95182a 100644 --- a/src/utils/functions/storage.ts +++ b/src/utils/functions/storage.ts @@ -1,7 +1,8 @@ import { OpenAPI, UserTokenDto } from '@api' +import { isDev } from '..' import { wrapValues } from './objects' -import { Role, Permission } from './permissions' +import { Permission } from './permissions' import { normalizeTableColumn, optimizeTableColumn, TableSettings, TableSettingsStore } from './table_settings' export enum StorageNames { @@ -10,6 +11,7 @@ export enum StorageNames { login = 'login', permissions = 'permissions', roles = 'roles', + user = 'user', tableSettings = 'tableSettings', dashboardNNB = 'dashboardNNB', witsInfo = 'witsInfo' @@ -22,11 +24,12 @@ export const getArrayFromLocalStorage = (name: string } export const getJSON = (name: StorageNames): T | null => { - const raw = localStorage.getItem(name) - if (!raw) return null try { - return JSON.parse(raw) - } catch {} + const raw = localStorage.getItem(name) + if (raw) return JSON.parse(raw) + } catch { + if (isDev()) console.warn(`Storage "${name}" parsing exception!`) + } return null } @@ -34,25 +37,28 @@ export const setJSON = (name: StorageNames, data: T | null): boolean => { try { localStorage.setItem(name, JSON.stringify(data)) return true - } catch {} + } catch { + if (isDev()) console.warn(`Storage "${name}" saving exception!`) + } return false } -export const getUserRoles = (): Role[] => getArrayFromLocalStorage(StorageNames.roles) ?? [] -export const getUserPermissions = (): Permission[] => getArrayFromLocalStorage(StorageNames.permissions) ?? [] +export const getUser = (): UserTokenDto | null => getJSON(StorageNames.user) + +export const getUserPermissions = (): Permission[] | null => getUser()?.permissions?.map((perm) => perm.name as string) || null 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.user, JSON.stringify(user)) + 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 = () => { @@ -60,7 +66,8 @@ export const removeUser = () => { localStorage.removeItem(StorageNames.login) localStorage.removeItem(StorageNames.token) localStorage.removeItem(StorageNames.permissions) - localStorage.removeItem(StorageNames.roles) + + localStorage.removeItem(StorageNames.user) } export const getTableSettings = (tableName: string): TableSettings => {