mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 12:31:54 +00:00
Merge branch 'chore/unify-filter-search-and-batch-patterns' into fix/resources-filters-and-drawer-polish
This commit is contained in:
@@ -151,6 +151,8 @@ node_modules
|
||||
|
||||
# Persistent data
|
||||
_data/
|
||||
/openspec/
|
||||
/.gitmodules
|
||||
|
||||
# AI Instructions (generated by skills/setup.sh from AGENTS.md)
|
||||
CLAUDE.md
|
||||
|
||||
@@ -22,6 +22,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libtool \
|
||||
libxslt1-dev \
|
||||
python3-dev \
|
||||
git \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install PowerShell
|
||||
|
||||
Generated
+10
-10
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 2.3.4 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "about-time"
|
||||
@@ -2974,7 +2974,7 @@ files = [
|
||||
[package.dependencies]
|
||||
autopep8 = "*"
|
||||
Django = ">=4.2"
|
||||
gprof2dot = ">=2017.09.19"
|
||||
gprof2dot = ">=2017.9.19"
|
||||
sqlparse = "*"
|
||||
|
||||
[[package]]
|
||||
@@ -4582,7 +4582,7 @@ files = [
|
||||
|
||||
[package.dependencies]
|
||||
attrs = ">=22.2.0"
|
||||
jsonschema-specifications = ">=2023.03.6"
|
||||
jsonschema-specifications = ">=2023.3.6"
|
||||
referencing = ">=0.28.4"
|
||||
rpds-py = ">=0.7.1"
|
||||
|
||||
@@ -4790,7 +4790,7 @@ librabbitmq = ["librabbitmq (>=2.0.0) ; python_version < \"3.11\""]
|
||||
mongodb = ["pymongo (==4.15.3)"]
|
||||
msgpack = ["msgpack (==1.1.2)"]
|
||||
pyro = ["pyro4 (==4.82)"]
|
||||
qpid = ["qpid-python (==1.36.0-1)", "qpid-tools (==1.36.0-1)"]
|
||||
qpid = ["qpid-python (==1.36.0.post1)", "qpid-tools (==1.36.0.post1)"]
|
||||
redis = ["redis (>=4.5.2,!=4.5.5,!=5.0.2,<6.5)"]
|
||||
slmq = ["softlayer_messaging (>=1.0.3)"]
|
||||
sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"]
|
||||
@@ -4811,7 +4811,7 @@ files = [
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=14.05.14"
|
||||
certifi = ">=14.5.14"
|
||||
durationpy = ">=0.7"
|
||||
google-auth = ">=1.0.1"
|
||||
oauthlib = ">=3.2.2"
|
||||
@@ -6964,11 +6964,11 @@ description = "C parser in Python"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["main", "dev"]
|
||||
markers = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""
|
||||
files = [
|
||||
{file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"},
|
||||
{file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"},
|
||||
]
|
||||
markers = {main = "implementation_name != \"PyPy\" and platform_python_implementation != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""}
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
@@ -7194,7 +7194,7 @@ files = [
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
astroid = ">=3.2.2,<=3.3.0-dev0"
|
||||
astroid = ">=3.2.2,<=3.3.0.dev0"
|
||||
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
|
||||
dill = [
|
||||
{version = ">=0.3.7", markers = "python_version >= \"3.12\""},
|
||||
@@ -7216,7 +7216,7 @@ description = "The MSALRuntime Python Interop Package"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
groups = ["main"]
|
||||
markers = "(platform_system == \"Windows\" or platform_system == \"Darwin\" or platform_system == \"Linux\") and sys_platform == \"win32\""
|
||||
markers = "sys_platform == \"win32\" and (platform_system == \"Windows\" or platform_system == \"Darwin\" or platform_system == \"Linux\")"
|
||||
files = [
|
||||
{file = "pymsalruntime-0.18.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:0c22e2e83faa10de422bbfaacc1bb2887c9025ee8a53f0fc2e4f7db01c4a7b66"},
|
||||
{file = "pymsalruntime-0.18.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:8ce2944a0f944833d047bb121396091e00287e2b6373716106da86ea99abf379"},
|
||||
@@ -8209,10 +8209,10 @@ files = [
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
botocore = ">=1.37.4,<2.0a.0"
|
||||
botocore = ">=1.37.4,<2.0a0"
|
||||
|
||||
[package.extras]
|
||||
crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"]
|
||||
crt = ["botocore[crt] (>=1.37.4,<2.0a0)"]
|
||||
|
||||
[[package]]
|
||||
name = "safety"
|
||||
|
||||
Generated
+6
-5
@@ -1934,6 +1934,7 @@ files = [
|
||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
]
|
||||
markers = {dev = "platform_system == \"Windows\" or sys_platform == \"win32\""}
|
||||
|
||||
[[package]]
|
||||
name = "contextlib2"
|
||||
@@ -3102,7 +3103,7 @@ files = [
|
||||
|
||||
[package.dependencies]
|
||||
attrs = ">=22.2.0"
|
||||
jsonschema-specifications = ">=2023.03.6"
|
||||
jsonschema-specifications = ">=2023.3.6"
|
||||
referencing = ">=0.28.4"
|
||||
rpds-py = ">=0.7.1"
|
||||
|
||||
@@ -3182,7 +3183,7 @@ files = [
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=14.05.14"
|
||||
certifi = ">=14.5.14"
|
||||
durationpy = ">=0.7"
|
||||
google-auth = ">=1.0.1"
|
||||
oauthlib = ">=3.2.2"
|
||||
@@ -4988,7 +4989,7 @@ files = [
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
astroid = ">=3.3.8,<=3.4.0-dev0"
|
||||
astroid = ">=3.3.8,<=3.4.0.dev0"
|
||||
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
|
||||
dill = [
|
||||
{version = ">=0.2", markers = "python_version < \"3.11\""},
|
||||
@@ -5834,10 +5835,10 @@ files = [
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
botocore = ">=1.37.4,<2.0a.0"
|
||||
botocore = ">=1.37.4,<2.0a0"
|
||||
|
||||
[package.extras]
|
||||
crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"]
|
||||
crt = ["botocore[crt] (>=1.37.4,<2.0a0)"]
|
||||
|
||||
[[package]]
|
||||
name = "safety"
|
||||
|
||||
+10
-4
@@ -6,17 +6,23 @@ All notable changes to the **Prowler UI** are documented in this file.
|
||||
|
||||
### 🔄 Changed
|
||||
|
||||
- Redesign compliance page, client-side search for compliance frameworks, compact scan selector trigger, enhanced compliance cards [(#10767)](https://github.com/prowler-cloud/prowler/pull/10767)
|
||||
- Allows tenant owners to expel users from their organizations [(#10787)](https://github.com/prowler-cloud/prowler/pull/10787)
|
||||
- Shared filter dropdowns now support local option search and auto-scroll to the first visible match across table and provider filters
|
||||
- Resources now use batch-applied filters, render metadata JSON with syntax highlighting, simplify metadata/tags tabs, and keep finding-row Learn more links interactive inside the drawer [(#10861)](https://github.com/prowler-cloud/prowler/pull/10861)
|
||||
|
||||
### ❌ Removed
|
||||
|
||||
- Redesign compliance page with a horizontal ThreatScore card (always-visible pillar breakdown + ActionDropdown), client-side search for compliance frameworks, compact scan selector trigger, responsive mobile filters, download-started toasts for CSV/PDF exports, enhanced compliance cards with truncated titles, and Alert-based empty/error states; migrate Progress component from HeroUI to shadcn [(#10767)](https://github.com/prowler-cloud/prowler/pull/10767)
|
||||
- Shared filter dropdowns now support local option search and auto-scroll to the first visible match across table and provider filters [(#10859)](https://github.com/prowler-cloud/prowler/pull/10859)
|
||||
- Backward-compatibility middleware redirect from `/sign-up?invitation_token=…` to `/invitation/accept?invitation_token=…`; new invitation emails use `/invitation/accept` directly [(#10797)](https://github.com/prowler-cloud/prowler/pull/10797)
|
||||
|
||||
---
|
||||
|
||||
## [1.24.4] (Prowler UNRELEASED)
|
||||
|
||||
### 🐞 Fixed
|
||||
|
||||
- Provider wizard no longer advances to the Launch Scan step when rotating credentials [(#10851)](https://github.com/prowler-cloud/prowler/pull/10851)
|
||||
|
||||
---
|
||||
|
||||
## [1.24.2] (Prowler v5.24.2)
|
||||
|
||||
### 🐞 Fixed
|
||||
|
||||
@@ -153,7 +153,7 @@ describe("useProviderWizardController", () => {
|
||||
expect(onOpenChange).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("moves to launch step after a successful connection test in update mode", async () => {
|
||||
it("closes the wizard after a successful connection test in update mode", async () => {
|
||||
// Given
|
||||
const onOpenChange = vi.fn();
|
||||
const { result } = renderHook(() =>
|
||||
@@ -181,9 +181,10 @@ describe("useProviderWizardController", () => {
|
||||
result.current.handleTestSuccess();
|
||||
});
|
||||
|
||||
// Then
|
||||
expect(result.current.currentStep).toBe(PROVIDER_WIZARD_STEP.LAUNCH);
|
||||
expect(onOpenChange).not.toHaveBeenCalled();
|
||||
// Then: credential rotation never surfaces the launch/schedule step
|
||||
expect(onOpenChange).toHaveBeenCalledWith(false);
|
||||
expect(refreshMock).toHaveBeenCalledTimes(1);
|
||||
expect(result.current.currentStep).not.toBe(PROVIDER_WIZARD_STEP.LAUNCH);
|
||||
});
|
||||
|
||||
it("does not override launch footer config in the controller", () => {
|
||||
|
||||
@@ -197,6 +197,12 @@ export function useProviderWizardController({
|
||||
};
|
||||
|
||||
const handleTestSuccess = () => {
|
||||
if (
|
||||
useProviderWizardStore.getState().mode === PROVIDER_WIZARD_MODE.UPDATE
|
||||
) {
|
||||
handleClose();
|
||||
return;
|
||||
}
|
||||
setCurrentStep(PROVIDER_WIZARD_STEP.LAUNCH);
|
||||
};
|
||||
|
||||
@@ -234,6 +240,7 @@ export function useProviderWizardController({
|
||||
handleTestSuccess,
|
||||
isOrgDirectEntry,
|
||||
isProviderFlow,
|
||||
mode,
|
||||
modalTitle,
|
||||
openOrganizationsFlow,
|
||||
orgCurrentStep,
|
||||
|
||||
@@ -10,7 +10,10 @@ import { DialogHeader, DialogTitle } from "@/components/shadcn/dialog";
|
||||
import { Modal } from "@/components/shadcn/modal";
|
||||
import { useScrollHint } from "@/hooks/use-scroll-hint";
|
||||
import { ORG_SETUP_PHASE, ORG_WIZARD_STEP } from "@/types/organizations";
|
||||
import { PROVIDER_WIZARD_STEP } from "@/types/provider-wizard";
|
||||
import {
|
||||
PROVIDER_WIZARD_MODE,
|
||||
PROVIDER_WIZARD_STEP,
|
||||
} from "@/types/provider-wizard";
|
||||
|
||||
import { useProviderWizardController } from "./hooks/use-provider-wizard-controller";
|
||||
import {
|
||||
@@ -23,7 +26,12 @@ import { WIZARD_FOOTER_ACTION_TYPE } from "./steps/footer-controls";
|
||||
import { LaunchStep } from "./steps/launch-step";
|
||||
import { TestConnectionStep } from "./steps/test-connection-step";
|
||||
import type { OrgWizardInitialData, ProviderWizardInitialData } from "./types";
|
||||
import { WizardStepper } from "./wizard-stepper";
|
||||
import { PROVIDER_WIZARD_STEPS, WizardStepper } from "./wizard-stepper";
|
||||
|
||||
const UPDATE_MODE_WIZARD_STEPS = PROVIDER_WIZARD_STEPS.slice(
|
||||
0,
|
||||
PROVIDER_WIZARD_STEP.LAUNCH,
|
||||
);
|
||||
|
||||
interface ProviderWizardModalProps {
|
||||
open: boolean;
|
||||
@@ -47,6 +55,7 @@ export function ProviderWizardModal({
|
||||
handleTestSuccess,
|
||||
isOrgDirectEntry,
|
||||
isProviderFlow,
|
||||
mode,
|
||||
modalTitle,
|
||||
openOrganizationsFlow,
|
||||
orgCurrentStep,
|
||||
@@ -97,7 +106,14 @@ export function ProviderWizardModal({
|
||||
<div className="mt-6 flex min-h-0 flex-1 flex-col overflow-hidden lg:mt-8 lg:flex-row">
|
||||
<div className="mb-4 box-border w-full shrink-0 lg:mb-0 lg:w-[328px]">
|
||||
{isProviderFlow ? (
|
||||
<WizardStepper currentStep={currentStep} />
|
||||
<WizardStepper
|
||||
currentStep={currentStep}
|
||||
steps={
|
||||
mode === PROVIDER_WIZARD_MODE.UPDATE
|
||||
? UPDATE_MODE_WIZARD_STEPS
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<WizardStepper
|
||||
currentStep={orgCurrentStep}
|
||||
|
||||
@@ -7,17 +7,18 @@ import { ProwlerShort } from "@/components/icons/prowler/ProwlerIcons";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { IconComponent, IconSvgProps } from "@/types/components";
|
||||
|
||||
interface WizardStepperProps {
|
||||
currentStep: number;
|
||||
stepOffset?: number;
|
||||
}
|
||||
|
||||
interface StepConfig {
|
||||
label: string;
|
||||
description: string;
|
||||
icon: IconComponent;
|
||||
}
|
||||
|
||||
interface WizardStepperProps {
|
||||
currentStep: number;
|
||||
stepOffset?: number;
|
||||
steps?: StepConfig[];
|
||||
}
|
||||
|
||||
const STEPS: StepConfig[] = [
|
||||
{
|
||||
label: "Link a Cloud Provider",
|
||||
@@ -43,18 +44,21 @@ const STEPS: StepConfig[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const PROVIDER_WIZARD_STEPS = STEPS;
|
||||
|
||||
export function WizardStepper({
|
||||
currentStep,
|
||||
stepOffset = 0,
|
||||
steps = STEPS,
|
||||
}: WizardStepperProps) {
|
||||
const activeVisualStep = Math.max(
|
||||
0,
|
||||
Math.min(currentStep + stepOffset, STEPS.length - 1),
|
||||
Math.min(currentStep + stepOffset, steps.length - 1),
|
||||
);
|
||||
|
||||
return (
|
||||
<nav aria-label="Wizard progress" className="flex flex-col gap-0">
|
||||
{STEPS.map((step, index) => {
|
||||
{steps.map((step, index) => {
|
||||
const isComplete = index < activeVisualStep;
|
||||
const isActive = index === activeVisualStep;
|
||||
const isInactive = index > activeVisualStep;
|
||||
@@ -67,7 +71,7 @@ export function WizardStepper({
|
||||
isActive={isActive}
|
||||
icon={step.icon}
|
||||
/>
|
||||
{index < STEPS.length - 1 && (
|
||||
{index < steps.length - 1 && (
|
||||
<StepConnector isComplete={isComplete} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from "react";
|
||||
import { Command as CommandPrimitive } from "cmdk";
|
||||
import { SearchIcon } from "lucide-react";
|
||||
import {
|
||||
type ComponentPropsWithoutRef,
|
||||
type ElementRef,
|
||||
forwardRef,
|
||||
} from "react";
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
|
||||
Reference in New Issue
Block a user