mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 21:11:53 +00:00
chore(codebase) Update/UI code base (#5960)
This commit is contained in:
+25
-12
@@ -37,6 +37,10 @@ export async function authenticate(
|
||||
credentials: "Incorrect email or password",
|
||||
},
|
||||
};
|
||||
case "CallbackRouteError":
|
||||
return {
|
||||
message: error.cause?.err?.message,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
message: "Unknown error",
|
||||
@@ -152,22 +156,31 @@ export const getUserByMe = async (accessToken: string) => {
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error("Error in trying to get user by me");
|
||||
|
||||
const parsedResponse = await response.json();
|
||||
if (!response.ok) {
|
||||
// Handle different HTTP error codes
|
||||
switch (response.status) {
|
||||
case 401:
|
||||
throw new Error("Invalid or expired token");
|
||||
case 403:
|
||||
throw new Error(parsedResponse.errors?.[0]?.detail);
|
||||
case 404:
|
||||
throw new Error("User not found");
|
||||
default:
|
||||
throw new Error(
|
||||
parsedResponse.errors?.[0]?.detail || "Unknown error",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const name = parsedResponse.data.attributes.name;
|
||||
const email = parsedResponse.data.attributes.email;
|
||||
const company = parsedResponse.data.attributes.company_name;
|
||||
const dateJoined = parsedResponse.data.attributes.date_joined;
|
||||
return {
|
||||
name,
|
||||
email,
|
||||
company,
|
||||
dateJoined,
|
||||
name: parsedResponse.data.attributes.name,
|
||||
email: parsedResponse.data.attributes.email,
|
||||
company: parsedResponse.data.attributes.company_name,
|
||||
dateJoined: parsedResponse.data.attributes.date_joined,
|
||||
};
|
||||
} catch (error) {
|
||||
throw new Error("Error in trying to get user by me");
|
||||
} catch (error: any) {
|
||||
throw new Error(error.message || "Network error or server unreachable");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -140,6 +140,7 @@ const SSRComplianceGrid = async ({
|
||||
const { attributes } = compliance;
|
||||
const {
|
||||
framework,
|
||||
version,
|
||||
requirements_status: { passed, total },
|
||||
} = attributes;
|
||||
|
||||
@@ -147,6 +148,7 @@ const SSRComplianceGrid = async ({
|
||||
<ComplianceCard
|
||||
key={compliance.id}
|
||||
title={framework}
|
||||
version={version}
|
||||
passingRequirements={passed}
|
||||
totalRequirements={total}
|
||||
prevPassingRequirements={passed}
|
||||
|
||||
@@ -105,6 +105,7 @@ export const authConfig = {
|
||||
const isLoggedIn = !!auth?.user;
|
||||
const isOnDashboard = nextUrl.pathname.startsWith("/");
|
||||
const isSignUpPage = nextUrl.pathname === "/sign-up";
|
||||
//CLOUD API CHANGES
|
||||
|
||||
// Allow access to sign-up page
|
||||
if (isSignUpPage) return true;
|
||||
|
||||
@@ -17,9 +17,11 @@ import { ApiError, authFormSchema } from "@/types";
|
||||
export const AuthForm = ({
|
||||
type,
|
||||
invitationToken,
|
||||
isCloudEnv,
|
||||
}: {
|
||||
type: string;
|
||||
invitationToken?: string | null;
|
||||
isCloudEnv?: boolean;
|
||||
}) => {
|
||||
const formSchema = authFormSchema(type);
|
||||
const router = useRouter();
|
||||
@@ -47,7 +49,6 @@ export const AuthForm = ({
|
||||
email: data.email.toLowerCase(),
|
||||
password: data.password,
|
||||
});
|
||||
|
||||
if (result?.message === "Success") {
|
||||
router.push("/");
|
||||
} else if (result?.errors && "credentials" in result.errors) {
|
||||
@@ -55,6 +56,8 @@ export const AuthForm = ({
|
||||
type: "server",
|
||||
message: result.errors.credentials ?? "Incorrect email or password",
|
||||
});
|
||||
} else if (result?.message === "User email is not verified") {
|
||||
router.push("/email-verification");
|
||||
} else {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
@@ -73,7 +76,12 @@ export const AuthForm = ({
|
||||
description: "The user was registered successfully.",
|
||||
});
|
||||
form.reset();
|
||||
router.push("/sign-in");
|
||||
|
||||
if (isCloudEnv) {
|
||||
router.push("/email-verification");
|
||||
} else {
|
||||
router.push("/sign-in");
|
||||
}
|
||||
} else {
|
||||
newUser.errors.forEach((error: ApiError) => {
|
||||
const errorMessage = error.detail;
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getComplianceIcon } from "../icons";
|
||||
|
||||
interface ComplianceCardProps {
|
||||
title: string;
|
||||
version: string;
|
||||
passingRequirements: number;
|
||||
totalRequirements: number;
|
||||
prevPassingRequirements: number;
|
||||
@@ -14,9 +15,14 @@ interface ComplianceCardProps {
|
||||
|
||||
export const ComplianceCard: React.FC<ComplianceCardProps> = ({
|
||||
title,
|
||||
version,
|
||||
passingRequirements,
|
||||
totalRequirements,
|
||||
}) => {
|
||||
const formatTitle = (title: string) => {
|
||||
return title.split("-").join(" ");
|
||||
};
|
||||
|
||||
const ratingPercentage = Math.floor(
|
||||
(passingRequirements / totalRequirements) * 100,
|
||||
);
|
||||
@@ -47,7 +53,7 @@ export const ComplianceCard: React.FC<ComplianceCardProps> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<Card fullWidth isPressable isHoverable shadow="sm">
|
||||
<Card fullWidth isHoverable shadow="sm">
|
||||
<CardBody className="flex flex-row items-center justify-between space-x-4 dark:bg-prowler-blue-800">
|
||||
<div className="flex w-full items-center space-x-4">
|
||||
<Image
|
||||
@@ -56,7 +62,10 @@ export const ComplianceCard: React.FC<ComplianceCardProps> = ({
|
||||
className="h-10 w-10 min-w-10 rounded-md border-1 border-gray-300 bg-white object-contain p-1"
|
||||
/>
|
||||
<div className="flex w-full flex-col">
|
||||
<h4 className="text-md font-bold leading-5 3xl:text-lg">{title}</h4>
|
||||
<h4 className="text-md font-bold leading-5 3xl:text-lg">
|
||||
{formatTitle(title)}
|
||||
{version ? ` - ${version}` : ""}
|
||||
</h4>
|
||||
<Progress
|
||||
label="Your Rating:"
|
||||
size="sm"
|
||||
|
||||
@@ -17,7 +17,15 @@ export const DataCompliance = ({ scans, regions }: DataComplianceProps) => {
|
||||
const searchParams = useSearchParams();
|
||||
const [showClearButton, setShowClearButton] = useState(false);
|
||||
const scanIdParam = searchParams.get("scanId");
|
||||
const selectedScanId = scanIdParam || scans[0]?.id;
|
||||
const selectedScanId = scanIdParam || (scans.length > 0 ? scans[0].id : "");
|
||||
|
||||
useEffect(() => {
|
||||
if (!scanIdParam && scans.length > 0) {
|
||||
const params = new URLSearchParams(searchParams);
|
||||
params.set("scanId", scans[0].id);
|
||||
router.push(`?${params.toString()}`);
|
||||
}
|
||||
}, [scans, scanIdParam, searchParams, router]);
|
||||
|
||||
useEffect(() => {
|
||||
const hasFilters = Array.from(searchParams.keys()).some(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Control } from "react-hook-form";
|
||||
|
||||
import { CustomInput } from "@/components/ui/custom";
|
||||
import { CustomTextarea } from "@/components/ui/custom";
|
||||
import { KubernetesCredentials } from "@/types";
|
||||
|
||||
export const KubernetesCredentialsForm = ({
|
||||
@@ -15,17 +15,17 @@ export const KubernetesCredentialsForm = ({
|
||||
Connect via Credentials
|
||||
</div>
|
||||
<div className="py-2 text-default-500">
|
||||
Please provide the information for your Kubernetes credentials.
|
||||
Please provide the kubeconfig content for your Kubernetes credentials.
|
||||
</div>
|
||||
</div>
|
||||
<CustomInput
|
||||
<CustomTextarea
|
||||
control={control}
|
||||
name="kubeconfig_content"
|
||||
type="text"
|
||||
label="Kubeconfig Content"
|
||||
labelPlacement="inside"
|
||||
placeholder="Enter the Kubeconfig Content"
|
||||
placeholder="Paste your Kubeconfig YAML content here"
|
||||
variant="bordered"
|
||||
minRows={10}
|
||||
isRequired
|
||||
isInvalid={!!control._formState.errors.kubeconfig_content}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
"use client";
|
||||
|
||||
import { Textarea } from "@nextui-org/input";
|
||||
import React from "react";
|
||||
import { Control, FieldPath, FieldValues } from "react-hook-form";
|
||||
|
||||
import { FormControl, FormField, FormMessage } from "@/components/ui/form";
|
||||
|
||||
interface CustomTextareaProps<T extends FieldValues> {
|
||||
control: Control<T>;
|
||||
name: FieldPath<T>;
|
||||
label?: string;
|
||||
labelPlacement?: "inside" | "outside" | "outside-left";
|
||||
variant?: "flat" | "bordered" | "underlined" | "faded";
|
||||
size?: "sm" | "md" | "lg";
|
||||
placeholder?: string;
|
||||
defaultValue?: string;
|
||||
isRequired?: boolean;
|
||||
isInvalid?: boolean;
|
||||
minRows?: number;
|
||||
maxRows?: number;
|
||||
fullWidth?: boolean;
|
||||
disableAutosize?: boolean;
|
||||
description?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const CustomTextarea = <T extends FieldValues>({
|
||||
control,
|
||||
name,
|
||||
label = name,
|
||||
labelPlacement = "inside",
|
||||
placeholder,
|
||||
variant = "flat",
|
||||
size = "md",
|
||||
defaultValue,
|
||||
isRequired = false,
|
||||
isInvalid = false,
|
||||
minRows = 3,
|
||||
maxRows = 8,
|
||||
fullWidth = true,
|
||||
disableAutosize = false,
|
||||
description,
|
||||
}: CustomTextareaProps<T>) => {
|
||||
return (
|
||||
<FormField
|
||||
control={control}
|
||||
name={name}
|
||||
render={({ field }) => (
|
||||
<>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
id={name}
|
||||
label={label}
|
||||
labelPlacement={labelPlacement}
|
||||
placeholder={placeholder}
|
||||
variant={variant}
|
||||
size={size}
|
||||
isInvalid={isInvalid}
|
||||
isRequired={isRequired}
|
||||
defaultValue={defaultValue}
|
||||
minRows={minRows}
|
||||
maxRows={maxRows}
|
||||
fullWidth={fullWidth}
|
||||
disableAutosize={disableAutosize}
|
||||
description={description}
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage className="text-system-error dark:text-system-error" />
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -5,3 +5,4 @@ export * from "./custom-dropdown-filter";
|
||||
export * from "./custom-input";
|
||||
export * from "./custom-loader";
|
||||
export * from "./custom-radio";
|
||||
export * from "./custom-textarea";
|
||||
|
||||
Reference in New Issue
Block a user