Merge branch 'fix/sidebar-admin-nav-internal-only' into 'main'
fix(sidebar): hide outbox/audit/webhooks для PUBLIC users See merge request 2-6/2-6-4/terravault/ordinis!221
This commit is contained in:
@@ -63,6 +63,13 @@ type NavItem = {
|
||||
* (или {@code ordinis:admin} super-role). Hide если нет.
|
||||
*/
|
||||
reviewerOnly?: boolean
|
||||
/**
|
||||
* Admin-only nav entries (outbox/audit/webhooks). Backend возвращает 403
|
||||
* audit_internal_required / outbox_internal_required для PUBLIC-scope users.
|
||||
* Frontend hide'ит вместо показа links → 403 toast (confusing UX).
|
||||
* Hide когда {@link useHasInternalScope} returns false.
|
||||
*/
|
||||
internalOnly?: boolean
|
||||
}
|
||||
|
||||
export function Sidebar() {
|
||||
@@ -138,6 +145,7 @@ export function Sidebar() {
|
||||
icon: Inbox,
|
||||
badge: outboxPending > 0 ? outboxPending : undefined,
|
||||
authRequired: true,
|
||||
internalOnly: true,
|
||||
},
|
||||
{
|
||||
to: '/webhooks',
|
||||
@@ -145,8 +153,13 @@ export function Sidebar() {
|
||||
icon: Webhook,
|
||||
badge: webhooksActive > 0 ? webhooksActive : undefined,
|
||||
authRequired: true,
|
||||
internalOnly: true,
|
||||
},
|
||||
{ to: '/audit', label: t('nav.audit'), icon: ScrollText, authRequired: true },
|
||||
// /audit, /outbox, /webhooks — admin observability tools. Backend
|
||||
// возвращает 403 (audit_internal_required / outbox_internal_required)
|
||||
// для PUBLIC-scope users. UI больше не показывает links — раньше
|
||||
// PUBLIC users видели nav entries и кликали → 403 toast (confusing).
|
||||
{ to: '/audit', label: t('nav.audit'), icon: ScrollText, authRequired: true, internalOnly: true },
|
||||
{ to: '/search', label: t('nav.search'), icon: Search },
|
||||
],
|
||||
},
|
||||
@@ -158,6 +171,7 @@ export function Sidebar() {
|
||||
items: s.items.filter((i) => {
|
||||
if (i.authRequired && !canMutate) return false
|
||||
if (i.reviewerOnly && !isReviewer) return false
|
||||
if (i.internalOnly && !hasInternal) return false
|
||||
return true
|
||||
}),
|
||||
}))
|
||||
@@ -502,6 +516,7 @@ export function MobileSidebar({ open, onClose }: { open: boolean; onClose: () =>
|
||||
icon: Inbox,
|
||||
badge: outboxPending > 0 ? outboxPending : undefined,
|
||||
authRequired: true,
|
||||
internalOnly: true,
|
||||
},
|
||||
{
|
||||
to: '/webhooks',
|
||||
@@ -509,8 +524,9 @@ export function MobileSidebar({ open, onClose }: { open: boolean; onClose: () =>
|
||||
icon: Webhook,
|
||||
badge: webhooksActive > 0 ? webhooksActive : undefined,
|
||||
authRequired: true,
|
||||
internalOnly: true,
|
||||
},
|
||||
{ to: '/audit', label: t('nav.audit'), icon: ScrollText, authRequired: true },
|
||||
{ to: '/audit', label: t('nav.audit'), icon: ScrollText, authRequired: true, internalOnly: true },
|
||||
{ to: '/search', label: t('nav.search'), icon: Search },
|
||||
],
|
||||
},
|
||||
@@ -521,6 +537,7 @@ export function MobileSidebar({ open, onClose }: { open: boolean; onClose: () =>
|
||||
items: s.items.filter((i) => {
|
||||
if (i.authRequired && !canMutate) return false
|
||||
if (i.reviewerOnly && !isReviewer) return false
|
||||
if (i.internalOnly && !hasInternal) return false
|
||||
return true
|
||||
}),
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user