fix(rbac): Viewer-Rolle in Detail-Pages + ActionButtons — Edit ebenfalls sperren

- ActionButtons: Edit-Button wird für Viewer wie Delete gesperrt (Tooltip zeigt Reason)
- Domains/Detail: isViewer-Flag an alle Sub-Panels weitergegeben; Save-, TLS-Cert-,
  Routing-Rules- und Headers-Buttons für Viewer disabled
- Backends/Detail: Save-Button + ServerPanel Add-Button für Viewer disabled
- i18n: domains.backendUp/backendDown Keys (waren noch hardkodiert)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-24 13:10:29 +02:00
parent 9708e4441b
commit 2d027b3044
9 changed files with 133 additions and 86 deletions

View File

@@ -9,9 +9,9 @@ import { useAuthStore } from '../stores/auth'
//
// Either prop may be omitted to suppress that button — useful for
// rows that aren't editable (e.g. builtin services).
// Viewer-role accounts automatically get delete disabled — mutations
// are blocked at the API level too, but hiding the button avoids
// confusing "access denied" errors for read-only users.
// Viewer-role accounts get both buttons disabled — mutations are
// blocked at the API level too, but disabling here avoids confusing
// "access denied" errors for read-only users.
interface ActionButtonsProps {
onEdit?: () => void
onDelete?: () => void
@@ -35,20 +35,23 @@ export default function ActionButtons({
const role = useAuthStore((s) => s.user?.role)
const isViewer = role === 'viewer'
const viewerReason = isViewer ? t('auth.viewerBadge') : undefined
const editDis = editDisabled || isViewer
const editDisReason = isViewer ? viewerReason : editDisabledReason
const delDisabled = deleteDisabled || isViewer
const delDisabledReason = isViewer
? t('auth.viewerBadge')
: deleteDisabledReason
const delDisabledReason = isViewer ? viewerReason : deleteDisabledReason
return (
<Space size={4}>
{onEdit && (
<Tooltip title={editDisabled ? editDisabledReason : (editTooltip ?? t('common.edit'))}>
<Tooltip title={editDis ? editDisReason : (editTooltip ?? t('common.edit'))}>
<Button
type="text"
size="small"
icon={<EditOutlined />}
disabled={editDisabled}
disabled={editDis}
onClick={onEdit}
/>
</Tooltip>