RBAC Improvements

Caching improvements
Maker-Checker Implementation
This commit is contained in:
2026-10-21 07:27:47 +02:00
parent dee9098379
commit 5d7e2f74ce
25 changed files with 1269 additions and 309 deletions
@@ -110,7 +110,7 @@ type ResolveChangeFormValues = z.infer<typeof resolveChangeSchema>;
export const ChangeManagementPage: React.FC = () => {
const queryClient = useQueryClient();
const { success, error: toastError } = useToast();
const { canAdd, canApprove, canExport } = useRbac();
const { canAdd, canApprove, canExport, canApproveRecord, isMaker } = useRbac();
const [selectedProjectId, setSelectedProjectId] = useState<string>('all');
const [activeTab, setActiveTab] = useState<'issues' | 'changes'>('issues');
@@ -1022,7 +1022,7 @@ export const ChangeManagementPage: React.FC = () => {
</span>
) : (
<>
{canApprove('change_management') && (
{canApproveRecord('change_management', cr.createdBy) && (
<button
onClick={() => openResolveChange(cr, ApprovalStatus.Approved)}
className="px-2.5 py-1 text-xs font-semibold text-emerald-300 bg-emerald-950/50 hover:bg-emerald-900/60 border border-emerald-700/50 rounded-lg transition cursor-pointer flex items-center gap-1"
@@ -1030,6 +1030,11 @@ export const ChangeManagementPage: React.FC = () => {
<Check className="w-3 h-3" /> Approve
</button>
)}
{canApprove('change_management') && isMaker(cr.createdBy) && (
<span className="text-[10px] text-amber-400 font-mono italic px-1.5 py-0.5 bg-amber-500/10 border border-amber-500/20 rounded">
Maker-Checker
</span>
)}
{canAdd('change_management') && (
<button
onClick={() => openResolveChange(cr, ApprovalStatus.Rejected)}
@@ -1522,9 +1527,21 @@ export const ChangeManagementPage: React.FC = () => {
>
<option value={ApprovalStatus.Pending}>Pending Review</option>
<option value={ApprovalStatus.Review}>Under Active Review</option>
<option value={ApprovalStatus.Approved} disabled={!canApprove('change_management')}>
Approved &amp; Enacted {!canApprove('change_management') ? '(Requires Update Permission)' : ''}
</option>
{(() => {
const canApproveChange = canApproveRecord('change_management', editingChange?.createdBy);
const isSelf = isMaker(editingChange?.createdBy);
let reason = '';
if (!canApprove('change_management')) {
reason = ' (Requires Update Permission)';
} else if (isSelf) {
reason = ' (Maker-Checker: Cannot approve own record)';
}
return (
<option value={ApprovalStatus.Approved} disabled={!canApproveChange}>
Approved &amp; Enacted {reason}
</option>
);
})()}
<option value={ApprovalStatus.Rejected}>Rejected</option>
</select>
</div>