Yetki düzenlemesi, Access Denied ve NotFound
This commit is contained in:
parent
821806a8db
commit
e97d560761
13 changed files with 180 additions and 87 deletions
|
|
@ -2497,6 +2497,12 @@
|
|||
"en": "Access Failed Count",
|
||||
"tr": "Başarısız Erişim Sayısı"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "Abp.Identity.Ai",
|
||||
"en": "AI Assistant",
|
||||
"tr": "Yapay Zeka Asistanı"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "Abp.Identity.Profile",
|
||||
|
|
@ -6352,7 +6358,7 @@
|
|||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "Public.notFound.button",
|
||||
"tr": "Ana Sayfaya Dön",
|
||||
"tr": "Ana Sayfa'ya Dön",
|
||||
"en": "Return to Homepage"
|
||||
},
|
||||
{
|
||||
|
|
@ -10602,6 +10608,14 @@
|
|||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3
|
||||
},
|
||||
{
|
||||
"GroupName": "AbpIdentity",
|
||||
"Name": "Abp.Identity.Ai",
|
||||
"ParentName": null,
|
||||
"DisplayName": "Abp.Identity.Ai",
|
||||
"IsEnabled": true,
|
||||
"MultiTenancySide": 3
|
||||
},
|
||||
{
|
||||
"GroupName": "AbpIdentity",
|
||||
"Name": "Abp.Identity.PermissionGroups",
|
||||
|
|
@ -25519,14 +25533,14 @@
|
|||
"path": "/admin/menuManager",
|
||||
"componentPath": "@/views/menu/MenuManager",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.Menus.Manager"]
|
||||
},
|
||||
{
|
||||
"key": "admin.listFormManagement.wizard",
|
||||
"path": "/admin/listform/wizard",
|
||||
"componentPath": "@/views/admin/listForm/Wizard",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.Listforms.Wizard"]
|
||||
},
|
||||
{
|
||||
"key": "admin.listFormManagement.edit",
|
||||
|
|
@ -25547,14 +25561,14 @@
|
|||
"path": "/admin/forumManagement",
|
||||
"componentPath": "@/views/forum/Management",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.ForumManagement"]
|
||||
},
|
||||
{
|
||||
"key": "admin.ai",
|
||||
"path": "/admin/ai",
|
||||
"componentPath": "@/views/ai/Assistant",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["Abp.Identity.Ai"]
|
||||
},
|
||||
{
|
||||
"key": "admin.profile.general",
|
||||
|
|
@ -25596,28 +25610,28 @@
|
|||
"path": "/admin/settings",
|
||||
"componentPath": "@/views/settings/Settings",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.Setting"]
|
||||
},
|
||||
{
|
||||
"key": "admin.identity.user.detail",
|
||||
"path": "/admin/users/detail/:userId",
|
||||
"componentPath": "@/views/admin/user-management/Details",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["AbpIdentity.Users.Update"]
|
||||
},
|
||||
{
|
||||
"key": "admin.identity.ous",
|
||||
"path": "/admin/ous",
|
||||
"componentPath": "@/views/admin/organization-unit/OrganizationUnits",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["Abp.Identity.OrganizationUnits"]
|
||||
},
|
||||
{
|
||||
"key": "admin.forum",
|
||||
"path": "/admin/forum",
|
||||
"componentPath": "@/views/forum/Forum",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.ForumManagement.Publish"]
|
||||
},
|
||||
{
|
||||
"key": "admin.list",
|
||||
|
|
@ -25666,70 +25680,70 @@
|
|||
"path": "/admin/developerkit",
|
||||
"componentPath": "@/views/developerKit/DashboardPage",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.DeveloperKit"]
|
||||
},
|
||||
{
|
||||
"key": "admin.developerkit.entities",
|
||||
"path": "/admin/developerkit/entities",
|
||||
"componentPath": "@/views/developerKit/EntityPage",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.DeveloperKit.Entity"]
|
||||
},
|
||||
{
|
||||
"key": "admin.developerkit.entities.new",
|
||||
"path": "/admin/developerkit/entities/new",
|
||||
"componentPath": "@/views/developerKit/EntityDetailPage",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.DeveloperKit.Entity"]
|
||||
},
|
||||
{
|
||||
"key": "admin.developerkit.entities.edit",
|
||||
"path": "/admin/developerkit/entities/edit/:id",
|
||||
"componentPath": "@/views/developerKit/EntityDetailPage",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.DeveloperKit.Entity"]
|
||||
},
|
||||
{
|
||||
"key": "admin.developerkit.migrations",
|
||||
"path": "/admin/developerkit/migrations",
|
||||
"componentPath": "@/views/developerKit/MigrationPage",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.DeveloperKit.Migrations"]
|
||||
},
|
||||
{
|
||||
"key": "admin.developerkit.endpoints",
|
||||
"path": "/admin/developerkit/endpoints",
|
||||
"componentPath": "@/views/developerKit/EndpointPage",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.DeveloperKit.Endpoints"]
|
||||
},
|
||||
{
|
||||
"key": "admin.developerkit.components",
|
||||
"path": "/admin/developerkit/components",
|
||||
"componentPath": "@/views/developerKit/ComponentPage",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.DeveloperKit.Components"]
|
||||
},
|
||||
{
|
||||
"key": "admin.developerkit.components.new",
|
||||
"path": "/admin/developerkit/components/new",
|
||||
"componentPath": "@/views/developerKit/ComponentDetailPage",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.DeveloperKit.Components"]
|
||||
},
|
||||
{
|
||||
"key": "admin.developerkit.components.view",
|
||||
"path": "/admin/developerkit/components/view/:id",
|
||||
"componentPath": "@/views/developerKit/ComponentDetailPage",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.DeveloperKit.Components"]
|
||||
},
|
||||
{
|
||||
"key": "admin.developerkit.components.edit",
|
||||
"path": "/admin/developerkit/components/edit/:id",
|
||||
"componentPath": "@/views/developerKit/CodePage",
|
||||
"routeType": "protected",
|
||||
"authority": []
|
||||
"authority": ["App.DeveloperKit.Components" ]
|
||||
}
|
||||
],
|
||||
"CustomEndpoints": [
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
|
|||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||
}, {
|
||||
"url": "index.html",
|
||||
"revision": "0.0ii4qr2m5co"
|
||||
"revision": "0.rs1dfl4jqho"
|
||||
}], {});
|
||||
workbox.cleanupOutdatedCaches();
|
||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||
|
|
|
|||
|
|
@ -38,58 +38,58 @@ const PublicLayout = lazy(() => import('./PublicLayout'))
|
|||
|
||||
const Layout = () => {
|
||||
const location = useLocation()
|
||||
const layoutType = useStoreState((state) => state.theme.layout.type) as LayoutType
|
||||
const layoutType = useStoreState((s) => s.theme.layout.type) as LayoutType
|
||||
const { routes, loading } = useDynamicRoutes()
|
||||
const { authenticated } = useAuth()
|
||||
|
||||
useDirection() // Her zaman çağrılmalı
|
||||
useLocale() // Her zaman çağrılmalı
|
||||
useDirection()
|
||||
useLocale()
|
||||
|
||||
const currentPath = location.pathname
|
||||
const isAdminPath = currentPath.startsWith('/admin')
|
||||
|
||||
const route = useMemo(() => {
|
||||
if (!routes || routes.length === 0) return undefined
|
||||
|
||||
const matched = routes.find((route) => {
|
||||
if (!route.path.includes(':')) return route.path === currentPath
|
||||
|
||||
const regexPath = route.path.replace(/:[^/]+/g, '[^/]+')
|
||||
const regex = new RegExp(`^${regexPath}$`)
|
||||
return regex.test(currentPath)
|
||||
})
|
||||
|
||||
return matched
|
||||
}, [routes, currentPath])
|
||||
|
||||
const AppLayout = useMemo(() => {
|
||||
if (authenticated && route?.routeType === 'protected') {
|
||||
// 1) Admin path ise, route bulunmasa bile admin layout'u göster
|
||||
if (isAdminPath) {
|
||||
return layouts[layoutType]
|
||||
}
|
||||
|
||||
if (route?.routeType === 'authenticated' || hasSubdomain()) {
|
||||
return AuthLayout
|
||||
// 2) Admin değil ve route bulunamadı -> PublicLayout
|
||||
if (!route) {
|
||||
return PublicLayout
|
||||
}
|
||||
|
||||
// 3) Mevcut kurallar
|
||||
if (authenticated && route.routeType === 'protected') {
|
||||
return layouts[layoutType]
|
||||
}
|
||||
if (route.routeType === 'authenticated' || hasSubdomain()) {
|
||||
return AuthLayout
|
||||
}
|
||||
return PublicLayout
|
||||
}, [layoutType, authenticated, route])
|
||||
}, [isAdminPath, route, layoutType, authenticated])
|
||||
|
||||
// ❗ KOŞUL BURADA OLMALI: HOOK’LARDAN SONRA
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex flex-auto flex-col h-[100vh]">
|
||||
<Loading loading={true} />
|
||||
<Loading loading />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className="flex flex-auto flex-col h-[100vh]">
|
||||
<Loading loading={true} />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Suspense fallback={<div className="flex flex-auto flex-col h-[100vh]"><Loading loading /></div>}>
|
||||
<AppLayout />
|
||||
</Suspense>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// AuthorityGuard.tsx
|
||||
import { PropsWithChildren } from 'react'
|
||||
import { Navigate } from 'react-router-dom'
|
||||
import { Navigate, useLocation } from 'react-router-dom'
|
||||
import useAuthority from '@/utils/hooks/useAuthority'
|
||||
import { getAccessDeniedPath } from '@/utils/routing'
|
||||
|
||||
type AuthorityGuardProps = PropsWithChildren<{
|
||||
userAuthority?: string[]
|
||||
|
|
@ -9,10 +11,15 @@ type AuthorityGuardProps = PropsWithChildren<{
|
|||
|
||||
const AuthorityGuard = (props: AuthorityGuardProps) => {
|
||||
const { userAuthority = [], authority = [], children } = props
|
||||
|
||||
const roleMatched = useAuthority(userAuthority, authority)
|
||||
const location = useLocation()
|
||||
|
||||
return <>{roleMatched ? children : <Navigate to="/access-denied" />}</>
|
||||
if (!roleMatched) {
|
||||
const to = getAccessDeniedPath(location.pathname)
|
||||
return <Navigate to={to} replace state={{ from: location }} />
|
||||
}
|
||||
|
||||
return <>{children}</>
|
||||
}
|
||||
|
||||
export default AuthorityGuard
|
||||
|
|
|
|||
|
|
@ -1,18 +1,24 @@
|
|||
// PermissionGuard.tsx
|
||||
import { usePermission } from '@/utils/hooks/usePermission'
|
||||
import { PropsWithChildren } from 'react'
|
||||
import { Navigate } from 'react-router-dom'
|
||||
import { Navigate, useLocation } from 'react-router-dom'
|
||||
import { getAccessDeniedPath } from '@/utils/routing'
|
||||
|
||||
type PermissionGuardProps = PropsWithChildren<{
|
||||
permissions?: string[]
|
||||
}>
|
||||
|
||||
const PermissionGuard = (props: PermissionGuardProps) => {
|
||||
const { permissions = [], children } = props
|
||||
|
||||
const PermissionGuard = ({ permissions = [], children }: PermissionGuardProps) => {
|
||||
const { checkPermissions } = usePermission()
|
||||
const permissionsMatched = checkPermissions(permissions)
|
||||
const location = useLocation()
|
||||
|
||||
return <>{permissionsMatched ? children : <Navigate to="/access-denied" />}</>
|
||||
if (!permissionsMatched) {
|
||||
const to = getAccessDeniedPath(location.pathname)
|
||||
return <Navigate to={to} replace state={{ from: location }} />
|
||||
}
|
||||
|
||||
return <>{children}</>
|
||||
}
|
||||
|
||||
export default PermissionGuard
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import Tooltip from '@/components/ui/Tooltip'
|
||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { usePermission } from '@/utils/hooks/usePermission'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { FcAssistant } from 'react-icons/fc'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
|
@ -8,15 +9,17 @@ import { useNavigate } from 'react-router-dom'
|
|||
const AiAssistant = () => {
|
||||
const { translate } = useLocalization()
|
||||
const navigate = useNavigate()
|
||||
const { checkPermissions } = usePermission()
|
||||
|
||||
const canViewAi = checkPermissions(['Abp.Identity.Ai'])
|
||||
|
||||
if (!canViewAi) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet
|
||||
titleTemplate="%s | Kurs Platform"
|
||||
title={translate('::' + 'AI Assistant')}
|
||||
defaultTitle="Kurs Platform"
|
||||
></Helmet>
|
||||
<Tooltip title="AI Asistan">
|
||||
<Tooltip title={translate('::Abp.Identity.Ai')}>
|
||||
<div
|
||||
onClick={() => navigate(ROUTES_ENUM.protected.admin.ai)}
|
||||
className="flex items-center justify-center w-9 h-9 m-2 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer transition-colors duration-200"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React, { useMemo } from 'react'
|
||||
// DynamicRouter.tsx
|
||||
import React from 'react'
|
||||
import { Routes, Route, Navigate } from 'react-router-dom'
|
||||
import { mapDynamicRoutes, loadComponent } from './dynamicRouteLoader'
|
||||
import { useDynamicRoutes } from './dynamicRoutesContext'
|
||||
|
|
@ -8,17 +9,20 @@ import PageContainer from '@/components/template/PageContainer'
|
|||
import { ROUTES_ENUM } from './route.constant'
|
||||
import { hasSubdomain } from '@/utils/subdomain'
|
||||
|
||||
// AccessDenied ve NotFound'u dinamiklikten çıkarıyoruz
|
||||
const AccessDenied = React.lazy(() => import('@/views/AccessDenied'))
|
||||
const NotFound = React.lazy(() => import('@/views/NotFound'))
|
||||
|
||||
export const DynamicRouter: React.FC = () => {
|
||||
const { routes, loading, error } = useDynamicRoutes()
|
||||
|
||||
const dynamicRoutes = useMemo(() => mapDynamicRoutes(routes), [routes])
|
||||
const NotFoundComponent = useMemo(() => loadComponent('views/NotFound'), [])
|
||||
const dynamicRoutes = React.useMemo(() => mapDynamicRoutes(routes), [routes])
|
||||
|
||||
if (loading) return <div>Loading...</div>
|
||||
if (error) return <div>Hata: {error}</div>
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
{/* ADMIN */}
|
||||
<Route path="/admin/*" element={<ProtectedRoute />}>
|
||||
{dynamicRoutes
|
||||
.filter((r) => r.routeType === 'protected')
|
||||
|
|
@ -27,7 +31,7 @@ export const DynamicRouter: React.FC = () => {
|
|||
return (
|
||||
<Route
|
||||
key={route.key}
|
||||
path={route.path.replace(/^\/admin\/?/, '') || '.'} // Remove /admin prefix for nested routes
|
||||
path={route.path.replace(/^\/admin\/?/, '') || '.'}
|
||||
element={
|
||||
<PermissionGuard permissions={route.authority}>
|
||||
<PageContainer>
|
||||
|
|
@ -40,9 +44,36 @@ export const DynamicRouter: React.FC = () => {
|
|||
/>
|
||||
)
|
||||
})}
|
||||
|
||||
{/* admin default */}
|
||||
<Route index element={<Navigate to={ROUTES_ENUM.protected.dashboard} replace />} />
|
||||
|
||||
{/* admin access denied (statik) */}
|
||||
<Route
|
||||
path="access-denied"
|
||||
element={
|
||||
<PageContainer>
|
||||
<React.Suspense fallback={<div>Loading...</div>}>
|
||||
<AccessDenied />
|
||||
</React.Suspense>
|
||||
</PageContainer>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* admin not found (statik) */}
|
||||
<Route
|
||||
path="*"
|
||||
element={
|
||||
<PageContainer>
|
||||
<React.Suspense fallback={<div>Loading...</div>}>
|
||||
<NotFound />
|
||||
</React.Suspense>
|
||||
</PageContainer>
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
{/* Auth/Public dinamik rotalar */}
|
||||
{dynamicRoutes
|
||||
.filter((r) =>
|
||||
hasSubdomain() ? r.routeType === 'authenticated' : r.routeType !== 'protected',
|
||||
|
|
@ -62,6 +93,7 @@ export const DynamicRouter: React.FC = () => {
|
|||
)
|
||||
})}
|
||||
|
||||
{/* root redirect */}
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
|
|
@ -72,16 +104,23 @@ export const DynamicRouter: React.FC = () => {
|
|||
}
|
||||
/>
|
||||
|
||||
{/* public access denied (statik) */}
|
||||
<Route
|
||||
path="/access-denied"
|
||||
element={
|
||||
<React.Suspense fallback={<div>Loading...</div>}>
|
||||
<AccessDenied />
|
||||
</React.Suspense>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* public not found (statik) */}
|
||||
<Route
|
||||
path="*"
|
||||
element={
|
||||
hasSubdomain() ? (
|
||||
<Navigate to={ROUTES_ENUM.authenticated.login} replace />
|
||||
) : (
|
||||
<React.Suspense fallback={<div>Loading...</div>}>
|
||||
<NotFoundComponent />
|
||||
<NotFound />
|
||||
</React.Suspense>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export const ROUTES_ENUM = {
|
|||
demo: '/demo',
|
||||
blog: '/blog',
|
||||
contact: '/contact',
|
||||
accessDenied: '/access-denied',
|
||||
},
|
||||
authenticated: {
|
||||
login: '/login',
|
||||
|
|
@ -67,5 +68,6 @@ export const ROUTES_ENUM = {
|
|||
chart: '/admin/chart/:chartCode',
|
||||
pivot: '/admin/pivot/:listFormCode',
|
||||
},
|
||||
accessDenied: '/admin/access-denied',
|
||||
},
|
||||
}
|
||||
|
|
|
|||
5
ui/src/utils/routing.ts
Normal file
5
ui/src/utils/routing.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { ROUTES_ENUM } from "@/routes/route.constant";
|
||||
|
||||
// src/utils/routing.ts
|
||||
export const getAccessDeniedPath = (pathname: string) =>
|
||||
pathname.startsWith('/admin') ? ROUTES_ENUM.protected.accessDenied : ROUTES_ENUM.public.accessDenied
|
||||
|
|
@ -10,19 +10,27 @@ const AccessDenied = () => {
|
|||
const navigate = useNavigate()
|
||||
const { translate } = useLocalization()
|
||||
|
||||
const currentPath = location.pathname
|
||||
const isAdminPath = currentPath.startsWith('/admin')
|
||||
|
||||
return (
|
||||
<Container className="h-full">
|
||||
<div className="h-full flex flex-col items-center justify-center p-24">
|
||||
<div className="h-full flex flex-col items-center justify-center p-28">
|
||||
<DoubleSidedImage
|
||||
src="/img/others/img-2.png"
|
||||
darkModeSrc="/img/others/img-2-dark.png"
|
||||
alt={ translate('::AccessDenied')}
|
||||
alt={translate('::AccessDenied')}
|
||||
/>
|
||||
<div className="mt-6 text-center">
|
||||
<h3 className="mb-2">{ translate('::AccessDenied')}</h3>
|
||||
<p className="text-base">{ translate('::AccessDeniedMessage')}</p>
|
||||
<h3 className="mb-2">{translate('::AccessDenied')}</h3>
|
||||
<p className="text-base">{translate('::AccessDeniedMessage')}</p>
|
||||
</div>
|
||||
<Button size="xs" className="mt-2" variant="default" onClick={() => navigate(ROUTES_ENUM.protected.dashboard)}>
|
||||
<Button
|
||||
size="xs"
|
||||
className="mt-2"
|
||||
variant="default"
|
||||
onClick={() => navigate(isAdminPath ? ROUTES_ENUM.protected.dashboard : ROUTES_ENUM.public.home)}
|
||||
>
|
||||
<MdArrowBack />
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,25 +1,30 @@
|
|||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
const NotFoundPage = () => {
|
||||
const navigate = useNavigate()
|
||||
const { translate } = useLocalization()
|
||||
|
||||
const currentPath = location.pathname
|
||||
const isAdminPath = currentPath.startsWith('/admin')
|
||||
|
||||
return (
|
||||
<div className="p-20">
|
||||
<div className="p-28">
|
||||
<div className="flex items-center justify-center font-inter">
|
||||
<div className="text-[8rem] sm:text-[10rem] md:text-[12rem] font-bold bg-gradient-to-br from-primary to-secondary bg-clip-text animate-pulse">
|
||||
404
|
||||
</div>
|
||||
</div>
|
||||
<p className="flex items-center justify-center text-xl mb-6 text-gray-600">
|
||||
Aradığınız sayfa bulunamadı.
|
||||
{translate('::Public.notFound.message')}
|
||||
</p>
|
||||
<div className="flex items-center justify-center font-inter">
|
||||
<button
|
||||
onClick={() => navigate(ROUTES_ENUM.protected.dashboard)}
|
||||
onClick={() => navigate(isAdminPath ? ROUTES_ENUM.protected.dashboard : ROUTES_ENUM.public.home)}
|
||||
className="px-6 py-3 bg-primary rounded-xl shadow hover:bg-secondary transition"
|
||||
>
|
||||
Ana Sayfa'ya Dön
|
||||
{translate('::Public.notFound.button')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import DialogProvider from './shared/DialogContext'
|
|||
import DialogShowComponent from './shared/DialogContext/DialogShowComponent'
|
||||
import UiDialog from './shared/UiDialog'
|
||||
import { DynamicRouter } from '@/routes/dynamicRouter'
|
||||
import { getAccessDeniedPath } from '@/utils/routing'
|
||||
|
||||
interface ViewsProps {
|
||||
pageContainerType?: 'default' | 'gutterless' | 'contained'
|
||||
|
|
@ -48,7 +49,11 @@ const Views = (props: ViewsProps) => {
|
|||
</Alert>
|
||||
)}
|
||||
{errors?.some((e) => e.statusCode === '403' || e.statusCode === '401') && (
|
||||
<Navigate to="/access-denied" replace />
|
||||
<Navigate
|
||||
to={getAccessDeniedPath(location.pathname)}
|
||||
replace
|
||||
state={{ from: location }}
|
||||
/>
|
||||
)}
|
||||
{errors?.map((e) => (
|
||||
<UiDialog
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { GridColumnData } from '../list/GridColumnData'
|
|||
import { addCss, addJs } from '../list/Utils'
|
||||
import { PermissionResults, RowMode, SimpleItemWithColData } from './types'
|
||||
import { EditingFormItemDto, GridDto, PlatformEditorTypes } from '@/proxy/form/models'
|
||||
import { getAccessDeniedPath } from '@/utils/routing'
|
||||
|
||||
const useGridData = (props: {
|
||||
mode: RowMode
|
||||
|
|
@ -287,16 +288,14 @@ const useGridData = (props: {
|
|||
|
||||
// Auth check
|
||||
useEffect(() => {
|
||||
if (!permissionResults) {
|
||||
return
|
||||
}
|
||||
if (!permissionResults) return
|
||||
|
||||
if (
|
||||
(mode === 'new' && !permissionResults.c) ||
|
||||
(mode === 'edit' && !permissionResults.u) ||
|
||||
(mode === 'view' && !permissionResults.r)
|
||||
) {
|
||||
navigate('/access-denied')
|
||||
const noCreate = mode === 'new' && !permissionResults.c
|
||||
const noUpdate = mode === 'edit' && !permissionResults.u
|
||||
const noRead = mode === 'view' && !permissionResults.r
|
||||
|
||||
if (noCreate || noUpdate || noRead) {
|
||||
navigate(getAccessDeniedPath(location.pathname), { replace: true, state: { from: location } })
|
||||
}
|
||||
}, [permissionResults])
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue