fix(ui): allow rename and delete for dynamic providers (#11957)

Co-authored-by: Pablo F.G <pablo.fernandez@prowler.com>
This commit is contained in:
Pablo Fernandez Guerra (PFE)
2026-07-16 11:50:35 +02:00
committed by GitHub
parent a022ad5c7a
commit 7d8c64d35b
3 changed files with 25 additions and 27 deletions
@@ -0,0 +1 @@
Dynamic providers can now be renamed and deleted from the Providers table
@@ -303,7 +303,7 @@ describe("DataTableRowActions", () => {
expect(screen.queryByText("Update Credentials")).not.toBeInTheDocument();
});
it("blocks provider-account actions (alias/credentials/delete) for a dynamic provider but keeps operational actions", async () => {
it("allows rename/delete and operational actions for a dynamic provider but hides credential management", async () => {
// Given a dynamic provider outside the configurable set, with the advanced
// schedule capability enabled (so Edit Scan Schedule can show).
const user = userEvent.setup();
@@ -323,15 +323,16 @@ describe("DataTableRowActions", () => {
// When
await user.click(screen.getByRole("button"));
// Then — provider-account CRUD is suppressed (can't add/edit/delete it)
expect(screen.queryByText("Edit Provider Alias")).not.toBeInTheDocument();
expect(screen.queryByText("Add Credentials")).not.toBeInTheDocument();
expect(screen.queryByText("Update Credentials")).not.toBeInTheDocument();
expect(screen.queryByText("Delete Provider")).not.toBeInTheDocument();
// ...but operational actions the provider exists for stay available
// Then — rename and delete are backend-generic, so they stay available
expect(screen.getByText("Edit Provider Alias")).toBeInTheDocument();
expect(screen.getByText("Delete Provider")).toBeInTheDocument();
// ...operational actions stay available too
expect(screen.getByText("Test Connection")).toBeInTheDocument();
expect(screen.getByText("View Scan Jobs")).toBeInTheDocument();
expect(screen.getByText("Edit Scan Schedule")).toBeInTheDocument();
// ...but credential management is hidden (no bespoke wizard for dynamic types)
expect(screen.queryByText("Add Credentials")).not.toBeInTheDocument();
expect(screen.queryByText("Update Credentials")).not.toBeInTheDocument();
});
it("navigates to the provider-filtered scan jobs from View Scan Jobs", async () => {
@@ -310,8 +310,8 @@ export function DataTableRowActions({
const provider = isOrganizationRow ? null : rowData;
const providerId = provider?.id ?? "";
const providerType = provider?.attributes.provider ?? "";
// Only predefined providers can be managed from the UI
const canManageProvider = isConfigurableProvider(providerType);
// Only predefined providers can manage credentials from the UI
const canManageCredentials = isConfigurableProvider(providerType);
const providerUid = provider?.attributes.uid ?? "";
const providerAlias = provider?.attributes.alias ?? null;
const providerSecretId = provider?.relationships.secret.data?.id ?? null;
@@ -590,13 +590,11 @@ export function DataTableRowActions({
)}
<div className="relative flex items-center justify-end gap-2">
<ActionDropdown>
{canManageProvider && (
<ActionDropdownItem
icon={<Pencil />}
label="Edit Provider Alias"
onSelect={() => setIsEditOpen(true)}
/>
)}
<ActionDropdownItem
icon={<Pencil />}
label="Edit Provider Alias"
onSelect={() => setIsEditOpen(true)}
/>
<ActionDropdownItem
icon={<Timer />}
label="View Scan Jobs"
@@ -634,7 +632,7 @@ export function DataTableRowActions({
disabled
/>
)}
{canManageProvider && (
{canManageCredentials && (
<ActionDropdownItem
icon={<KeyRound />}
label={hasSecret ? "Update Credentials" : "Add Credentials"}
@@ -661,16 +659,14 @@ export function DataTableRowActions({
}}
disabled={!hasSecret || loading}
/>
{canManageProvider && (
<ActionDropdownDangerZone>
<ActionDropdownItem
icon={<Trash2 />}
label="Delete Provider"
destructive
onSelect={() => setIsDeleteOpen(true)}
/>
</ActionDropdownDangerZone>
)}
<ActionDropdownDangerZone>
<ActionDropdownItem
icon={<Trash2 />}
label="Delete Provider"
destructive
onSelect={() => setIsDeleteOpen(true)}
/>
</ActionDropdownDangerZone>
</ActionDropdown>
</div>
</>