/** * AccessRulesTable * * Checkbox-based compact table for editing RBAC access rules. * Shows all permissions in a matrix format similar to Unix permissions. */ import React from 'react'; import { FaTable, FaDesktop, FaServer, FaTrash } from 'react-icons/fa'; import { type AccessRule, type RuleContext, type AccessLevel } from '../../hooks/useAccessRules'; import styles from './AccessRules.module.css'; import { useLanguage } from '../../providers/language/LanguageContext'; // ============================================================================= // TYPES // ============================================================================= interface AccessRulesTableProps { rules: AccessRule[]; context: RuleContext; readOnly?: boolean; onUpdate: (ruleId: string, updates: Partial) => void; onDelete: (ruleId: string) => void; } // ============================================================================= // HELPER FUNCTIONS // ============================================================================= /** * Check if access level is at least the specified minimum level. * Hierarchy: n (none) < m (mine) < g (group) < a (all) */ const hasLevel = (level: AccessLevel | null | undefined, minLevel: 'm' | 'g' | 'a'): boolean => { if (!level || level === 'n') return false; const hierarchy = ['n', 'm', 'g', 'a']; return hierarchy.indexOf(level) >= hierarchy.indexOf(minLevel); }; /** * Calculate the new access level when a checkbox is toggled. */ const calculateNewLevel = ( _currentLevel: AccessLevel | null | undefined, targetLevel: 'm' | 'g' | 'a', checked: boolean ): AccessLevel => { if (checked) { // Activating: set to target level return targetLevel; } else { // Deactivating: set to level below target const hierarchy: AccessLevel[] = ['n', 'm', 'g', 'a']; const targetIndex = hierarchy.indexOf(targetLevel); return hierarchy[targetIndex - 1] || 'n'; } }; // ============================================================================= // RULE ROW COMPONENT // ============================================================================= interface AccessRuleRowProps { rule: AccessRule; isDataContext: boolean; readOnly?: boolean; onUpdate: (ruleId: string, updates: Partial) => void; onDelete: (ruleId: string) => void; } const AccessRuleRow: React.FC = ({ rule, isDataContext, readOnly, onUpdate, onDelete, }) => { const { t } = useLanguage(); const opTitle = (op: 'create' | 'read' | 'update' | 'delete') => ({ create: t('Erstellen'), read: t('Lesen'), update: t('Bearbeiten'), delete: t('Löschen') })[op]; const handleLevelToggle = ( field: 'read' | 'create' | 'update' | 'delete', targetLevel: 'm' | 'g' | 'a', checked: boolean ) => { const currentLevel = rule[field] as AccessLevel | null | undefined; const newLevel = calculateNewLevel(currentLevel, targetLevel, checked); onUpdate(rule.id, { [field]: newLevel }); }; // Get icon for context const getContextIcon = () => { switch (rule.context) { case 'DATA': return ; case 'UI': return ; case 'RESOURCE': return ; default: return ; } }; return ( {/* Object Name */} {getContextIcon()} {rule.item || '(global)'} {/* View Checkbox */} onUpdate(rule.id, { view: e.target.checked })} disabled={readOnly} title={t('Sichtbar')} /> {/* CRUD Checkboxes for DATA context */} {isDataContext && ( <> {/* EIGENE (m) */} {(['create', 'read', 'update', 'delete'] as const).map(op => ( handleLevelToggle(op, 'm', e.target.checked)} disabled={readOnly} title={`${opTitle(op)} - ${t('Eigene')}`} /> ))} {/* GRUPPE (g) */} {(['create', 'read', 'update', 'delete'] as const).map(op => ( handleLevelToggle(op, 'g', e.target.checked)} disabled={readOnly} title={`${opTitle(op)} - ${t('Gruppe')}`} /> ))} {/* ALLE (a) */} {(['create', 'read', 'update', 'delete'] as const).map(op => ( handleLevelToggle(op, 'a', e.target.checked)} disabled={readOnly} title={`${opTitle(op)} - ${t('Alle')}`} /> ))} )} {/* Delete Button */} {!readOnly && ( )} ); }; // ============================================================================= // MAIN TABLE COMPONENT // ============================================================================= export const AccessRulesTable: React.FC = ({ rules, context, readOnly, onUpdate, onDelete, }) => { const { t } = useLanguage(); const isDataContext = context === 'DATA'; if (rules.length === 0) { return null; } return (
{isDataContext && ( <> )} {isDataContext && ( )} {rules.map(rule => ( ))}
{t('object dot notation')} {t('Ansicht')}{t('own')} {t('group')} {t('Alle')}
C R U D C R U D C R U D
); }; export default AccessRulesTable;