fix(client): block renaming a storage backend onto an existing name

This commit is contained in:
jubnl
2026-08-20 14:45:20 +02:00
parent e22a836dd8
commit c4b1e18eaf
4 changed files with 22 additions and 2 deletions
@@ -120,4 +120,15 @@ describe('BackendForm', () => {
});
expect(committed.options).not.toHaveProperty('region');
});
it('FE-ADMIN-STORF-009: renaming onto another existing backend warns and blocks Apply', () => {
renderForm({ initial: S3_INITIAL });
expect(screen.getByRole('button', { name: 'Apply' })).toBeEnabled();
fireEvent.change(screen.getByLabelText(/Name/), { target: { value: 'uploads-local' } });
expect(screen.getByText(/A backend named uploads-local already exists/)).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Apply' })).toBeDisabled();
// Keeping the original name stays allowed.
fireEvent.change(screen.getByLabelText(/Name/), { target: { value: 'off-box' } });
expect(screen.getByRole('button', { name: 'Apply' })).toBeEnabled();
});
});
@@ -62,7 +62,7 @@ export default function BackendForm({
if (field.kind === 'backend-ref-list') return Array.isArray(value) && value.length > 0
return typeof value === 'string' && value.trim() !== ''
}
const duplicate = initial === null && backendNames.includes(name.trim())
const duplicate = name.trim() !== (initial?.name ?? '') && backendNames.includes(name.trim())
const blocked = hasPlaintextSecret({ type, options: values }) && !encryptionReady
const canApply =
name.trim() !== '' && !duplicate && fields.every((f) => !f.required || filled(f))
@@ -68,7 +68,7 @@ function MBackendForm({
if (field.kind === 'backend-ref-list') return Array.isArray(value) && value.length > 0
return typeof value === 'string' && value.trim() !== ''
}
const duplicate = initial === null && backendNames.includes(name.trim())
const duplicate = name.trim() !== (initial?.name ?? '') && backendNames.includes(name.trim())
const blocked = hasPlaintextSecret({ type, options: values }) && !encryptionReady
const canApply = name.trim() !== '' && !duplicate && fields.every((f) => !f.required || filled(f))
@@ -90,4 +90,13 @@ describe('MAdminStoragePanel', () => {
fireEvent.click(screen.getByRole('button', { name: 'Save changes' }));
expect(await screen.findByText('registry says no')).toBeInTheDocument();
});
it('FE-MOB-MSTOR-005: renaming onto another existing backend warns and blocks Apply', async () => {
await renderPanel();
fireEvent.click(within(screen.getByTestId('m-storage-backend-off-box')).getByRole('button', { name: 'Edit' }));
const nameInput = screen.getByDisplayValue('off-box');
fireEvent.change(nameInput, { target: { value: 'uploads-local' } });
expect(screen.getByText(/A backend named uploads-local already exists/)).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Apply' })).toBeDisabled();
});
});