mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-03-21 18:58:04 +00:00
feat: upgrade to Next.js 16.1.3 (#9826)
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
.now/*
|
||||
*.css
|
||||
.changeset
|
||||
dist
|
||||
esm/*
|
||||
public/*
|
||||
tests/*
|
||||
scripts/*
|
||||
*.config.js
|
||||
.DS_Store
|
||||
node_modules
|
||||
coverage
|
||||
.next
|
||||
build
|
||||
next-env.d.ts
|
||||
!.commitlintrc.cjs
|
||||
!.lintstagedrc.cjs
|
||||
!jest.config.js
|
||||
!plopfile.js
|
||||
!react-shim.js
|
||||
!tsup.config.ts
|
||||
@@ -1,53 +0,0 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
node: true,
|
||||
es2021: true,
|
||||
},
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["prettier", "@typescript-eslint", "simple-import-sort", "jsx-a11y"],
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:security/recommended-legacy",
|
||||
"plugin:jsx-a11y/recommended",
|
||||
"eslint-config-prettier",
|
||||
"prettier",
|
||||
"next/core-web-vitals",
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// console.error are allowed but no console.log
|
||||
"no-console": ["error", { allow: ["error"] }],
|
||||
eqeqeq: 2,
|
||||
quotes: ["error", "double", "avoid-escape"],
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"security/detect-object-injection": "off",
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
endOfLine: "auto",
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
},
|
||||
],
|
||||
"eol-last": ["error", "always"],
|
||||
"simple-import-sort/imports": "error",
|
||||
"simple-import-sort/exports": "error",
|
||||
"jsx-a11y/anchor-is-valid": [
|
||||
"error",
|
||||
{
|
||||
components: ["Link"],
|
||||
specialLink: ["hrefLeft", "hrefRight"],
|
||||
aspects: ["invalidHref", "preferButton"],
|
||||
},
|
||||
],
|
||||
"jsx-a11y/alt-text": "error",
|
||||
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
|
||||
},
|
||||
};
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
All notable changes to the **Prowler UI** are documented in this file.
|
||||
|
||||
## [1.18.0] (Prowler v5.18.0)
|
||||
## [1.18.0] (Prowler UNRELEASED)
|
||||
|
||||
### 🔄 Changed
|
||||
|
||||
@@ -25,6 +25,7 @@ All notable changes to the **Prowler UI** are documented in this file.
|
||||
|
||||
### 🔄 Changed
|
||||
|
||||
- Upgrade Next.js from 15.5.9 to 16.1.3 with ESLint 9 flat config migration [(#9826)](https://github.com/prowler-cloud/prowler/pull/9826)
|
||||
- Refactor Lighthouse AI MCP tool filtering from blacklist to whitelist approach for improved security [(#9802)](https://github.com/prowler-cloud/prowler/pull/9802)
|
||||
- Refactor ScatterPlot as reusable generic component with TypeScript generics [(#9664)](https://github.com/prowler-cloud/prowler/pull/9664)
|
||||
- Rename resource_group filter to group in Resources page and Overview cards [(#9492)](https://github.com/prowler-cloud/prowler/pull/9492)
|
||||
|
||||
@@ -89,7 +89,7 @@ export const createApiKey = async (
|
||||
const data = (await handleApiResponse(response)) as CreateApiKeyResponse;
|
||||
|
||||
// Revalidate the api-keys list
|
||||
revalidateTag("api-keys");
|
||||
revalidateTag("api-keys", "max");
|
||||
|
||||
return { data };
|
||||
} catch (error) {
|
||||
@@ -138,7 +138,7 @@ export const updateApiKey = async (
|
||||
const data = (await handleApiResponse(response)) as SingleApiKeyResponse;
|
||||
|
||||
// Revalidate the api-keys list
|
||||
revalidateTag("api-keys");
|
||||
revalidateTag("api-keys", "max");
|
||||
|
||||
return { data };
|
||||
} catch (error) {
|
||||
@@ -171,7 +171,7 @@ export const revokeApiKey = async (
|
||||
}
|
||||
|
||||
// Revalidate the api-keys list
|
||||
revalidateTag("api-keys");
|
||||
revalidateTag("api-keys", "max");
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
|
||||
@@ -82,7 +82,7 @@ export const createNewUser = async (formData: SignUpFormData) => {
|
||||
}
|
||||
|
||||
return parsedResponse;
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
return {
|
||||
errors: [
|
||||
{
|
||||
@@ -127,7 +127,7 @@ export const getToken = async (formData: SignInFormData) => {
|
||||
accessToken,
|
||||
refreshToken,
|
||||
};
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
throw new Error("Error in trying to get token");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use server";
|
||||
|
||||
import { extract } from "@extractus/feed-extractor";
|
||||
import { unstable_cache } from "next/cache";
|
||||
import Parser from "rss-parser";
|
||||
import { z } from "zod";
|
||||
|
||||
import type { FeedError, FeedItem, FeedSource, ParsedFeed } from "./types";
|
||||
@@ -42,44 +42,24 @@ function getFeedSources(): FeedSource[] {
|
||||
async function parseSingleFeed(
|
||||
source: FeedSource,
|
||||
): Promise<{ items: FeedItem[]; error?: FeedError }> {
|
||||
const parser = new Parser({
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
"User-Agent": "Prowler-UI/1.0",
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
const feed = await parser.parseURL(source.url);
|
||||
const feed = await extract(source.url);
|
||||
|
||||
// Map RSS items to our FeedItem type
|
||||
const items: FeedItem[] = (feed.items || []).map((item) => {
|
||||
// Validate and parse date with fallback to current date
|
||||
const parsePubDate = (): string => {
|
||||
const dateString = item.isoDate || item.pubDate;
|
||||
if (!dateString) return new Date().toISOString();
|
||||
|
||||
const parsed = new Date(dateString);
|
||||
return isNaN(parsed.getTime())
|
||||
? new Date().toISOString()
|
||||
: parsed.toISOString();
|
||||
};
|
||||
|
||||
return {
|
||||
id: item.guid || item.link || `${source.id}-${item.title}`,
|
||||
title: item.title || "Untitled",
|
||||
description:
|
||||
item.contentSnippet || item.content || item.description || "",
|
||||
link: item.link || "",
|
||||
pubDate: parsePubDate(),
|
||||
sourceId: source.id,
|
||||
sourceName: source.name,
|
||||
sourceType: source.type,
|
||||
author: item.creator || item.author,
|
||||
categories: item.categories || [],
|
||||
contentSnippet: item.contentSnippet || undefined,
|
||||
};
|
||||
});
|
||||
const items: FeedItem[] = (feed.entries || []).map((entry) => ({
|
||||
id: entry.id || entry.link || `${source.id}-${entry.title}`,
|
||||
title: entry.title || "Untitled",
|
||||
description: entry.description || "",
|
||||
link: entry.link || "",
|
||||
pubDate: entry.published
|
||||
? new Date(entry.published).toISOString()
|
||||
: new Date().toISOString(),
|
||||
sourceId: source.id,
|
||||
sourceName: source.name,
|
||||
sourceType: source.type,
|
||||
author: undefined,
|
||||
categories: [],
|
||||
contentSnippet: entry.description?.slice(0, 500),
|
||||
}));
|
||||
|
||||
return { items };
|
||||
} catch (error) {
|
||||
|
||||
@@ -404,7 +404,7 @@ export const pollConnectionTestStatus = async (
|
||||
error: pollResult.message || "Connection test failed.",
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
return { success: false, error: "Failed to check connection test status." };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -210,7 +210,7 @@ export const initiateSamlAuth = async (email: string) => {
|
||||
errorData.errors?.[0]?.detail ||
|
||||
"An error occurred during SAML authentication.",
|
||||
};
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
return {
|
||||
success: false,
|
||||
error: "Failed to connect to authentication service.",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const COMPLIANCE_WATCHLIST_OVERVIEW_TYPE = {
|
||||
export const COMPLIANCE_WATCHLIST_OVERVIEW_TYPE = {
|
||||
WATCHLIST_OVERVIEW: "compliance-watchlist-overviews",
|
||||
} as const;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export type VerticalStepProps = {
|
||||
title?: ReactNode;
|
||||
};
|
||||
|
||||
const STEP_COLORS = {
|
||||
export const STEP_COLORS = {
|
||||
primary: "primary",
|
||||
secondary: "secondary",
|
||||
success: "success",
|
||||
|
||||
@@ -7,7 +7,7 @@ import { ConnectLLMProvider } from "@/components/lighthouse/connect-llm-provider
|
||||
import { SelectBedrockAuthMethod } from "@/components/lighthouse/select-bedrock-auth-method";
|
||||
import type { LighthouseProvider } from "@/types/lighthouse";
|
||||
|
||||
const BEDROCK_AUTH_MODES = {
|
||||
export const BEDROCK_AUTH_MODES = {
|
||||
IAM: "iam",
|
||||
API_KEY: "api_key",
|
||||
} as const;
|
||||
|
||||
@@ -50,14 +50,12 @@ export async function GET(req: Request) {
|
||||
|
||||
return NextResponse.redirect(new URL("/", baseUrl));
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("SignIn error:", error);
|
||||
return NextResponse.redirect(
|
||||
new URL("/sign-in?error=AuthenticationFailed", baseUrl),
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Error in Github callback:", error);
|
||||
return NextResponse.json(
|
||||
{ error: (error as Error).message },
|
||||
|
||||
@@ -50,14 +50,12 @@ export async function GET(req: Request) {
|
||||
|
||||
return NextResponse.redirect(new URL("/", baseUrl));
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("SignIn error:", error);
|
||||
return NextResponse.redirect(
|
||||
new URL("/sign-in?error=AuthenticationFailed", baseUrl),
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Error in Google callback:", error);
|
||||
return NextResponse.json(
|
||||
{ error: (error as Error).message },
|
||||
|
||||
@@ -36,7 +36,7 @@ const MAP_COLORS = {
|
||||
pointHover: "var(--bg-fail)",
|
||||
} as const;
|
||||
|
||||
const RISK_LEVELS = {
|
||||
export const RISK_LEVELS = {
|
||||
LOW_HIGH: "low-high",
|
||||
HIGH: "high",
|
||||
CRITICAL: "critical",
|
||||
|
||||
@@ -381,7 +381,6 @@ export function ThreatMap({
|
||||
}
|
||||
|
||||
svg.appendChild(pointsGroup);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
dimensions,
|
||||
data.locations,
|
||||
|
||||
@@ -130,7 +130,7 @@ export const JiraIntegrationForm = ({
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
|
||||
@@ -78,7 +78,7 @@ export const JiraIntegrationsManager = ({
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
@@ -109,7 +109,7 @@ export const JiraIntegrationsManager = ({
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
@@ -160,7 +160,7 @@ export const JiraIntegrationsManager = ({
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
|
||||
@@ -92,7 +92,7 @@ export const S3IntegrationsManager = ({
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
@@ -123,7 +123,7 @@ export const S3IntegrationsManager = ({
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
@@ -158,7 +158,7 @@ export const S3IntegrationsManager = ({
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
|
||||
@@ -93,7 +93,7 @@ export const SecurityHubIntegrationsManager = ({
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
@@ -125,7 +125,7 @@ export const SecurityHubIntegrationsManager = ({
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
@@ -176,7 +176,7 @@ export const SecurityHubIntegrationsManager = ({
|
||||
description: result.error,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
|
||||
@@ -80,7 +80,7 @@ export const SendInvitationForm = ({
|
||||
const invitationId = data?.data?.id || "";
|
||||
router.push(`/invitations/check-details/?id=${invitationId}`);
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
|
||||
@@ -268,7 +268,6 @@ export const VerticalSteps = React.forwardRef<
|
||||
"pointer-events-none absolute top-[calc(64px*var(--idx)+1)] left-3 flex h-1/2 -translate-y-1/3 items-center px-4",
|
||||
)}
|
||||
style={{
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
"--idx": stepIdx,
|
||||
}}
|
||||
|
||||
@@ -63,7 +63,6 @@ function InputGroupAddon({
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) {
|
||||
return (
|
||||
/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions */
|
||||
<div
|
||||
role="group"
|
||||
data-slot="input-group-addon"
|
||||
|
||||
@@ -723,7 +723,7 @@ export const PromptInput = ({
|
||||
controller.textInput.clear();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
// Don't clear on error - user may want to retry
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ export const LighthouseBanner = async () => {
|
||||
const isConfigured = await isLighthouseConfigured();
|
||||
|
||||
return <LighthouseBannerClient isConfigured={isConfigured} />;
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -95,7 +95,7 @@ export const AddGroupForm = ({
|
||||
description: "The group was created successfully.",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
|
||||
@@ -131,7 +131,7 @@ export const EditGroupForm = ({
|
||||
});
|
||||
router.push("/manage-groups");
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Error",
|
||||
|
||||
@@ -157,7 +157,6 @@ export const ConnectAccountForm = () => {
|
||||
router.push(`/providers/add-credentials?type=${providerType}&id=${id}`);
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Error during submission:", error);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
|
||||
@@ -153,7 +153,7 @@ export const TestConnectionForm = ({
|
||||
setIsRedirecting(true);
|
||||
router.push("/scans");
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
form.setError("providerId", {
|
||||
type: "server",
|
||||
message: "An unexpected error occurred. Please try again.",
|
||||
@@ -198,7 +198,6 @@ export const TestConnectionForm = ({
|
||||
`/providers/add-credentials?type=${providerType}&id=${providerId}`,
|
||||
);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Failed to delete credentials:", error);
|
||||
} finally {
|
||||
setIsResettingCredentials(false);
|
||||
|
||||
@@ -267,7 +267,6 @@ export const VerticalSteps = React.forwardRef<
|
||||
"pointer-events-none absolute top-[calc(64px*var(--idx)+1)] left-3 flex h-1/2 -translate-y-1/3 items-center px-4",
|
||||
)}
|
||||
style={{
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
"--idx": stepIdx,
|
||||
}}
|
||||
|
||||
@@ -268,7 +268,6 @@ export const VerticalSteps = React.forwardRef<
|
||||
"pointer-events-none absolute top-[calc(64px*var(--idx)+1)] left-3 flex h-1/2 -translate-y-1/3 items-center px-4",
|
||||
)}
|
||||
style={{
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
"--idx": stepIdx,
|
||||
}}
|
||||
|
||||
@@ -49,7 +49,6 @@ export const DataTableRowDetails = ({ entityId }: { entityId: string }) => {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Error in fetchScanDetails:", error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { cn } from "@/lib/utils";
|
||||
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "../tooltip";
|
||||
|
||||
const INFO_FIELD_VARIANTS = {
|
||||
export const INFO_FIELD_VARIANTS = {
|
||||
default: "default",
|
||||
simple: "simple",
|
||||
transparent: "transparent",
|
||||
|
||||
@@ -351,8 +351,7 @@ function getPayloadConfigFromPayload(
|
||||
}
|
||||
|
||||
return configLabelKey in config
|
||||
? // eslint-disable-next-line security/detect-object-injection
|
||||
config[configLabelKey]
|
||||
? config[configLabelKey]
|
||||
: config[key as keyof typeof config];
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ type ToasterToast = ToastProps & {
|
||||
action?: ToastActionElement;
|
||||
};
|
||||
|
||||
const actionTypes = {
|
||||
export const actionTypes = {
|
||||
ADD_TOAST: "ADD_TOAST",
|
||||
UPDATE_TOAST: "UPDATE_TOAST",
|
||||
DISMISS_TOAST: "DISMISS_TOAST",
|
||||
|
||||
@@ -15,6 +15,14 @@
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-12-15T08:24:46.195Z"
|
||||
},
|
||||
{
|
||||
"section": "dependencies",
|
||||
"name": "@extractus/feed-extractor",
|
||||
"from": "7.1.7",
|
||||
"to": "7.1.7",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2026-01-19T15:06:16.239Z"
|
||||
},
|
||||
{
|
||||
"section": "dependencies",
|
||||
"name": "@heroui/react",
|
||||
@@ -74,10 +82,10 @@
|
||||
{
|
||||
"section": "dependencies",
|
||||
"name": "@next/third-parties",
|
||||
"from": "15.3.5",
|
||||
"to": "15.5.9",
|
||||
"from": "15.5.9",
|
||||
"to": "16.1.3",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-12-15T11:18:25.093Z"
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "dependencies",
|
||||
@@ -458,10 +466,10 @@
|
||||
{
|
||||
"section": "dependencies",
|
||||
"name": "next",
|
||||
"from": "15.5.7",
|
||||
"to": "15.5.9",
|
||||
"from": "15.5.9",
|
||||
"to": "16.1.3",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-12-15T11:18:25.093Z"
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "dependencies",
|
||||
@@ -490,10 +498,10 @@
|
||||
{
|
||||
"section": "dependencies",
|
||||
"name": "react",
|
||||
"from": "19.2.1",
|
||||
"to": "19.2.2",
|
||||
"from": "19.2.2",
|
||||
"to": "19.2.3",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-12-15T11:18:25.093Z"
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "dependencies",
|
||||
@@ -506,10 +514,10 @@
|
||||
{
|
||||
"section": "dependencies",
|
||||
"name": "react-dom",
|
||||
"from": "19.2.1",
|
||||
"to": "19.2.2",
|
||||
"from": "19.2.2",
|
||||
"to": "19.2.3",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-12-15T11:18:25.093Z"
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "dependencies",
|
||||
@@ -543,14 +551,6 @@
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-12-16T08:33:37.278Z"
|
||||
},
|
||||
{
|
||||
"section": "dependencies",
|
||||
"name": "rss-parser",
|
||||
"from": "3.13.0",
|
||||
"to": "3.13.0",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-10-22T12:36:37.962Z"
|
||||
},
|
||||
{
|
||||
"section": "dependencies",
|
||||
"name": "server-only",
|
||||
@@ -663,6 +663,14 @@
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-10-22T12:36:37.962Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
"name": "@eslint/eslintrc",
|
||||
"from": "3.3.3",
|
||||
"to": "3.3.3",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
"name": "@iconify/react",
|
||||
@@ -671,6 +679,14 @@
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-10-22T12:36:37.962Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
"name": "@next/eslint-plugin-next",
|
||||
"from": "16.1.3",
|
||||
"to": "16.1.3",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2026-01-19T14:49:57.304Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
"name": "@playwright/test",
|
||||
@@ -707,17 +723,17 @@
|
||||
"section": "devDependencies",
|
||||
"name": "@types/react",
|
||||
"from": "19.1.13",
|
||||
"to": "19.1.13",
|
||||
"to": "19.2.8",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-10-22T12:36:37.962Z"
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
"name": "@types/react-dom",
|
||||
"from": "19.1.9",
|
||||
"to": "19.1.9",
|
||||
"to": "19.2.3",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-10-22T12:36:37.962Z"
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
@@ -747,17 +763,17 @@
|
||||
"section": "devDependencies",
|
||||
"name": "@typescript-eslint/eslint-plugin",
|
||||
"from": "7.18.0",
|
||||
"to": "7.18.0",
|
||||
"to": "8.53.0",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-10-22T12:36:37.962Z"
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
"name": "@typescript-eslint/parser",
|
||||
"from": "7.18.0",
|
||||
"to": "7.18.0",
|
||||
"to": "8.53.0",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-10-22T12:36:37.962Z"
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
@@ -771,9 +787,9 @@
|
||||
"section": "devDependencies",
|
||||
"name": "babel-plugin-react-compiler",
|
||||
"from": "19.1.0-rc.3",
|
||||
"to": "19.1.0-rc.3",
|
||||
"to": "1.0.0",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-10-22T12:36:37.962Z"
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
@@ -787,17 +803,17 @@
|
||||
"section": "devDependencies",
|
||||
"name": "eslint",
|
||||
"from": "8.57.1",
|
||||
"to": "8.57.1",
|
||||
"to": "9.39.2",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-10-22T12:36:37.962Z"
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
"name": "eslint-config-next",
|
||||
"from": "15.5.7",
|
||||
"to": "15.5.9",
|
||||
"from": "15.5.9",
|
||||
"to": "16.1.3",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-12-15T11:18:25.093Z"
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
@@ -875,9 +891,17 @@
|
||||
"section": "devDependencies",
|
||||
"name": "eslint-plugin-unused-imports",
|
||||
"from": "3.2.0",
|
||||
"to": "3.2.0",
|
||||
"to": "4.3.0",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2025-10-22T12:36:37.962Z"
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
"name": "globals",
|
||||
"from": "17.0.0",
|
||||
"to": "17.0.0",
|
||||
"strategy": "installed",
|
||||
"generatedAt": "2026-01-19T13:54:24.770Z"
|
||||
},
|
||||
{
|
||||
"section": "devDependencies",
|
||||
|
||||
135
ui/eslint.config.mjs
Normal file
135
ui/eslint.config.mjs
Normal file
@@ -0,0 +1,135 @@
|
||||
import { dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import tsPlugin from "@typescript-eslint/eslint-plugin";
|
||||
import tsParser from "@typescript-eslint/parser";
|
||||
import prettierPlugin from "eslint-plugin-prettier";
|
||||
import simpleImportSort from "eslint-plugin-simple-import-sort";
|
||||
import jsxA11y from "eslint-plugin-jsx-a11y";
|
||||
import security from "eslint-plugin-security";
|
||||
import unusedImports from "eslint-plugin-unused-imports";
|
||||
import nextPlugin from "@next/eslint-plugin-next";
|
||||
import reactPlugin from "eslint-plugin-react";
|
||||
import reactHooksPlugin from "eslint-plugin-react-hooks";
|
||||
import globals from "globals";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
export default [
|
||||
// Global ignores (replaces .eslintignore)
|
||||
{
|
||||
ignores: [
|
||||
".now/**",
|
||||
"**/*.css",
|
||||
".changeset/**",
|
||||
"dist/**",
|
||||
"esm/**",
|
||||
"public/**",
|
||||
"tests/**",
|
||||
"scripts/**",
|
||||
"*.config.js",
|
||||
"*.config.mjs",
|
||||
".DS_Store",
|
||||
"node_modules/**",
|
||||
"coverage/**",
|
||||
".next/**",
|
||||
"build/**",
|
||||
"next-env.d.ts",
|
||||
],
|
||||
},
|
||||
|
||||
// TypeScript and React files configuration
|
||||
{
|
||||
files: ["**/*.{ts,tsx,js,jsx}"],
|
||||
plugins: {
|
||||
"@typescript-eslint": tsPlugin,
|
||||
"@next/next": nextPlugin,
|
||||
react: reactPlugin,
|
||||
"react-hooks": reactHooksPlugin,
|
||||
prettier: prettierPlugin,
|
||||
"simple-import-sort": simpleImportSort,
|
||||
"jsx-a11y": jsxA11y,
|
||||
security: security,
|
||||
"unused-imports": unusedImports,
|
||||
},
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.node,
|
||||
...globals.es2021,
|
||||
React: "readonly",
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: "detect",
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// Console rules - allow console.error but no console.log
|
||||
"no-console": ["error", { allow: ["error"] }],
|
||||
eqeqeq: 2,
|
||||
quotes: ["error", "double", "avoid-escape"],
|
||||
|
||||
// TypeScript rules
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
argsIgnorePattern: "^_",
|
||||
varsIgnorePattern: "^_",
|
||||
caughtErrorsIgnorePattern: "^_",
|
||||
},
|
||||
],
|
||||
|
||||
// Security
|
||||
"security/detect-object-injection": "off",
|
||||
|
||||
// Prettier integration
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
endOfLine: "auto",
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
},
|
||||
],
|
||||
"eol-last": ["error", "always"],
|
||||
|
||||
// Import sorting
|
||||
"simple-import-sort/imports": "error",
|
||||
"simple-import-sort/exports": "error",
|
||||
|
||||
// Unused imports
|
||||
"unused-imports/no-unused-imports": "error",
|
||||
|
||||
// Accessibility
|
||||
"jsx-a11y/anchor-is-valid": [
|
||||
"error",
|
||||
{
|
||||
components: ["Link"],
|
||||
specialLink: ["hrefLeft", "hrefRight"],
|
||||
aspects: ["invalidHref", "preferButton"],
|
||||
},
|
||||
],
|
||||
"jsx-a11y/alt-text": "error",
|
||||
|
||||
// React Hooks
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "warn",
|
||||
|
||||
// Next.js specific rules
|
||||
"@next/next/no-html-link-for-pages": "error",
|
||||
"@next/next/no-img-element": "warn",
|
||||
"@next/next/no-sync-scripts": "error",
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -21,7 +21,6 @@ export const useLocalStorage = (
|
||||
setState(JSON.parse(value));
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error);
|
||||
}
|
||||
}, [key]);
|
||||
@@ -39,7 +38,6 @@ export const useLocalStorage = (
|
||||
window.localStorage.setItem(key, JSON.stringify(valueToStore));
|
||||
setState(valueToStore);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
startProgress,
|
||||
} from "@/components/ui/navigation-progress/use-navigation-progress";
|
||||
|
||||
const NAVIGATION_TYPE = {
|
||||
export const NAVIGATION_TYPE = {
|
||||
PUSH: "push",
|
||||
REPLACE: "replace",
|
||||
TRAVERSE: "traverse",
|
||||
|
||||
@@ -184,7 +184,7 @@ const downloadFile = async (
|
||||
title: "Download Complete",
|
||||
description: successMessage,
|
||||
});
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: "Download Failed",
|
||||
@@ -263,7 +263,6 @@ export const checkTaskStatus = async (
|
||||
const task = await getTask(taskId);
|
||||
|
||||
if (task.error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`Error retrieving task: ${task.error}`);
|
||||
return { completed: false, error: task.error };
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ function parseLineRange(lineRange: string): {
|
||||
|
||||
// Handle formats: "10-15", "10:15", "10"
|
||||
// Safe regex: anchored pattern for line numbers only (no ReDoS risk)
|
||||
// eslint-disable-next-line security/detect-unsafe-regex
|
||||
|
||||
const match = lineRange.match(/^(\d+)[-:]?(\d+)?$/);
|
||||
if (match) {
|
||||
const startLine = parseInt(match[1], 10);
|
||||
|
||||
@@ -106,7 +106,7 @@ export const runTestConnection = async ({
|
||||
config?.errorMessage || `Failed to connect to ${integrationType}.`;
|
||||
onError?.(pollResult.error || defaultError);
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
onError?.(
|
||||
"Failed to start connection test. You can try manually using the Test Connection button.",
|
||||
);
|
||||
|
||||
@@ -125,7 +125,7 @@ export const handleApiResponse = async (
|
||||
let data: any;
|
||||
try {
|
||||
data = JSON.parse(rawText);
|
||||
} catch (e) {
|
||||
} catch (_e) {
|
||||
// If body isn't valid JSON, return as text payload
|
||||
data = { data: rawText };
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ export const convertToYaml = (config: string | object): string => {
|
||||
// If it's not JSON, assume it's already YAML
|
||||
return config;
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
return config.toString();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -41,9 +41,8 @@ const nextConfig = {
|
||||
output: "standalone",
|
||||
outputFileTracingRoot: __dirname,
|
||||
}),
|
||||
experimental: {
|
||||
reactCompiler: true,
|
||||
},
|
||||
// React Compiler is now stable in Next.js 16
|
||||
reactCompiler: true,
|
||||
turbopack: {
|
||||
root: __dirname,
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "prowler-next-app",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack",
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"start:standalone": "node .next/standalone/server.js",
|
||||
@@ -10,8 +10,8 @@
|
||||
"postinstall": "node scripts/postinstall.js",
|
||||
"typecheck": "tsc",
|
||||
"healthcheck": "pnpm run typecheck && pnpm run lint:check",
|
||||
"lint:check": "eslint . --ext .ts,.tsx -c .eslintrc.cjs",
|
||||
"lint:fix": "eslint . --ext .ts,.tsx -c .eslintrc.cjs --fix",
|
||||
"lint:check": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"format:check": "./node_modules/.bin/prettier --check ./app",
|
||||
"format:write": "./node_modules/.bin/prettier --config .prettierrc.json --write ./app",
|
||||
"prepare": "husky",
|
||||
@@ -26,6 +26,7 @@
|
||||
"dependencies": {
|
||||
"@ai-sdk/react": "2.0.111",
|
||||
"@aws-sdk/client-bedrock-runtime": "3.948.0",
|
||||
"@extractus/feed-extractor": "7.1.7",
|
||||
"@heroui/react": "2.8.4",
|
||||
"@hookform/resolvers": "5.2.2",
|
||||
"@internationalized/date": "3.10.0",
|
||||
@@ -33,7 +34,7 @@
|
||||
"@langchain/core": "1.1.15",
|
||||
"@langchain/mcp-adapters": "1.0.3",
|
||||
"@langchain/openai": "1.1.3",
|
||||
"@next/third-parties": "15.5.9",
|
||||
"@next/third-parties": "16.1.3",
|
||||
"@radix-ui/react-alert-dialog": "1.1.14",
|
||||
"@radix-ui/react-avatar": "1.1.11",
|
||||
"@radix-ui/react-checkbox": "1.3.3",
|
||||
@@ -81,18 +82,17 @@
|
||||
"lucide-react": "0.543.0",
|
||||
"marked": "15.0.12",
|
||||
"nanoid": "5.1.6",
|
||||
"next": "15.5.9",
|
||||
"next": "16.1.3",
|
||||
"next-auth": "5.0.0-beta.30",
|
||||
"next-themes": "0.2.1",
|
||||
"radix-ui": "1.4.2",
|
||||
"react": "19.2.2",
|
||||
"react": "19.2.3",
|
||||
"react-day-picker": "9.13.0",
|
||||
"react-dom": "19.2.2",
|
||||
"react-dom": "19.2.3",
|
||||
"react-hook-form": "7.62.0",
|
||||
"react-markdown": "10.1.0",
|
||||
"recharts": "2.15.4",
|
||||
"require-in-the-middle": "8.0.1",
|
||||
"rss-parser": "3.13.0",
|
||||
"server-only": "0.0.1",
|
||||
"sharp": "0.33.5",
|
||||
"shiki": "3.20.0",
|
||||
@@ -109,23 +109,25 @@
|
||||
"zustand": "5.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "3.3.3",
|
||||
"@iconify/react": "5.2.1",
|
||||
"@next/eslint-plugin-next": "16.1.3",
|
||||
"@playwright/test": "1.56.1",
|
||||
"@types/d3": "7.4.3",
|
||||
"@types/geojson": "7946.0.16",
|
||||
"@types/node": "24.10.8",
|
||||
"@types/react": "19.1.13",
|
||||
"@types/react-dom": "19.1.9",
|
||||
"@types/react": "19.2.8",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"@types/topojson-client": "3.1.5",
|
||||
"@types/topojson-specification": "1.0.5",
|
||||
"@types/uuid": "10.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "7.18.0",
|
||||
"@typescript-eslint/parser": "7.18.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.53.0",
|
||||
"@typescript-eslint/parser": "8.53.0",
|
||||
"autoprefixer": "10.4.19",
|
||||
"babel-plugin-react-compiler": "19.1.0-rc.3",
|
||||
"babel-plugin-react-compiler": "1.0.0",
|
||||
"dotenv-expand": "12.0.3",
|
||||
"eslint": "8.57.1",
|
||||
"eslint-config-next": "15.5.9",
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-next": "16.1.3",
|
||||
"eslint-config-prettier": "10.1.5",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"eslint-plugin-jsx-a11y": "6.10.2",
|
||||
@@ -135,7 +137,8 @@
|
||||
"eslint-plugin-react-hooks": "7.0.1",
|
||||
"eslint-plugin-security": "3.0.1",
|
||||
"eslint-plugin-simple-import-sort": "12.1.1",
|
||||
"eslint-plugin-unused-imports": "3.2.0",
|
||||
"eslint-plugin-unused-imports": "4.3.0",
|
||||
"globals": "17.0.0",
|
||||
"husky": "9.1.7",
|
||||
"lint-staged": "15.5.2",
|
||||
"postcss": "8.4.38",
|
||||
@@ -150,12 +153,12 @@
|
||||
"overrides": {
|
||||
"@react-types/shared": "3.26.0",
|
||||
"@internationalized/date": "3.10.0",
|
||||
"alert>react": "19.2.2",
|
||||
"alert>react-dom": "19.2.2",
|
||||
"@react-aria/ssr>react": "19.2.2",
|
||||
"@react-aria/ssr>react-dom": "19.2.2",
|
||||
"@react-aria/visually-hidden>react": "19.2.2",
|
||||
"@react-aria/interactions>react": "19.2.2"
|
||||
"alert>react": "19.2.3",
|
||||
"alert>react-dom": "19.2.3",
|
||||
"@react-aria/ssr>react": "19.2.3",
|
||||
"@react-aria/ssr>react-dom": "19.2.3",
|
||||
"@react-aria/visually-hidden>react": "19.2.3",
|
||||
"@react-aria/interactions>react": "19.2.3"
|
||||
}
|
||||
},
|
||||
"version": "0.0.1"
|
||||
|
||||
8337
ui/pnpm-lock.yaml
generated
8337
ui/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,7 @@ const isPublicRoute = (pathname: string): boolean => {
|
||||
return publicRoutes.some((route) => pathname.startsWith(route));
|
||||
};
|
||||
|
||||
// NextAuth's auth() wrapper - renamed from middleware to proxy
|
||||
export default auth((req: NextRequest & { auth: any }) => {
|
||||
const { pathname } = req.nextUrl;
|
||||
const user = req.auth?.user;
|
||||
@@ -6,13 +6,19 @@
|
||||
"incremental": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"noEmit": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
"@/*": [
|
||||
"./*"
|
||||
]
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
@@ -24,12 +30,15 @@
|
||||
"strict": true,
|
||||
"target": "es5"
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
],
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
"images.d.ts"
|
||||
"images.d.ts",
|
||||
".next/dev/types/**/*.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ export interface AttackPathScansResponse {
|
||||
}
|
||||
|
||||
// Data type constants
|
||||
const DATA_TYPES = {
|
||||
export const DATA_TYPES = {
|
||||
STRING: "string",
|
||||
NUMBER: "number",
|
||||
BOOLEAN: "boolean",
|
||||
@@ -168,7 +168,7 @@ export interface AttackPathQueryResult {
|
||||
}
|
||||
|
||||
// Finding severity and status constants
|
||||
const FINDING_SEVERITIES = {
|
||||
export const FINDING_SEVERITIES = {
|
||||
CRITICAL: "critical",
|
||||
HIGH: "high",
|
||||
MEDIUM: "medium",
|
||||
@@ -179,7 +179,7 @@ const FINDING_SEVERITIES = {
|
||||
type FindingSeverity =
|
||||
(typeof FINDING_SEVERITIES)[keyof typeof FINDING_SEVERITIES];
|
||||
|
||||
const FINDING_STATUSES = {
|
||||
export const FINDING_STATUSES = {
|
||||
PASS: "PASS",
|
||||
FAIL: "FAIL",
|
||||
MANUAL: "MANUAL",
|
||||
|
||||
Reference in New Issue
Block a user